summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@nokia.com>2012-06-20 13:01:08 +0200
committerSimon Hausmann <simon.hausmann@nokia.com>2012-06-20 13:01:08 +0200
commit49233e234e5c787396cadb2cea33b31ae0cd65c1 (patch)
tree5410cb9a8fd53168bb60d62c54b654d86f03c38d /Source/JavaScriptCore
parentb211c645d8ab690f713515dfdc84d80b11c27d2c (diff)
downloadqtwebkit-49233e234e5c787396cadb2cea33b31ae0cd65c1.tar.gz
Imported WebKit commit 3a8c29f35d00659d2ce7a0ccdfa8304f14e82327 (http://svn.webkit.org/repository/webkit/trunk@120813)
New snapshot with Windows build fixes
Diffstat (limited to 'Source/JavaScriptCore')
-rw-r--r--Source/JavaScriptCore/CMakeLists.txt10
-rw-r--r--Source/JavaScriptCore/ChangeLog3140
-rw-r--r--Source/JavaScriptCore/Configurations/FeatureDefines.xcconfig6
-rw-r--r--Source/JavaScriptCore/DerivedSources.make6
-rw-r--r--Source/JavaScriptCore/GNUmakefile.am43
-rw-r--r--Source/JavaScriptCore/GNUmakefile.list.am58
-rw-r--r--Source/JavaScriptCore/JavaScriptCore.gyp/JavaScriptCore.gyp10
-rw-r--r--Source/JavaScriptCore/JavaScriptCore.gypi583
-rw-r--r--Source/JavaScriptCore/JavaScriptCore.pri1
-rwxr-xr-xSource/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def8
-rw-r--r--Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj52
-rw-r--r--Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreCommon.vsprops2
-rwxr-xr-xSource/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/copy-files.cmd1
-rw-r--r--Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj178
-rw-r--r--Source/JavaScriptCore/PlatformBlackBerry.cmake8
-rw-r--r--Source/JavaScriptCore/Target.pri8
-rw-r--r--Source/JavaScriptCore/assembler/ARMv7Assembler.h49
-rw-r--r--Source/JavaScriptCore/assembler/AbstractMacroAssembler.h24
-rw-r--r--Source/JavaScriptCore/assembler/AssemblerBuffer.h4
-rw-r--r--Source/JavaScriptCore/assembler/LinkBuffer.cpp231
-rw-r--r--Source/JavaScriptCore/assembler/LinkBuffer.h198
-rw-r--r--Source/JavaScriptCore/assembler/MacroAssemblerARM.h18
-rw-r--r--Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h24
-rw-r--r--Source/JavaScriptCore/assembler/MacroAssemblerCodeRef.h9
-rw-r--r--Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h18
-rw-r--r--Source/JavaScriptCore/assembler/MacroAssemblerSH4.h21
-rw-r--r--Source/JavaScriptCore/assembler/MacroAssemblerX86.h11
-rw-r--r--Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h10
-rw-r--r--Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h8
-rw-r--r--Source/JavaScriptCore/assembler/X86Assembler.h53
-rw-r--r--Source/JavaScriptCore/bytecode/CodeBlock.cpp51
-rw-r--r--Source/JavaScriptCore/bytecode/CodeBlock.h55
-rw-r--r--Source/JavaScriptCore/bytecode/DFGExitProfile.h8
-rw-r--r--Source/JavaScriptCore/bytecode/GetByIdStatus.cpp115
-rw-r--r--Source/JavaScriptCore/bytecode/GetByIdStatus.h18
-rw-r--r--Source/JavaScriptCore/bytecode/Instruction.h6
-rw-r--r--Source/JavaScriptCore/bytecode/LazyOperandValueProfile.cpp4
-rw-r--r--Source/JavaScriptCore/bytecode/LazyOperandValueProfile.h2
-rw-r--r--Source/JavaScriptCore/bytecode/Opcode.h2
-rw-r--r--Source/JavaScriptCore/bytecode/PredictedType.h279
-rw-r--r--Source/JavaScriptCore/bytecode/PutByIdStatus.cpp3
-rw-r--r--Source/JavaScriptCore/bytecode/SpeculatedType.cpp (renamed from Source/JavaScriptCore/bytecode/PredictedType.cpp)154
-rw-r--r--Source/JavaScriptCore/bytecode/SpeculatedType.h279
-rw-r--r--Source/JavaScriptCore/bytecode/StructureSet.h23
-rw-r--r--Source/JavaScriptCore/bytecode/StructureStubInfo.h10
-rw-r--r--Source/JavaScriptCore/bytecode/ValueProfile.h14
-rw-r--r--Source/JavaScriptCore/bytecode/Watchpoint.cpp127
-rw-r--r--Source/JavaScriptCore/bytecode/Watchpoint.h220
-rw-r--r--Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp104
-rw-r--r--Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h21
-rw-r--r--Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp18
-rw-r--r--Source/JavaScriptCore/debugger/Debugger.cpp2
-rw-r--r--Source/JavaScriptCore/dfg/DFGAbstractState.cpp614
-rw-r--r--Source/JavaScriptCore/dfg/DFGAbstractState.h32
-rw-r--r--Source/JavaScriptCore/dfg/DFGAbstractValue.h74
-rw-r--r--Source/JavaScriptCore/dfg/DFGArgumentPosition.h15
-rw-r--r--Source/JavaScriptCore/dfg/DFGArgumentsSimplificationPhase.cpp123
-rw-r--r--Source/JavaScriptCore/dfg/DFGAssemblyHelpers.h15
-rw-r--r--Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp319
-rw-r--r--Source/JavaScriptCore/dfg/DFGCCallHelpers.h28
-rw-r--r--Source/JavaScriptCore/dfg/DFGCFGSimplificationPhase.cpp61
-rw-r--r--Source/JavaScriptCore/dfg/DFGCSEPhase.cpp225
-rw-r--r--Source/JavaScriptCore/dfg/DFGCapabilities.h2
-rw-r--r--Source/JavaScriptCore/dfg/DFGCommon.h2
-rw-r--r--Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp48
-rw-r--r--Source/JavaScriptCore/dfg/DFGCorrectableJumpPoint.h5
-rw-r--r--Source/JavaScriptCore/dfg/DFGDriver.cpp6
-rw-r--r--Source/JavaScriptCore/dfg/DFGFixupPhase.cpp25
-rw-r--r--Source/JavaScriptCore/dfg/DFGGraph.cpp27
-rw-r--r--Source/JavaScriptCore/dfg/DFGGraph.h26
-rw-r--r--Source/JavaScriptCore/dfg/DFGJITCompiler.cpp34
-rw-r--r--Source/JavaScriptCore/dfg/DFGJITCompiler.h12
-rw-r--r--Source/JavaScriptCore/dfg/DFGNode.h111
-rw-r--r--Source/JavaScriptCore/dfg/DFGNodeType.h14
-rw-r--r--Source/JavaScriptCore/dfg/DFGOSRExit.cpp1
-rw-r--r--Source/JavaScriptCore/dfg/DFGOSRExit.h1
-rw-r--r--Source/JavaScriptCore/dfg/DFGOSRExitCompiler.cpp10
-rw-r--r--Source/JavaScriptCore/dfg/DFGOSRExitCompiler.h2
-rw-r--r--Source/JavaScriptCore/dfg/DFGOSRExitCompiler32_64.cpp148
-rw-r--r--Source/JavaScriptCore/dfg/DFGOSRExitCompiler64.cpp115
-rw-r--r--Source/JavaScriptCore/dfg/DFGOperations.cpp58
-rw-r--r--Source/JavaScriptCore/dfg/DFGOperations.h152
-rw-r--r--Source/JavaScriptCore/dfg/DFGPhase.cpp4
-rw-r--r--Source/JavaScriptCore/dfg/DFGPhase.h11
-rw-r--r--Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp187
-rw-r--r--Source/JavaScriptCore/dfg/DFGRepatch.cpp33
-rw-r--r--Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp190
-rw-r--r--Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h69
-rw-r--r--Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp328
-rw-r--r--Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp313
-rw-r--r--Source/JavaScriptCore/dfg/DFGThunks.cpp2
-rw-r--r--Source/JavaScriptCore/dfg/DFGVariableAccessData.h36
-rw-r--r--Source/JavaScriptCore/disassembler/Disassembler.h49
-rw-r--r--Source/JavaScriptCore/disassembler/UDis86Disassembler.cpp63
-rw-r--r--Source/JavaScriptCore/disassembler/udis86/differences.txt22
-rw-r--r--Source/JavaScriptCore/disassembler/udis86/itab.py354
-rw-r--r--Source/JavaScriptCore/disassembler/udis86/optable.xml8959
-rw-r--r--Source/JavaScriptCore/disassembler/udis86/ud_opcode.py235
-rw-r--r--Source/JavaScriptCore/disassembler/udis86/ud_optable.py103
-rw-r--r--Source/JavaScriptCore/disassembler/udis86/udis86.c183
-rw-r--r--Source/JavaScriptCore/disassembler/udis86/udis86.h33
-rw-r--r--Source/JavaScriptCore/disassembler/udis86/udis86_decode.c1142
-rw-r--r--Source/JavaScriptCore/disassembler/udis86/udis86_decode.h258
-rw-r--r--Source/JavaScriptCore/disassembler/udis86/udis86_extern.h88
-rw-r--r--Source/JavaScriptCore/disassembler/udis86/udis86_input.c263
-rw-r--r--Source/JavaScriptCore/disassembler/udis86/udis86_input.h67
-rw-r--r--Source/JavaScriptCore/disassembler/udis86/udis86_itab_holder.c34
-rw-r--r--Source/JavaScriptCore/disassembler/udis86/udis86_syn-att.c253
-rw-r--r--Source/JavaScriptCore/disassembler/udis86/udis86_syn-intel.c279
-rw-r--r--Source/JavaScriptCore/disassembler/udis86/udis86_syn.c87
-rw-r--r--Source/JavaScriptCore/disassembler/udis86/udis86_syn.h47
-rw-r--r--Source/JavaScriptCore/disassembler/udis86/udis86_types.h238
-rw-r--r--Source/JavaScriptCore/gyp/JavaScriptCore.gyp227
-rw-r--r--Source/JavaScriptCore/gyp/gtk.gyp18
-rw-r--r--Source/JavaScriptCore/heap/BlockAllocator.cpp13
-rw-r--r--Source/JavaScriptCore/heap/BlockAllocator.h20
-rw-r--r--Source/JavaScriptCore/heap/CopiedBlock.h33
-rw-r--r--Source/JavaScriptCore/heap/CopiedSpace.cpp43
-rw-r--r--Source/JavaScriptCore/heap/CopiedSpace.h21
-rw-r--r--Source/JavaScriptCore/heap/CopiedSpaceInlineMethods.h41
-rw-r--r--Source/JavaScriptCore/heap/Handle.h2
-rw-r--r--Source/JavaScriptCore/heap/Heap.cpp97
-rw-r--r--Source/JavaScriptCore/heap/Heap.h27
-rw-r--r--Source/JavaScriptCore/heap/HeapTimer.cpp71
-rw-r--r--Source/JavaScriptCore/heap/HeapTimer.h45
-rw-r--r--Source/JavaScriptCore/heap/IncrementalSweeper.cpp32
-rw-r--r--Source/JavaScriptCore/heap/IncrementalSweeper.h18
-rw-r--r--Source/JavaScriptCore/heap/ListableHandler.h10
-rw-r--r--Source/JavaScriptCore/heap/MarkStack.cpp142
-rw-r--r--Source/JavaScriptCore/heap/MarkStack.h77
-rw-r--r--Source/JavaScriptCore/heap/MarkedAllocator.cpp1
-rw-r--r--Source/JavaScriptCore/heap/MarkedBlock.cpp2
-rw-r--r--Source/JavaScriptCore/heap/MarkedBlock.h12
-rw-r--r--Source/JavaScriptCore/heap/MarkedSpace.cpp15
-rw-r--r--Source/JavaScriptCore/heap/MarkedSpace.h1
-rw-r--r--Source/JavaScriptCore/heap/SlotVisitor.h11
-rw-r--r--Source/JavaScriptCore/heap/Weak.h6
-rw-r--r--Source/JavaScriptCore/heap/WeakBlock.cpp3
-rw-r--r--Source/JavaScriptCore/heap/WeakSet.cpp14
-rw-r--r--Source/JavaScriptCore/heap/WeakSet.h2
-rw-r--r--Source/JavaScriptCore/interpreter/Interpreter.cpp122
-rw-r--r--Source/JavaScriptCore/jit/HostCallReturnValue.h4
-rw-r--r--Source/JavaScriptCore/jit/JIT.cpp14
-rw-r--r--Source/JavaScriptCore/jit/JIT.h5
-rw-r--r--Source/JavaScriptCore/jit/JITCode.h13
-rw-r--r--Source/JavaScriptCore/jit/JITOpcodes.cpp11
-rw-r--r--Source/JavaScriptCore/jit/JITOpcodes32_64.cpp14
-rw-r--r--Source/JavaScriptCore/jit/JITPropertyAccess.cpp80
-rw-r--r--Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp101
-rw-r--r--Source/JavaScriptCore/jit/JITStubs.cpp62
-rw-r--r--Source/JavaScriptCore/jit/JITStubs.h257
-rw-r--r--Source/JavaScriptCore/jit/SpecializedThunkJIT.h4
-rw-r--r--Source/JavaScriptCore/jit/ThunkGenerators.cpp66
-rw-r--r--Source/JavaScriptCore/llint/LLIntOfflineAsmConfig.h4
-rw-r--r--Source/JavaScriptCore/llint/LLIntSlowPaths.cpp64
-rw-r--r--Source/JavaScriptCore/llint/LLIntSlowPaths.h228
-rw-r--r--Source/JavaScriptCore/llint/LLIntThunks.cpp16
-rw-r--r--Source/JavaScriptCore/llint/LowLevelInterpreter.asm8
-rw-r--r--Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm48
-rw-r--r--Source/JavaScriptCore/llint/LowLevelInterpreter64.asm47
-rw-r--r--Source/JavaScriptCore/offlineasm/asm.rb2
-rw-r--r--Source/JavaScriptCore/profiler/Profiler.cpp7
-rw-r--r--Source/JavaScriptCore/profiler/Profiler.h6
-rw-r--r--Source/JavaScriptCore/runtime/Completion.cpp2
-rw-r--r--Source/JavaScriptCore/runtime/Executable.cpp65
-rw-r--r--Source/JavaScriptCore/runtime/Executable.h73
-rw-r--r--Source/JavaScriptCore/runtime/GCActivityCallback.cpp94
-rw-r--r--Source/JavaScriptCore/runtime/GCActivityCallback.h34
-rw-r--r--Source/JavaScriptCore/runtime/GCActivityCallbackBlackBerry.cpp58
-rw-r--r--Source/JavaScriptCore/runtime/GCActivityCallbackCF.cpp155
-rw-r--r--Source/JavaScriptCore/runtime/JSArray.cpp2
-rw-r--r--Source/JavaScriptCore/runtime/JSCell.cpp5
-rw-r--r--Source/JavaScriptCore/runtime/JSCell.h4
-rw-r--r--Source/JavaScriptCore/runtime/JSGlobalData.cpp15
-rw-r--r--Source/JavaScriptCore/runtime/JSGlobalData.h7
-rw-r--r--Source/JavaScriptCore/runtime/JSGlobalObject.cpp60
-rw-r--r--Source/JavaScriptCore/runtime/JSGlobalObject.h34
-rw-r--r--Source/JavaScriptCore/runtime/JSObject.cpp24
-rw-r--r--Source/JavaScriptCore/runtime/JSObject.h2
-rw-r--r--Source/JavaScriptCore/runtime/JSSegmentedVariableObject.cpp71
-rw-r--r--Source/JavaScriptCore/runtime/JSSegmentedVariableObject.h101
-rw-r--r--Source/JavaScriptCore/runtime/JSStaticScopeObject.cpp8
-rw-r--r--Source/JavaScriptCore/runtime/JSString.cpp13
-rw-r--r--Source/JavaScriptCore/runtime/JSString.h1
-rw-r--r--Source/JavaScriptCore/runtime/JSSymbolTableObject.cpp88
-rw-r--r--Source/JavaScriptCore/runtime/JSSymbolTableObject.h163
-rw-r--r--Source/JavaScriptCore/runtime/JSVariableObject.cpp61
-rw-r--r--Source/JavaScriptCore/runtime/JSVariableObject.h90
-rw-r--r--Source/JavaScriptCore/runtime/Lookup.h7
-rw-r--r--Source/JavaScriptCore/runtime/MathObject.cpp388
-rw-r--r--Source/JavaScriptCore/runtime/Options.cpp42
-rw-r--r--Source/JavaScriptCore/runtime/Options.h5
-rw-r--r--Source/JavaScriptCore/runtime/Structure.cpp4
-rw-r--r--Source/JavaScriptCore/runtime/Structure.h38
-rw-r--r--Source/JavaScriptCore/runtime/SymbolTable.cpp94
-rw-r--r--Source/JavaScriptCore/runtime/SymbolTable.h247
-rw-r--r--Source/JavaScriptCore/runtime/WriteBarrier.h3
-rw-r--r--Source/JavaScriptCore/shell/CMakeLists.txt4
-rw-r--r--Source/JavaScriptCore/yarr/YarrJIT.cpp8
199 files changed, 22630 insertions, 4169 deletions
diff --git a/Source/JavaScriptCore/CMakeLists.txt b/Source/JavaScriptCore/CMakeLists.txt
index dc00849e3..24e67b940 100644
--- a/Source/JavaScriptCore/CMakeLists.txt
+++ b/Source/JavaScriptCore/CMakeLists.txt
@@ -7,6 +7,7 @@ SET(JavaScriptCore_INCLUDE_DIRECTORIES
"${JAVASCRIPTCORE_DIR}/bytecode"
"${JAVASCRIPTCORE_DIR}/bytecompiler"
"${JAVASCRIPTCORE_DIR}/dfg"
+ "${JAVASCRIPTCORE_DIR}/disassembler"
"${JAVASCRIPTCORE_DIR}/heap"
"${JAVASCRIPTCORE_DIR}/debugger"
"${JAVASCRIPTCORE_DIR}/interpreter"
@@ -35,6 +36,8 @@ SET(JavaScriptCore_SOURCES
API/JSValueRef.cpp
API/JSWeakObjectMapRefPrivate.cpp
API/OpaqueJSString.cpp
+
+ assembler/LinkBuffer.cpp
bytecode/CallLinkInfo.cpp
bytecode/CallLinkStatus.cpp
@@ -49,10 +52,11 @@ SET(JavaScriptCore_SOURCES
bytecode/MethodOfGettingAValueProfile.cpp
bytecode/Opcode.cpp
bytecode/PolymorphicPutByIdList.cpp
- bytecode/PredictedType.cpp
+ bytecode/SpeculatedType.cpp
bytecode/PutByIdStatus.cpp
bytecode/SamplingTool.cpp
bytecode/StructureStubInfo.cpp
+ bytecode/Watchpoint.cpp
bytecompiler/BytecodeGenerator.cpp
bytecompiler/NodesCodegen.cpp
@@ -97,6 +101,7 @@ SET(JavaScriptCore_SOURCES
heap/HandleSet.cpp
heap/HandleStack.cpp
heap/Heap.cpp
+ heap/HeapTimer.cpp
heap/IncrementalSweeper.cpp
heap/MachineStackMarker.cpp
heap/MarkedAllocator.cpp
@@ -186,9 +191,11 @@ SET(JavaScriptCore_SOURCES
runtime/JSObject.cpp
runtime/JSONObject.cpp
runtime/JSPropertyNameIterator.cpp
+ runtime/JSSegmentedVariableObject.cpp
runtime/JSStaticScopeObject.cpp
runtime/JSString.cpp
runtime/JSStringJoiner.cpp
+ runtime/JSSymbolTableObject.cpp
runtime/JSValue.cpp
runtime/JSVariableObject.cpp
runtime/JSWrapperObject.cpp
@@ -229,6 +236,7 @@ SET(JavaScriptCore_SOURCES
runtime/StringRecursionChecker.cpp
runtime/Structure.cpp
runtime/StructureChain.cpp
+ runtime/SymbolTable.cpp
runtime/TimeoutChecker.cpp
runtime/UString.cpp
diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog
index 807d83297..aafc84dca 100644
--- a/Source/JavaScriptCore/ChangeLog
+++ b/Source/JavaScriptCore/ChangeLog
@@ -1,3 +1,3143 @@
+2012-06-19 Filip Pizlo <fpizlo@apple.com>
+
+ JSC should be able to show disassembly for all generated JIT code
+ https://bugs.webkit.org/show_bug.cgi?id=89536
+
+ Reviewed by Gavin Barraclough.
+
+ Now instead of doing linkBuffer.finalizeCode(), you do
+ FINALIZE_CODE(linkBuffer, (... explanation ...)). FINALIZE_CODE() then
+ prints your explanation and the disassembled code, if
+ Options::showDisassembly is set to true.
+
+ * CMakeLists.txt:
+ * GNUmakefile.list.am:
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * Target.pri:
+ * assembler/LinkBuffer.cpp: Added.
+ (JSC):
+ (JSC::LinkBuffer::finalizeCodeWithoutDisassembly):
+ (JSC::LinkBuffer::finalizeCodeWithDisassembly):
+ (JSC::LinkBuffer::linkCode):
+ (JSC::LinkBuffer::performFinalization):
+ (JSC::LinkBuffer::dumpLinkStatistics):
+ (JSC::LinkBuffer::dumpCode):
+ * assembler/LinkBuffer.h:
+ (LinkBuffer):
+ (JSC):
+ * assembler/MacroAssemblerCodeRef.h:
+ (JSC::MacroAssemblerCodeRef::tryToDisassemble):
+ (MacroAssemblerCodeRef):
+ * 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::emitPutReplaceStub):
+ (JSC::DFG::emitPutTransitionStub):
+ * dfg/DFGThunks.cpp:
+ (JSC::DFG::osrExitGenerationThunkGenerator):
+ * disassembler/Disassembler.h:
+ (JSC):
+ (JSC::tryToDisassemble):
+ * disassembler/UDis86Disassembler.cpp:
+ (JSC::tryToDisassemble):
+ * jit/JIT.cpp:
+ (JSC::JIT::privateCompile):
+ * jit/JITCode.h:
+ (JSC::JITCode::tryToDisassemble):
+ * 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/SpecializedThunkJIT.h:
+ (JSC::SpecializedThunkJIT::finalize):
+ * jit/ThunkGenerators.cpp:
+ (JSC::charCodeAtThunkGenerator):
+ (JSC::charAtThunkGenerator):
+ (JSC::fromCharCodeThunkGenerator):
+ (JSC::sqrtThunkGenerator):
+ (JSC::floorThunkGenerator):
+ (JSC::ceilThunkGenerator):
+ (JSC::roundThunkGenerator):
+ (JSC::expThunkGenerator):
+ (JSC::logThunkGenerator):
+ (JSC::absThunkGenerator):
+ (JSC::powThunkGenerator):
+ * llint/LLIntThunks.cpp:
+ (JSC::LLInt::generateThunkWithJumpTo):
+ (JSC::LLInt::functionForCallEntryThunkGenerator):
+ (JSC::LLInt::functionForConstructEntryThunkGenerator):
+ (JSC::LLInt::functionForCallArityCheckThunkGenerator):
+ (JSC::LLInt::functionForConstructArityCheckThunkGenerator):
+ (JSC::LLInt::evalEntryThunkGenerator):
+ (JSC::LLInt::programEntryThunkGenerator):
+ * runtime/Options.cpp:
+ (Options):
+ (JSC::Options::initializeOptions):
+ * runtime/Options.h:
+ (Options):
+ * yarr/YarrJIT.cpp:
+ (JSC::Yarr::YarrGenerator::compile):
+
+2012-06-19 Mark Hahnenberg <mhahnenberg@apple.com>
+
+ [Qt][Mac] REGRESSION(r120742): It broke the build
+ https://bugs.webkit.org/show_bug.cgi?id=89516
+
+ Reviewed by Geoffrey Garen.
+
+ Removing GCActivityCallbackCF.cpp because it doesn't mesh well with cross-platform
+ code on Darwin (e.g. Qt). We now use plain ol' vanilla ifdefs to handle platforms
+ without CF support. These if-defs will probably disappear in the future when we
+ use cross-platform timers in HeapTimer.
+
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * runtime/GCActivityCallback.cpp:
+ (JSC):
+ (JSC::DefaultGCActivityCallback::DefaultGCActivityCallback):
+ (JSC::DefaultGCActivityCallback::doWork):
+ (JSC::DefaultGCActivityCallback::scheduleTimer):
+ (JSC::DefaultGCActivityCallback::cancelTimer):
+ (JSC::DefaultGCActivityCallback::didAllocate):
+ (JSC::DefaultGCActivityCallback::willCollect):
+ (JSC::DefaultGCActivityCallback::cancel):
+ * runtime/GCActivityCallbackCF.cpp: Removed.
+
+2012-06-19 Filip Pizlo <fpizlo@apple.com>
+
+ DFG CFA forgets to notify subsequent phases of found constants if it proves LogicalNot to be a constant
+ https://bugs.webkit.org/show_bug.cgi?id=89511
+ <rdar://problem/11700089>
+
+ Reviewed by Geoffrey Garen.
+
+ * dfg/DFGAbstractState.cpp:
+ (JSC::DFG::AbstractState::execute):
+
+2012-06-19 Mark Lam <mark.lam@apple.com>
+
+ CodeBlock::needsCallReturnIndices() is no longer needed.
+ https://bugs.webkit.org/show_bug.cgi?id=89490
+
+ Reviewed by Geoffrey Garen.
+
+ * bytecode/CodeBlock.h:
+ (JSC::CodeBlock::needsCallReturnIndices): removed.
+ * dfg/DFGJITCompiler.cpp:
+ (JSC::DFG::JITCompiler::link):
+ * jit/JIT.cpp:
+ (JSC::JIT::privateCompile):
+
+2012-06-19 Filip Pizlo <fpizlo@apple.com>
+
+ Unreviewed, try to fix Windows build.
+
+ * JavaScriptCore.vcproj/JavaScriptCore/copy-files.cmd:
+
+2012-06-17 Filip Pizlo <fpizlo@apple.com>
+
+ It should be possible to look at disassembly
+ https://bugs.webkit.org/show_bug.cgi?id=89319
+
+ Reviewed by Sam Weinig.
+
+ This imports the udis86 disassembler library. The library is placed
+ behind an abstraction in disassembler/Disassembler.h, so that we can
+ in the future use other disassemblers (for other platforms) whenever
+ appropriate. As a first step, the disassembler is being invoked for
+ DFG verbose dumps.
+
+ If we ever want to merge a new version of udis86 in the future, I've
+ made notes about changes I made to the library in
+ disassembler/udis86/differences.txt.
+
+ * CMakeLists.txt:
+ * DerivedSources.make:
+ * GNUmakefile.list.am:
+ * JavaScriptCore.pri:
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreCommon.vsprops:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * dfg/DFGJITCompiler.cpp:
+ (JSC::DFG::JITCompiler::compile):
+ (JSC::DFG::JITCompiler::compileFunction):
+ * disassembler: Added.
+ * disassembler/Disassembler.h: Added.
+ (JSC):
+ (JSC::tryToDisassemble):
+ * disassembler/UDis86Disassembler.cpp: Added.
+ (JSC):
+ (JSC::tryToDisassemble):
+ * disassembler/udis86: Added.
+ * disassembler/udis86/differences.txt: Added.
+ * disassembler/udis86/itab.py: Added.
+ (UdItabGenerator):
+ (UdItabGenerator.__init__):
+ (UdItabGenerator.toGroupId):
+ (UdItabGenerator.genLookupTable):
+ (UdItabGenerator.genLookupTableList):
+ (UdItabGenerator.genInsnTable):
+ (genItabH):
+ (genItabH.UD_ITAB_H):
+ (genItabC):
+ (genItab):
+ (main):
+ * disassembler/udis86/optable.xml: Added.
+ * disassembler/udis86/ud_opcode.py: Added.
+ (UdOpcodeTables):
+ (UdOpcodeTables.sizeOfTable):
+ (UdOpcodeTables.nameOfTable):
+ (UdOpcodeTables.updateTable):
+ (UdOpcodeTables.Insn):
+ (UdOpcodeTables.Insn.__init__):
+ (UdOpcodeTables.Insn.__init__.opcode):
+ (UdOpcodeTables.parse):
+ (UdOpcodeTables.addInsnDef):
+ (UdOpcodeTables.print_table):
+ (UdOpcodeTables.print_tree):
+ * disassembler/udis86/ud_optable.py: Added.
+ (UdOptableXmlParser):
+ (UdOptableXmlParser.parseDef):
+ (UdOptableXmlParser.parse):
+ (printFn):
+ (parse):
+ (main):
+ * disassembler/udis86/udis86.c: Added.
+ (ud_init):
+ (ud_disassemble):
+ (ud_set_mode):
+ (ud_set_vendor):
+ (ud_set_pc):
+ (ud):
+ (ud_insn_asm):
+ (ud_insn_off):
+ (ud_insn_hex):
+ (ud_insn_ptr):
+ (ud_insn_len):
+ * disassembler/udis86/udis86.h: Added.
+ * disassembler/udis86/udis86_decode.c: Added.
+ (eff_adr_mode):
+ (ud_lookup_mnemonic):
+ (decode_prefixes):
+ (modrm):
+ (resolve_operand_size):
+ (resolve_mnemonic):
+ (decode_a):
+ (decode_gpr):
+ (resolve_gpr64):
+ (resolve_gpr32):
+ (resolve_reg):
+ (decode_imm):
+ (decode_modrm_reg):
+ (decode_modrm_rm):
+ (decode_o):
+ (decode_operand):
+ (decode_operands):
+ (clear_insn):
+ (resolve_mode):
+ (gen_hex):
+ (decode_insn):
+ (decode_3dnow):
+ (decode_ssepfx):
+ (decode_ext):
+ (decode_opcode):
+ (ud_decode):
+ * disassembler/udis86/udis86_decode.h: Added.
+ (ud_itab_entry_operand):
+ (ud_itab_entry):
+ (ud_lookup_table_list_entry):
+ (sse_pfx_idx):
+ (mode_idx):
+ (modrm_mod_idx):
+ (vendor_idx):
+ (is_group_ptr):
+ (group_idx):
+ * disassembler/udis86/udis86_extern.h: Added.
+ * disassembler/udis86/udis86_input.c: Added.
+ (inp_buff_hook):
+ (inp_file_hook):
+ (ud):
+ (ud_set_user_opaque_data):
+ (ud_get_user_opaque_data):
+ (ud_set_input_buffer):
+ (ud_set_input_file):
+ (ud_input_skip):
+ (ud_input_end):
+ (ud_inp_next):
+ (ud_inp_back):
+ (ud_inp_peek):
+ (ud_inp_move):
+ (ud_inp_uint8):
+ (ud_inp_uint16):
+ (ud_inp_uint32):
+ (ud_inp_uint64):
+ * disassembler/udis86/udis86_input.h: Added.
+ * disassembler/udis86/udis86_itab_holder.c: Added.
+ * disassembler/udis86/udis86_syn-att.c: Added.
+ (opr_cast):
+ (gen_operand):
+ (ud_translate_att):
+ * disassembler/udis86/udis86_syn-intel.c: Added.
+ (opr_cast):
+ (gen_operand):
+ (ud_translate_intel):
+ * disassembler/udis86/udis86_syn.c: Added.
+ * disassembler/udis86/udis86_syn.h: Added.
+ (mkasm):
+ * disassembler/udis86/udis86_types.h: Added.
+ (ud_operand):
+ (ud):
+ * jit/JITCode.h:
+ (JITCode):
+ (JSC::JITCode::tryToDisassemble):
+
+2012-06-19 Mark Hahnenberg <mhahnenberg@apple.com>
+
+ GCActivityCallback and IncrementalSweeper should share code
+ https://bugs.webkit.org/show_bug.cgi?id=89400
+
+ Reviewed by Geoffrey Garen.
+
+ A lot of functionality is duplicated between GCActivityCallback and IncrementalSweeper.
+ We should extract the common functionality out into a separate class that both of them
+ can inherit from. This refactoring will be an even greater boon when we add the ability
+ to shut these two agents down in a thread-safe fashion
+
+ * CMakeLists.txt:
+ * GNUmakefile.list.am:
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * Target.pri:
+ * heap/Heap.cpp:
+ (JSC::Heap::Heap): Move initialization down so that the JSGlobalData has a valid Heap when
+ we're initializing the GCActivityCallback and the IncrementalSweeper.
+ * heap/Heap.h:
+ (Heap):
+ * heap/HeapTimer.cpp: Added.
+ (JSC):
+ (JSC::HeapTimer::HeapTimer): Initialize the various base class data that
+ DefaultGCActivityCallback::commonConstructor() used to do.
+ (JSC::HeapTimer::~HeapTimer): Call to invalidate().
+ (JSC::HeapTimer::synchronize): Same functionality as the old DefaultGCActivityCallback::synchronize().
+ Virtual so that non-CF subclasses can override.
+ (JSC::HeapTimer::invalidate): Tears down the runloop timer to prevent any future firing.
+ (JSC::HeapTimer::timerDidFire): Callback to pass to the timer function. Casts and calls the virtual doWork().
+ * heap/HeapTimer.h: Added. This is the class that serves as the common base class for
+ both GCActivityCallback and IncrementalSweeper. It handles setting up and tearing down run loops and synchronizing
+ across threads for its subclasses.
+ (JSC):
+ (HeapTimer):
+ * heap/IncrementalSweeper.cpp: Changes to accomodate the extraction of common functionality
+ between IncrementalSweeper and GCActivityCallback into a common ancestor.
+ (JSC):
+ (JSC::IncrementalSweeper::doWork):
+ (JSC::IncrementalSweeper::IncrementalSweeper):
+ (JSC::IncrementalSweeper::cancelTimer):
+ (JSC::IncrementalSweeper::create):
+ * heap/IncrementalSweeper.h:
+ (IncrementalSweeper):
+ * runtime/GCActivityCallback.cpp:
+ (JSC::DefaultGCActivityCallback::DefaultGCActivityCallback):
+ (JSC::DefaultGCActivityCallback::doWork):
+ * runtime/GCActivityCallback.h:
+ (GCActivityCallback):
+ (JSC::GCActivityCallback::willCollect):
+ (JSC::GCActivityCallback::GCActivityCallback):
+ (JSC):
+ (DefaultGCActivityCallback): Remove the platform data struct. The platform data should be kept in
+ the class itself so as to be accessible by doWork(). Most of the platform data for CF is kept in
+ HeapTimer anyways, so we only need the m_delay field now.
+ * runtime/GCActivityCallbackBlackBerry.cpp:
+ (JSC):
+ (JSC::DefaultGCActivityCallback::DefaultGCActivityCallback):
+ (JSC::DefaultGCActivityCallback::doWork):
+ (JSC::DefaultGCActivityCallback::didAllocate):
+ * runtime/GCActivityCallbackCF.cpp:
+ (JSC):
+ (JSC::DefaultGCActivityCallback::DefaultGCActivityCallback):
+ (JSC::DefaultGCActivityCallback::doWork):
+ (JSC::DefaultGCActivityCallback::scheduleTimer):
+ (JSC::DefaultGCActivityCallback::cancelTimer):
+ (JSC::DefaultGCActivityCallback::didAllocate):
+ (JSC::DefaultGCActivityCallback::willCollect):
+ (JSC::DefaultGCActivityCallback::cancel):
+
+
+2012-06-19 Mike West <mkwst@chromium.org>
+
+ Introduce ENABLE_CSP_NEXT configuration flag.
+ https://bugs.webkit.org/show_bug.cgi?id=89300
+
+ Reviewed by Adam Barth.
+
+ The 1.0 draft of the Content Security Policy spec is just about to
+ move to Last Call. We'll hide work on the upcoming 1.1 spec behind
+ this ENABLE flag, disabled by default.
+
+ Spec: https://dvcs.w3.org/hg/content-security-policy/raw-file/tip/csp-specification.dev.html
+
+ * Configurations/FeatureDefines.xcconfig:
+
+2012-06-18 Mark Lam <mark.lam@apple.com>
+
+ Changed JSC to always record line number information so that error.stack
+ and window.onerror() can report proper line numbers.
+ https://bugs.webkit.org/show_bug.cgi?id=89410
+
+ Reviewed by Geoffrey Garen.
+
+ * bytecode/CodeBlock.cpp:
+ (JSC::CodeBlock::CodeBlock):
+ (JSC::CodeBlock::lineNumberForBytecodeOffset):
+ (JSC::CodeBlock::shrinkToFit): m_lineInfo is now available unconditionally.
+
+ * bytecode/CodeBlock.h:
+ (JSC::CodeBlock::addLineInfo):
+ (JSC::CodeBlock::hasLineInfo): Unused. Now removed.
+ (JSC::CodeBlock::needsCallReturnIndices):
+ (CodeBlock):
+ (RareData): Hoisted m_lineInfo out of m_rareData. m_lineInfo is now
+ filled in unconditionally.
+
+ * bytecompiler/BytecodeGenerator.h:
+ (JSC::BytecodeGenerator::addLineInfo):
+
+2012-06-18 Andy Estes <aestes@apple.com>
+
+ Fix r120663, which didn't land the change that was reviewed.
+
+2012-06-18 Andy Estes <aestes@apple.com>
+
+ [JSC] In JSGlobalData.cpp, enableAssembler() sometimes leaks two CF objects
+ https://bugs.webkit.org/show_bug.cgi?id=89415
+
+ Reviewed by Sam Weinig.
+
+ In the case where canUseJIT was a non-NULL CFBooleanRef,
+ enableAssembler() would leak both canUseJITKey and canUseJIT by
+ returning before calling CFRelease. Fix this by using RetainPtr.
+
+ * runtime/JSGlobalData.cpp:
+ (JSC::enableAssembler):
+
+2012-06-17 Geoffrey Garen <ggaren@apple.com>
+
+ GC copy phase spends needless cycles zero-filling blocks
+ https://bugs.webkit.org/show_bug.cgi?id=89128
+
+ Reviewed by Gavin Barraclough.
+
+ We only need to zero-fill when we're allocating memory that might not
+ get fully initialized before GC.
+
+ * heap/CopiedBlock.h:
+ (JSC::CopiedBlock::createNoZeroFill):
+ (JSC::CopiedBlock::create): Added a way to create without zero-filling.
+ This is our optimization.
+
+ (JSC::CopiedBlock::zeroFillToEnd):
+ (JSC::CopiedBlock::CopiedBlock): Split zero-filling out from creation,
+ so we can sometimes create without zero-filling.
+
+ * heap/CopiedSpace.cpp:
+ (JSC::CopiedSpace::init):
+ (JSC::CopiedSpace::tryAllocateSlowCase):
+ (JSC::CopiedSpace::doneCopying): Renamed addNewBlock to allocateBlock()
+ to clarify that the new block is always newly-allocated.
+
+ (JSC::CopiedSpace::doneFillingBlock): Make sure to zero-fill to the end
+ of a block that might be used in the future for allocation. (Most of the
+ time, this is a no-op, since we've already filled the block completely.)
+
+ (JSC::CopiedSpace::getFreshBlock): Removed this function because the
+ abstraction of "allocation must succeed" is no longer useful.
+
+ * heap/CopiedSpace.h: Updated declarations to match.
+
+ * heap/CopiedSpaceInlineMethods.h:
+ (JSC::CopiedSpace::allocateBlockForCopyingPhase): New function, which
+ knows that it can skip zero-filling.
+
+ Added tighter scoping to our lock, to improve parallelism.
+
+ (JSC::CopiedSpace::allocateBlock): Folded getFreshBlock functionality
+ into this function, for simplicity.
+
+ * heap/MarkStack.cpp:
+ (JSC::SlotVisitor::startCopying):
+ (JSC::SlotVisitor::allocateNewSpace): Use our new zero-fill-free helper
+ function for great good.
+
+2012-06-17 Filip Pizlo <fpizlo@apple.com>
+
+ DFG should attempt to use structure watchpoints for all inlined get_by_id's and put_by_id's
+ https://bugs.webkit.org/show_bug.cgi?id=89316
+
+ Reviewed by Oliver Hunt.
+
+ * dfg/DFGByteCodeParser.cpp:
+ (JSC::DFG::ByteCodeParser::addStructureTransitionCheck):
+ (ByteCodeParser):
+ (JSC::DFG::ByteCodeParser::handleGetById):
+ (JSC::DFG::ByteCodeParser::parseBlock):
+
+2012-06-15 Yong Li <yoli@rim.com>
+
+ [BlackBerry] Put platform-specific GC policy in GCActivityCallback
+ https://bugs.webkit.org/show_bug.cgi?id=89236
+
+ Reviewed by Rob Buis.
+
+ Add GCActivityCallbackBlackBerry.cpp and implement platform-specific
+ low memory GC policy there.
+
+ * PlatformBlackBerry.cmake:
+ * heap/Heap.h:
+ (JSC::Heap::isSafeToCollect): Added.
+ * runtime/GCActivityCallbackBlackBerry.cpp: Added.
+ (JSC):
+ (JSC::DefaultGCActivityCallbackPlatformData::DefaultGCActivityCallbackPlatformData):
+ (DefaultGCActivityCallbackPlatformData):
+ (JSC::DefaultGCActivityCallback::DefaultGCActivityCallback):
+ (JSC::DefaultGCActivityCallback::~DefaultGCActivityCallback):
+ (JSC::DefaultGCActivityCallback::didAllocate):
+ (JSC::DefaultGCActivityCallback::willCollect):
+ (JSC::DefaultGCActivityCallback::synchronize):
+ (JSC::DefaultGCActivityCallback::cancel):
+
+2012-06-15 Filip Pizlo <fpizlo@apple.com>
+
+ DFG should be able to set watchpoints on structure transitions in the
+ method check prototype chain
+ https://bugs.webkit.org/show_bug.cgi?id=89058
+
+ Adding the same assertion to 32-bit that I added to 64-bit. This change
+ does not affect correctness but it's a good thing for assertion coverage.
+
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+
+2012-06-13 Filip Pizlo <fpizlo@apple.com>
+
+ DFG should be able to set watchpoints on structure transitions in the
+ method check prototype chain
+ https://bugs.webkit.org/show_bug.cgi?id=89058
+
+ Reviewed by Gavin Barraclough.
+
+ This adds the ability to set watchpoints on Structures, and then does
+ the most modest thing we can do with this ability: the DFG now sets
+ watchpoints on structure transitions in the prototype chain of method
+ checks.
+
+ This appears to be a >1% speed-up on V8.
+
+ * bytecode/PutByIdStatus.cpp:
+ (JSC::PutByIdStatus::computeFromLLInt):
+ (JSC::PutByIdStatus::computeFor):
+ * bytecode/StructureSet.h:
+ (JSC::StructureSet::containsOnly):
+ (StructureSet):
+ * bytecode/Watchpoint.cpp:
+ (JSC::WatchpointSet::WatchpointSet):
+ (JSC::InlineWatchpointSet::add):
+ (JSC):
+ (JSC::InlineWatchpointSet::inflateSlow):
+ (JSC::InlineWatchpointSet::freeFat):
+ * bytecode/Watchpoint.h:
+ (WatchpointSet):
+ (JSC):
+ (InlineWatchpointSet):
+ (JSC::InlineWatchpointSet::InlineWatchpointSet):
+ (JSC::InlineWatchpointSet::~InlineWatchpointSet):
+ (JSC::InlineWatchpointSet::hasBeenInvalidated):
+ (JSC::InlineWatchpointSet::isStillValid):
+ (JSC::InlineWatchpointSet::startWatching):
+ (JSC::InlineWatchpointSet::notifyWrite):
+ (JSC::InlineWatchpointSet::isFat):
+ (JSC::InlineWatchpointSet::fat):
+ (JSC::InlineWatchpointSet::inflate):
+ * dfg/DFGAbstractState.cpp:
+ (JSC::DFG::AbstractState::execute):
+ * dfg/DFGByteCodeParser.cpp:
+ (JSC::DFG::ByteCodeParser::addStructureTransitionCheck):
+ (ByteCodeParser):
+ (JSC::DFG::ByteCodeParser::parseBlock):
+ * dfg/DFGCSEPhase.cpp:
+ (JSC::DFG::CSEPhase::structureTransitionWatchpointElimination):
+ (CSEPhase):
+ (JSC::DFG::CSEPhase::performNodeCSE):
+ * dfg/DFGCommon.h:
+ * dfg/DFGGraph.cpp:
+ (JSC::DFG::Graph::dump):
+ * dfg/DFGGraph.h:
+ (JSC::DFG::Graph::isCellConstant):
+ * dfg/DFGJITCompiler.h:
+ (JSC::DFG::JITCompiler::addWeakReferences):
+ (JITCompiler):
+ * dfg/DFGNode.h:
+ (JSC::DFG::Node::hasStructure):
+ (Node):
+ (JSC::DFG::Node::structure):
+ * dfg/DFGNodeType.h:
+ (DFG):
+ * dfg/DFGPredictionPropagationPhase.cpp:
+ (JSC::DFG::PredictionPropagationPhase::propagate):
+ * dfg/DFGRepatch.cpp:
+ (JSC::DFG::emitPutTransitionStub):
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * jit/JITStubs.cpp:
+ (JSC::JITThunks::tryCachePutByID):
+ * llint/LLIntSlowPaths.cpp:
+ (JSC::LLInt::LLINT_SLOW_PATH_DECL):
+ * runtime/Structure.cpp:
+ (JSC::Structure::Structure):
+ * runtime/Structure.h:
+ (JSC::Structure::transitionWatchpointSetHasBeenInvalidated):
+ (Structure):
+ (JSC::Structure::transitionWatchpointSetIsStillValid):
+ (JSC::Structure::addTransitionWatchpoint):
+ (JSC::Structure::notifyTransitionFromThisStructure):
+ (JSC::JSCell::setStructure):
+ * runtime/SymbolTable.cpp:
+ (JSC::SymbolTableEntry::attemptToWatch):
+
+2012-06-13 Filip Pizlo <fpizlo@apple.com>
+
+ DFG should be able to set watchpoints on global variables
+ https://bugs.webkit.org/show_bug.cgi?id=88692
+
+ Reviewed by Geoffrey Garen.
+
+ Rolling back in after fixing Windows build issues, and implementing
+ branchTest8 for the Qt port's strange assemblers.
+
+ This implements global variable constant folding by allowing the optimizing
+ compiler to set a "watchpoint" on globals that it wishes to constant fold.
+ If the watchpoint fires, then an OSR exit is forced by overwriting the
+ machine code that the optimizing compiler generated with a jump.
+
+ As such, this patch is adding quite a bit of stuff:
+
+ - Jump replacement on those hardware targets supported by the optimizing
+ JIT. It is now possible to patch in a jump instruction over any recorded
+ watchpoint label. The jump must be "local" in the sense that it must be
+ within the range of the largest jump distance supported by a one
+ instruction jump.
+
+ - WatchpointSets and Watchpoints. A Watchpoint is a doubly-linked list node
+ that records the location where a jump must be inserted and the
+ destination to which it should jump. Watchpoints can be added to a
+ WatchpointSet. The WatchpointSet can be fired all at once, which plants
+ all jumps. WatchpointSet also remembers if it had ever been invalidated,
+ which allows for monotonicity: we typically don't want to optimize using
+ watchpoints on something for which watchpoints had previously fired. The
+ act of notifying a WatchpointSet has a trivial fast path in case no
+ Watchpoints are registered (one-byte load+branch).
+
+ - SpeculativeJIT::speculationWatchpoint(). It's like speculationCheck(),
+ except that you don't have to emit branches. But, you need to know what
+ WatchpointSet to add the resulting Watchpoint to. Not everything that
+ you could write a speculationCheck() for will have a WatchpointSet that
+ would get notified if the condition you were speculating against became
+ invalid.
+
+ - SymbolTableEntry now has the ability to refer to a WatchpointSet. It can
+ do so without incurring any space overhead for those entries that don't
+ have WatchpointSets.
+
+ - The bytecode generator infers all global function variables to be
+ watchable, and makes all stores perform the WatchpointSet's write check,
+ and marks all loads as being potentially watchable (i.e. you can compile
+ them to a watchpoint and a constant).
+
+ Put together, this allows for fully sleazy inlining of calls to globally
+ declared functions. The inline prologue will no longer contain the load of
+ the function, or any checks of the function you're calling. I.e. it's
+ pretty much like the kind of inlining you would see in Java or C++.
+ Furthermore, the watchpointing functionality is built to be fairly general,
+ and should allow setting watchpoints on all sorts of interesting things
+ in the future.
+
+ The sleazy inlining means that we will now sometimes inline in code paths
+ that have never executed. Previously, to inline we would have either had
+ to have executed the call (to read the call's inline cache) or have
+ executed the method check (to read the method check's inline cache). Now,
+ we might inline when the callee is a watched global variable. This
+ revealed some humorous bugs. First, constant folding disagreed with CFA
+ over what kinds of operations can clobber (example: code path A is dead
+ but stores a String into variable X, all other code paths store 0 into
+ X, and then you do CompareEq(X, 0) - CFA will say that this is a non-
+ clobbering constant, but constant folding thought it was clobbering
+ because it saw the String prediction). Second, inlining would crash if
+ the inline callee had not been compiled. This patch fixes both bugs,
+ since otherwise run-javascriptcore-tests would report regressions.
+
+ * CMakeLists.txt:
+ * GNUmakefile.list.am:
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def:
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * Target.pri:
+ * assembler/ARMv7Assembler.h:
+ (ARMv7Assembler):
+ (JSC::ARMv7Assembler::ARMv7Assembler):
+ (JSC::ARMv7Assembler::labelForWatchpoint):
+ (JSC::ARMv7Assembler::label):
+ (JSC::ARMv7Assembler::replaceWithJump):
+ (JSC::ARMv7Assembler::maxJumpReplacementSize):
+ * assembler/AbstractMacroAssembler.h:
+ (JSC):
+ (AbstractMacroAssembler):
+ (Label):
+ (JSC::AbstractMacroAssembler::watchpointLabel):
+ (JSC::AbstractMacroAssembler::readPointer):
+ * assembler/AssemblerBuffer.h:
+ * assembler/MacroAssemblerARM.h:
+ (JSC::MacroAssemblerARM::branchTest8):
+ (MacroAssemblerARM):
+ (JSC::MacroAssemblerARM::replaceWithJump):
+ (JSC::MacroAssemblerARM::maxJumpReplacementSize):
+ * assembler/MacroAssemblerARMv7.h:
+ (JSC::MacroAssemblerARMv7::load8Signed):
+ (JSC::MacroAssemblerARMv7::load16Signed):
+ (MacroAssemblerARMv7):
+ (JSC::MacroAssemblerARMv7::replaceWithJump):
+ (JSC::MacroAssemblerARMv7::maxJumpReplacementSize):
+ (JSC::MacroAssemblerARMv7::branchTest8):
+ (JSC::MacroAssemblerARMv7::jump):
+ (JSC::MacroAssemblerARMv7::makeBranch):
+ * assembler/MacroAssemblerMIPS.h:
+ (JSC::MacroAssemblerMIPS::branchTest8):
+ (MacroAssemblerMIPS):
+ (JSC::MacroAssemblerMIPS::replaceWithJump):
+ (JSC::MacroAssemblerMIPS::maxJumpReplacementSize):
+ * assembler/MacroAssemblerSH4.h:
+ (JSC::MacroAssemblerSH4::branchTest8):
+ (MacroAssemblerSH4):
+ (JSC::MacroAssemblerSH4::replaceWithJump):
+ (JSC::MacroAssemblerSH4::maxJumpReplacementSize):
+ * assembler/MacroAssemblerX86.h:
+ (MacroAssemblerX86):
+ (JSC::MacroAssemblerX86::branchTest8):
+ * assembler/MacroAssemblerX86Common.h:
+ (JSC::MacroAssemblerX86Common::replaceWithJump):
+ (MacroAssemblerX86Common):
+ (JSC::MacroAssemblerX86Common::maxJumpReplacementSize):
+ * assembler/MacroAssemblerX86_64.h:
+ (MacroAssemblerX86_64):
+ (JSC::MacroAssemblerX86_64::branchTest8):
+ * assembler/X86Assembler.h:
+ (JSC::X86Assembler::X86Assembler):
+ (X86Assembler):
+ (JSC::X86Assembler::cmpb_im):
+ (JSC::X86Assembler::testb_im):
+ (JSC::X86Assembler::labelForWatchpoint):
+ (JSC::X86Assembler::label):
+ (JSC::X86Assembler::replaceWithJump):
+ (JSC::X86Assembler::maxJumpReplacementSize):
+ (JSC::X86Assembler::X86InstructionFormatter::memoryModRM):
+ * bytecode/CodeBlock.cpp:
+ (JSC):
+ (JSC::CodeBlock::printGetByIdCacheStatus):
+ (JSC::CodeBlock::dump):
+ * bytecode/CodeBlock.h:
+ (JSC::CodeBlock::appendOSRExit):
+ (JSC::CodeBlock::appendSpeculationRecovery):
+ (CodeBlock):
+ (JSC::CodeBlock::appendWatchpoint):
+ (JSC::CodeBlock::numberOfWatchpoints):
+ (JSC::CodeBlock::watchpoint):
+ (DFGData):
+ * bytecode/DFGExitProfile.h:
+ (JSC::DFG::exitKindToString):
+ (JSC::DFG::exitKindIsCountable):
+ * bytecode/GetByIdStatus.cpp:
+ (JSC::GetByIdStatus::computeForChain):
+ * bytecode/Instruction.h:
+ (Instruction):
+ (JSC::Instruction::Instruction):
+ * bytecode/Opcode.h:
+ (JSC):
+ (JSC::padOpcodeName):
+ * bytecode/Watchpoint.cpp: Added.
+ (JSC):
+ (JSC::Watchpoint::~Watchpoint):
+ (JSC::Watchpoint::correctLabels):
+ (JSC::Watchpoint::fire):
+ (JSC::WatchpointSet::WatchpointSet):
+ (JSC::WatchpointSet::~WatchpointSet):
+ (JSC::WatchpointSet::add):
+ (JSC::WatchpointSet::notifyWriteSlow):
+ (JSC::WatchpointSet::fireAllWatchpoints):
+ * bytecode/Watchpoint.h: Added.
+ (JSC):
+ (Watchpoint):
+ (JSC::Watchpoint::Watchpoint):
+ (JSC::Watchpoint::setDestination):
+ (WatchpointSet):
+ (JSC::WatchpointSet::isStillValid):
+ (JSC::WatchpointSet::hasBeenInvalidated):
+ (JSC::WatchpointSet::startWatching):
+ (JSC::WatchpointSet::notifyWrite):
+ (JSC::WatchpointSet::addressOfIsWatched):
+ * bytecompiler/BytecodeGenerator.cpp:
+ (JSC::ResolveResult::checkValidity):
+ (JSC::BytecodeGenerator::addGlobalVar):
+ (JSC::BytecodeGenerator::BytecodeGenerator):
+ (JSC::BytecodeGenerator::resolve):
+ (JSC::BytecodeGenerator::emitResolve):
+ (JSC::BytecodeGenerator::emitResolveWithBase):
+ (JSC::BytecodeGenerator::emitResolveWithThis):
+ (JSC::BytecodeGenerator::emitGetStaticVar):
+ (JSC::BytecodeGenerator::emitPutStaticVar):
+ * bytecompiler/BytecodeGenerator.h:
+ (BytecodeGenerator):
+ * bytecompiler/NodesCodegen.cpp:
+ (JSC::FunctionCallResolveNode::emitBytecode):
+ (JSC::PostfixResolveNode::emitBytecode):
+ (JSC::PrefixResolveNode::emitBytecode):
+ (JSC::ReadModifyResolveNode::emitBytecode):
+ (JSC::AssignResolveNode::emitBytecode):
+ (JSC::ConstDeclNode::emitCodeSingle):
+ * dfg/DFGAbstractState.cpp:
+ (JSC::DFG::AbstractState::execute):
+ (JSC::DFG::AbstractState::clobberStructures):
+ * dfg/DFGAbstractState.h:
+ (AbstractState):
+ (JSC::DFG::AbstractState::didClobber):
+ * dfg/DFGByteCodeParser.cpp:
+ (JSC::DFG::ByteCodeParser::handleInlining):
+ (JSC::DFG::ByteCodeParser::parseBlock):
+ * dfg/DFGCCallHelpers.h:
+ (CCallHelpers):
+ (JSC::DFG::CCallHelpers::setupArguments):
+ * dfg/DFGCSEPhase.cpp:
+ (JSC::DFG::CSEPhase::globalVarWatchpointElimination):
+ (CSEPhase):
+ (JSC::DFG::CSEPhase::globalVarStoreElimination):
+ (JSC::DFG::CSEPhase::performNodeCSE):
+ * dfg/DFGCapabilities.h:
+ (JSC::DFG::canCompileOpcode):
+ * dfg/DFGConstantFoldingPhase.cpp:
+ (JSC::DFG::ConstantFoldingPhase::run):
+ * dfg/DFGCorrectableJumpPoint.h:
+ (JSC::DFG::CorrectableJumpPoint::isSet):
+ (CorrectableJumpPoint):
+ * dfg/DFGJITCompiler.cpp:
+ (JSC::DFG::JITCompiler::linkOSRExits):
+ (JSC::DFG::JITCompiler::link):
+ * dfg/DFGNode.h:
+ (JSC::DFG::Node::hasIdentifierNumberForCheck):
+ (Node):
+ (JSC::DFG::Node::identifierNumberForCheck):
+ (JSC::DFG::Node::hasRegisterPointer):
+ * dfg/DFGNodeType.h:
+ (DFG):
+ * dfg/DFGOSRExit.cpp:
+ (JSC::DFG::OSRExit::OSRExit):
+ * dfg/DFGOSRExit.h:
+ (OSRExit):
+ * dfg/DFGOperations.cpp:
+ * dfg/DFGOperations.h:
+ * dfg/DFGPredictionPropagationPhase.cpp:
+ (JSC::DFG::PredictionPropagationPhase::propagate):
+ * dfg/DFGSpeculativeJIT.h:
+ (JSC::DFG::SpeculativeJIT::callOperation):
+ (JSC::DFG::SpeculativeJIT::appendCall):
+ (SpeculativeJIT):
+ (JSC::DFG::SpeculativeJIT::speculationWatchpoint):
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * interpreter/Interpreter.cpp:
+ (JSC::Interpreter::privateExecute):
+ * jit/JIT.cpp:
+ (JSC::JIT::privateCompileMainPass):
+ (JSC::JIT::privateCompileSlowCases):
+ * jit/JIT.h:
+ * jit/JITPropertyAccess.cpp:
+ (JSC::JIT::emit_op_put_global_var_check):
+ (JSC):
+ (JSC::JIT::emitSlow_op_put_global_var_check):
+ * jit/JITPropertyAccess32_64.cpp:
+ (JSC::JIT::emit_op_put_global_var_check):
+ (JSC):
+ (JSC::JIT::emitSlow_op_put_global_var_check):
+ * jit/JITStubs.cpp:
+ (JSC::DEFINE_STUB_FUNCTION):
+ (JSC):
+ * jit/JITStubs.h:
+ * llint/LLIntSlowPaths.cpp:
+ (JSC::LLInt::LLINT_SLOW_PATH_DECL):
+ (LLInt):
+ * llint/LLIntSlowPaths.h:
+ (LLInt):
+ * llint/LowLevelInterpreter32_64.asm:
+ * llint/LowLevelInterpreter64.asm:
+ * runtime/JSObject.cpp:
+ (JSC::JSObject::removeDirect):
+ * runtime/JSObject.h:
+ (JSObject):
+ * runtime/JSSymbolTableObject.h:
+ (JSC::symbolTableGet):
+ (JSC::symbolTablePut):
+ (JSC::symbolTablePutWithAttributes):
+ * runtime/SymbolTable.cpp: Added.
+ (JSC):
+ (JSC::SymbolTableEntry::copySlow):
+ (JSC::SymbolTableEntry::freeFatEntrySlow):
+ (JSC::SymbolTableEntry::couldBeWatched):
+ (JSC::SymbolTableEntry::attemptToWatch):
+ (JSC::SymbolTableEntry::addressOfIsWatched):
+ (JSC::SymbolTableEntry::addWatchpoint):
+ (JSC::SymbolTableEntry::notifyWriteSlow):
+ (JSC::SymbolTableEntry::inflateSlow):
+ * runtime/SymbolTable.h:
+ (JSC):
+ (SymbolTableEntry):
+ (Fast):
+ (JSC::SymbolTableEntry::Fast::Fast):
+ (JSC::SymbolTableEntry::Fast::isNull):
+ (JSC::SymbolTableEntry::Fast::getIndex):
+ (JSC::SymbolTableEntry::Fast::isReadOnly):
+ (JSC::SymbolTableEntry::Fast::getAttributes):
+ (JSC::SymbolTableEntry::Fast::isFat):
+ (JSC::SymbolTableEntry::SymbolTableEntry):
+ (JSC::SymbolTableEntry::~SymbolTableEntry):
+ (JSC::SymbolTableEntry::operator=):
+ (JSC::SymbolTableEntry::isNull):
+ (JSC::SymbolTableEntry::getIndex):
+ (JSC::SymbolTableEntry::getFast):
+ (JSC::SymbolTableEntry::getAttributes):
+ (JSC::SymbolTableEntry::isReadOnly):
+ (JSC::SymbolTableEntry::watchpointSet):
+ (JSC::SymbolTableEntry::notifyWrite):
+ (FatEntry):
+ (JSC::SymbolTableEntry::FatEntry::FatEntry):
+ (JSC::SymbolTableEntry::isFat):
+ (JSC::SymbolTableEntry::fatEntry):
+ (JSC::SymbolTableEntry::inflate):
+ (JSC::SymbolTableEntry::bits):
+ (JSC::SymbolTableEntry::freeFatEntry):
+ (JSC::SymbolTableEntry::pack):
+ (JSC::SymbolTableEntry::isValidIndex):
+
+2012-06-13 Sheriff Bot <webkit.review.bot@gmail.com>
+
+ Unreviewed, rolling out r120172.
+ http://trac.webkit.org/changeset/120172
+ https://bugs.webkit.org/show_bug.cgi?id=88976
+
+ The patch causes compilation failures on Gtk, Qt and Apple Win
+ bots (Requested by zdobersek on #webkit).
+
+ * CMakeLists.txt:
+ * GNUmakefile.list.am:
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def:
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * Target.pri:
+ * assembler/ARMv7Assembler.h:
+ (JSC::ARMv7Assembler::nop):
+ (JSC::ARMv7Assembler::label):
+ (JSC::ARMv7Assembler::readPointer):
+ (ARMv7Assembler):
+ * assembler/AbstractMacroAssembler.h:
+ (JSC):
+ (AbstractMacroAssembler):
+ (Label):
+ * assembler/AssemblerBuffer.h:
+ * assembler/MacroAssemblerARM.h:
+ * assembler/MacroAssemblerARMv7.h:
+ (JSC::MacroAssemblerARMv7::nop):
+ (JSC::MacroAssemblerARMv7::jump):
+ (JSC::MacroAssemblerARMv7::makeBranch):
+ * assembler/MacroAssemblerMIPS.h:
+ * assembler/MacroAssemblerSH4.h:
+ * assembler/MacroAssemblerX86.h:
+ (MacroAssemblerX86):
+ (JSC::MacroAssemblerX86::moveWithPatch):
+ * assembler/MacroAssemblerX86Common.h:
+ * assembler/MacroAssemblerX86_64.h:
+ (JSC::MacroAssemblerX86_64::branchTest8):
+ * assembler/X86Assembler.h:
+ (JSC::X86Assembler::cmpb_im):
+ (JSC::X86Assembler::codeSize):
+ (JSC::X86Assembler::label):
+ (JSC::X86Assembler::X86InstructionFormatter::memoryModRM):
+ * bytecode/CodeBlock.cpp:
+ (JSC::CodeBlock::dump):
+ * bytecode/CodeBlock.h:
+ (JSC::CodeBlock::appendOSRExit):
+ (JSC::CodeBlock::appendSpeculationRecovery):
+ (DFGData):
+ * bytecode/DFGExitProfile.h:
+ (JSC::DFG::exitKindToString):
+ (JSC::DFG::exitKindIsCountable):
+ * bytecode/Instruction.h:
+ * bytecode/Opcode.h:
+ (JSC):
+ (JSC::padOpcodeName):
+ * bytecode/Watchpoint.cpp: Removed.
+ * bytecode/Watchpoint.h: Removed.
+ * bytecompiler/BytecodeGenerator.cpp:
+ (JSC::ResolveResult::checkValidity):
+ (JSC::BytecodeGenerator::addGlobalVar):
+ (JSC::BytecodeGenerator::BytecodeGenerator):
+ (JSC::BytecodeGenerator::resolve):
+ (JSC::BytecodeGenerator::emitResolve):
+ (JSC::BytecodeGenerator::emitResolveWithBase):
+ (JSC::BytecodeGenerator::emitResolveWithThis):
+ (JSC::BytecodeGenerator::emitGetStaticVar):
+ (JSC::BytecodeGenerator::emitPutStaticVar):
+ * bytecompiler/BytecodeGenerator.h:
+ (BytecodeGenerator):
+ * bytecompiler/NodesCodegen.cpp:
+ (JSC::FunctionCallResolveNode::emitBytecode):
+ (JSC::PostfixResolveNode::emitBytecode):
+ (JSC::PrefixResolveNode::emitBytecode):
+ (JSC::ReadModifyResolveNode::emitBytecode):
+ (JSC::AssignResolveNode::emitBytecode):
+ (JSC::ConstDeclNode::emitCodeSingle):
+ * dfg/DFGAbstractState.cpp:
+ (JSC::DFG::AbstractState::execute):
+ (JSC::DFG::AbstractState::clobberStructures):
+ * dfg/DFGAbstractState.h:
+ (AbstractState):
+ * dfg/DFGByteCodeParser.cpp:
+ (JSC::DFG::ByteCodeParser::handleInlining):
+ (JSC::DFG::ByteCodeParser::parseBlock):
+ * dfg/DFGCCallHelpers.h:
+ (JSC::DFG::CCallHelpers::setupArguments):
+ * dfg/DFGCSEPhase.cpp:
+ (JSC::DFG::CSEPhase::globalVarStoreElimination):
+ (JSC::DFG::CSEPhase::performNodeCSE):
+ * dfg/DFGCapabilities.h:
+ (JSC::DFG::canCompileOpcode):
+ * dfg/DFGConstantFoldingPhase.cpp:
+ (JSC::DFG::ConstantFoldingPhase::run):
+ * dfg/DFGCorrectableJumpPoint.h:
+ * dfg/DFGJITCompiler.cpp:
+ (JSC::DFG::JITCompiler::linkOSRExits):
+ (JSC::DFG::JITCompiler::link):
+ * dfg/DFGNode.h:
+ (JSC::DFG::Node::hasRegisterPointer):
+ * dfg/DFGNodeType.h:
+ (DFG):
+ * dfg/DFGOSRExit.cpp:
+ (JSC::DFG::OSRExit::OSRExit):
+ * dfg/DFGOSRExit.h:
+ (OSRExit):
+ * dfg/DFGOperations.cpp:
+ * dfg/DFGOperations.h:
+ * dfg/DFGPredictionPropagationPhase.cpp:
+ (JSC::DFG::PredictionPropagationPhase::propagate):
+ * dfg/DFGSpeculativeJIT.h:
+ (JSC::DFG::SpeculativeJIT::callOperation):
+ (JSC::DFG::SpeculativeJIT::appendCallSetResult):
+ (JSC::DFG::SpeculativeJIT::speculationCheck):
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * jit/JIT.cpp:
+ (JSC::JIT::privateCompileMainPass):
+ (JSC::JIT::privateCompileSlowCases):
+ * jit/JIT.h:
+ * jit/JITPropertyAccess.cpp:
+ * jit/JITPropertyAccess32_64.cpp:
+ * jit/JITStubs.cpp:
+ * jit/JITStubs.h:
+ * llint/LLIntSlowPaths.cpp:
+ * llint/LLIntSlowPaths.h:
+ (LLInt):
+ * llint/LowLevelInterpreter32_64.asm:
+ * llint/LowLevelInterpreter64.asm:
+ * runtime/JSObject.cpp:
+ (JSC::JSObject::removeDirect):
+ * runtime/JSObject.h:
+ (JSObject):
+ * runtime/JSSymbolTableObject.h:
+ (JSC::symbolTableGet):
+ (JSC::symbolTablePut):
+ (JSC::symbolTablePutWithAttributes):
+ * runtime/SymbolTable.cpp: Removed.
+ * runtime/SymbolTable.h:
+ (JSC):
+ (JSC::SymbolTableEntry::isNull):
+ (JSC::SymbolTableEntry::getIndex):
+ (SymbolTableEntry):
+ (JSC::SymbolTableEntry::getAttributes):
+ (JSC::SymbolTableEntry::isReadOnly):
+ (JSC::SymbolTableEntry::pack):
+ (JSC::SymbolTableEntry::isValidIndex):
+
+2012-06-12 Filip Pizlo <fpizlo@apple.com>
+
+ DFG should be able to set watchpoints on global variables
+ https://bugs.webkit.org/show_bug.cgi?id=88692
+
+ Reviewed by Geoffrey Garen.
+
+ This implements global variable constant folding by allowing the optimizing
+ compiler to set a "watchpoint" on globals that it wishes to constant fold.
+ If the watchpoint fires, then an OSR exit is forced by overwriting the
+ machine code that the optimizing compiler generated with a jump.
+
+ As such, this patch is adding quite a bit of stuff:
+
+ - Jump replacement on those hardware targets supported by the optimizing
+ JIT. It is now possible to patch in a jump instruction over any recorded
+ watchpoint label. The jump must be "local" in the sense that it must be
+ within the range of the largest jump distance supported by a one
+ instruction jump.
+
+ - WatchpointSets and Watchpoints. A Watchpoint is a doubly-linked list node
+ that records the location where a jump must be inserted and the
+ destination to which it should jump. Watchpoints can be added to a
+ WatchpointSet. The WatchpointSet can be fired all at once, which plants
+ all jumps. WatchpointSet also remembers if it had ever been invalidated,
+ which allows for monotonicity: we typically don't want to optimize using
+ watchpoints on something for which watchpoints had previously fired. The
+ act of notifying a WatchpointSet has a trivial fast path in case no
+ Watchpoints are registered (one-byte load+branch).
+
+ - SpeculativeJIT::speculationWatchpoint(). It's like speculationCheck(),
+ except that you don't have to emit branches. But, you need to know what
+ WatchpointSet to add the resulting Watchpoint to. Not everything that
+ you could write a speculationCheck() for will have a WatchpointSet that
+ would get notified if the condition you were speculating against became
+ invalid.
+
+ - SymbolTableEntry now has the ability to refer to a WatchpointSet. It can
+ do so without incurring any space overhead for those entries that don't
+ have WatchpointSets.
+
+ - The bytecode generator infers all global function variables to be
+ watchable, and makes all stores perform the WatchpointSet's write check,
+ and marks all loads as being potentially watchable (i.e. you can compile
+ them to a watchpoint and a constant).
+
+ Put together, this allows for fully sleazy inlining of calls to globally
+ declared functions. The inline prologue will no longer contain the load of
+ the function, or any checks of the function you're calling. I.e. it's
+ pretty much like the kind of inlining you would see in Java or C++.
+ Furthermore, the watchpointing functionality is built to be fairly general,
+ and should allow setting watchpoints on all sorts of interesting things
+ in the future.
+
+ The sleazy inlining means that we will now sometimes inline in code paths
+ that have never executed. Previously, to inline we would have either had
+ to have executed the call (to read the call's inline cache) or have
+ executed the method check (to read the method check's inline cache). Now,
+ we might inline when the callee is a watched global variable. This
+ revealed some humorous bugs. First, constant folding disagreed with CFA
+ over what kinds of operations can clobber (example: code path A is dead
+ but stores a String into variable X, all other code paths store 0 into
+ X, and then you do CompareEq(X, 0) - CFA will say that this is a non-
+ clobbering constant, but constant folding thought it was clobbering
+ because it saw the String prediction). Second, inlining would crash if
+ the inline callee had not been compiled. This patch fixes both bugs,
+ since otherwise run-javascriptcore-tests would report regressions.
+
+ * CMakeLists.txt:
+ * GNUmakefile.list.am:
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * Target.pri:
+ * assembler/ARMv7Assembler.h:
+ (ARMv7Assembler):
+ (JSC::ARMv7Assembler::ARMv7Assembler):
+ (JSC::ARMv7Assembler::labelForWatchpoint):
+ (JSC::ARMv7Assembler::label):
+ (JSC::ARMv7Assembler::replaceWithJump):
+ (JSC::ARMv7Assembler::maxJumpReplacementSize):
+ * assembler/AbstractMacroAssembler.h:
+ (JSC):
+ (AbstractMacroAssembler):
+ (Label):
+ (JSC::AbstractMacroAssembler::watchpointLabel):
+ * assembler/AssemblerBuffer.h:
+ * assembler/MacroAssemblerARM.h:
+ (JSC::MacroAssemblerARM::replaceWithJump):
+ (MacroAssemblerARM):
+ (JSC::MacroAssemblerARM::maxJumpReplacementSize):
+ * assembler/MacroAssemblerARMv7.h:
+ (MacroAssemblerARMv7):
+ (JSC::MacroAssemblerARMv7::replaceWithJump):
+ (JSC::MacroAssemblerARMv7::maxJumpReplacementSize):
+ (JSC::MacroAssemblerARMv7::branchTest8):
+ (JSC::MacroAssemblerARMv7::jump):
+ (JSC::MacroAssemblerARMv7::makeBranch):
+ * assembler/MacroAssemblerMIPS.h:
+ (JSC::MacroAssemblerMIPS::replaceWithJump):
+ (MacroAssemblerMIPS):
+ (JSC::MacroAssemblerMIPS::maxJumpReplacementSize):
+ * assembler/MacroAssemblerSH4.h:
+ (JSC::MacroAssemblerSH4::replaceWithJump):
+ (MacroAssemblerSH4):
+ (JSC::MacroAssemblerSH4::maxJumpReplacementSize):
+ * assembler/MacroAssemblerX86.h:
+ (MacroAssemblerX86):
+ (JSC::MacroAssemblerX86::branchTest8):
+ * assembler/MacroAssemblerX86Common.h:
+ (JSC::MacroAssemblerX86Common::replaceWithJump):
+ (MacroAssemblerX86Common):
+ (JSC::MacroAssemblerX86Common::maxJumpReplacementSize):
+ * assembler/MacroAssemblerX86_64.h:
+ (MacroAssemblerX86_64):
+ (JSC::MacroAssemblerX86_64::branchTest8):
+ * assembler/X86Assembler.h:
+ (JSC::X86Assembler::X86Assembler):
+ (X86Assembler):
+ (JSC::X86Assembler::cmpb_im):
+ (JSC::X86Assembler::testb_im):
+ (JSC::X86Assembler::labelForWatchpoint):
+ (JSC::X86Assembler::label):
+ (JSC::X86Assembler::replaceWithJump):
+ (JSC::X86Assembler::maxJumpReplacementSize):
+ (JSC::X86Assembler::X86InstructionFormatter::memoryModRM):
+ * bytecode/CodeBlock.cpp:
+ (JSC::CodeBlock::dump):
+ * bytecode/CodeBlock.h:
+ (JSC::CodeBlock::appendOSRExit):
+ (JSC::CodeBlock::appendSpeculationRecovery):
+ (CodeBlock):
+ (JSC::CodeBlock::appendWatchpoint):
+ (JSC::CodeBlock::numberOfWatchpoints):
+ (JSC::CodeBlock::watchpoint):
+ (DFGData):
+ * bytecode/DFGExitProfile.h:
+ (JSC::DFG::exitKindToString):
+ (JSC::DFG::exitKindIsCountable):
+ * bytecode/Instruction.h:
+ (Instruction):
+ (JSC::Instruction::Instruction):
+ * bytecode/Opcode.h:
+ (JSC):
+ (JSC::padOpcodeName):
+ * bytecode/Watchpoint.cpp: Added.
+ (JSC):
+ (JSC::Watchpoint::~Watchpoint):
+ (JSC::Watchpoint::correctLabels):
+ (JSC::Watchpoint::fire):
+ (JSC::WatchpointSet::WatchpointSet):
+ (JSC::WatchpointSet::~WatchpointSet):
+ (JSC::WatchpointSet::add):
+ (JSC::WatchpointSet::notifyWriteSlow):
+ (JSC::WatchpointSet::fireAllWatchpoints):
+ * bytecode/Watchpoint.h: Added.
+ (JSC):
+ (Watchpoint):
+ (JSC::Watchpoint::Watchpoint):
+ (JSC::Watchpoint::setDestination):
+ (WatchpointSet):
+ (JSC::WatchpointSet::isStillValid):
+ (JSC::WatchpointSet::hasBeenInvalidated):
+ (JSC::WatchpointSet::startWatching):
+ (JSC::WatchpointSet::notifyWrite):
+ (JSC::WatchpointSet::addressOfIsWatched):
+ * bytecompiler/BytecodeGenerator.cpp:
+ (JSC::ResolveResult::checkValidity):
+ (JSC::BytecodeGenerator::addGlobalVar):
+ (JSC::BytecodeGenerator::BytecodeGenerator):
+ (JSC::BytecodeGenerator::resolve):
+ (JSC::BytecodeGenerator::emitResolve):
+ (JSC::BytecodeGenerator::emitResolveWithBase):
+ (JSC::BytecodeGenerator::emitResolveWithThis):
+ (JSC::BytecodeGenerator::emitGetStaticVar):
+ (JSC::BytecodeGenerator::emitPutStaticVar):
+ * bytecompiler/BytecodeGenerator.h:
+ (BytecodeGenerator):
+ * bytecompiler/NodesCodegen.cpp:
+ (JSC::FunctionCallResolveNode::emitBytecode):
+ (JSC::PostfixResolveNode::emitBytecode):
+ (JSC::PrefixResolveNode::emitBytecode):
+ (JSC::ReadModifyResolveNode::emitBytecode):
+ (JSC::AssignResolveNode::emitBytecode):
+ (JSC::ConstDeclNode::emitCodeSingle):
+ * dfg/DFGAbstractState.cpp:
+ (JSC::DFG::AbstractState::execute):
+ (JSC::DFG::AbstractState::clobberStructures):
+ * dfg/DFGAbstractState.h:
+ (AbstractState):
+ (JSC::DFG::AbstractState::didClobber):
+ * dfg/DFGByteCodeParser.cpp:
+ (JSC::DFG::ByteCodeParser::handleInlining):
+ (JSC::DFG::ByteCodeParser::parseBlock):
+ * dfg/DFGCCallHelpers.h:
+ (CCallHelpers):
+ (JSC::DFG::CCallHelpers::setupArguments):
+ * dfg/DFGCSEPhase.cpp:
+ (JSC::DFG::CSEPhase::globalVarWatchpointElimination):
+ (CSEPhase):
+ (JSC::DFG::CSEPhase::globalVarStoreElimination):
+ (JSC::DFG::CSEPhase::performNodeCSE):
+ * dfg/DFGCapabilities.h:
+ (JSC::DFG::canCompileOpcode):
+ * dfg/DFGConstantFoldingPhase.cpp:
+ (JSC::DFG::ConstantFoldingPhase::run):
+ * dfg/DFGCorrectableJumpPoint.h:
+ (JSC::DFG::CorrectableJumpPoint::isSet):
+ (CorrectableJumpPoint):
+ * dfg/DFGJITCompiler.cpp:
+ (JSC::DFG::JITCompiler::linkOSRExits):
+ (JSC::DFG::JITCompiler::link):
+ * dfg/DFGNode.h:
+ (JSC::DFG::Node::hasIdentifierNumberForCheck):
+ (Node):
+ (JSC::DFG::Node::identifierNumberForCheck):
+ (JSC::DFG::Node::hasRegisterPointer):
+ * dfg/DFGNodeType.h:
+ (DFG):
+ * dfg/DFGOSRExit.cpp:
+ (JSC::DFG::OSRExit::OSRExit):
+ * dfg/DFGOSRExit.h:
+ (OSRExit):
+ * dfg/DFGOperations.cpp:
+ * dfg/DFGOperations.h:
+ * dfg/DFGPredictionPropagationPhase.cpp:
+ (JSC::DFG::PredictionPropagationPhase::propagate):
+ * dfg/DFGSpeculativeJIT.h:
+ (JSC::DFG::SpeculativeJIT::callOperation):
+ (JSC::DFG::SpeculativeJIT::appendCall):
+ (SpeculativeJIT):
+ (JSC::DFG::SpeculativeJIT::speculationWatchpoint):
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * jit/JIT.cpp:
+ (JSC::JIT::privateCompileMainPass):
+ (JSC::JIT::privateCompileSlowCases):
+ * jit/JIT.h:
+ * jit/JITPropertyAccess.cpp:
+ (JSC::JIT::emit_op_put_global_var_check):
+ (JSC):
+ (JSC::JIT::emitSlow_op_put_global_var_check):
+ * jit/JITPropertyAccess32_64.cpp:
+ (JSC::JIT::emit_op_put_global_var_check):
+ (JSC):
+ (JSC::JIT::emitSlow_op_put_global_var_check):
+ * jit/JITStubs.cpp:
+ (JSC::JITThunks::JITThunks):
+ (JSC::DEFINE_STUB_FUNCTION):
+ (JSC):
+ * jit/JITStubs.h:
+ * llint/LLIntSlowPaths.cpp:
+ (JSC::LLInt::LLINT_SLOW_PATH_DECL):
+ (LLInt):
+ * llint/LLIntSlowPaths.h:
+ (LLInt):
+ * llint/LowLevelInterpreter32_64.asm:
+ * llint/LowLevelInterpreter64.asm:
+ * runtime/JSObject.cpp:
+ (JSC::JSObject::removeDirect):
+ * runtime/JSObject.h:
+ (JSObject):
+ * runtime/JSSymbolTableObject.h:
+ (JSC::symbolTableGet):
+ (JSC::symbolTablePut):
+ (JSC::symbolTablePutWithAttributes):
+ * runtime/SymbolTable.cpp: Added.
+ (JSC):
+ (JSC::SymbolTableEntry::copySlow):
+ (JSC::SymbolTableEntry::freeFatEntrySlow):
+ (JSC::SymbolTableEntry::couldBeWatched):
+ (JSC::SymbolTableEntry::attemptToWatch):
+ (JSC::SymbolTableEntry::addressOfIsWatched):
+ (JSC::SymbolTableEntry::addWatchpoint):
+ (JSC::SymbolTableEntry::notifyWriteSlow):
+ (JSC::SymbolTableEntry::inflateSlow):
+ * runtime/SymbolTable.h:
+ (JSC):
+ (SymbolTableEntry):
+ (Fast):
+ (JSC::SymbolTableEntry::Fast::Fast):
+ (JSC::SymbolTableEntry::Fast::isNull):
+ (JSC::SymbolTableEntry::Fast::getIndex):
+ (JSC::SymbolTableEntry::Fast::isReadOnly):
+ (JSC::SymbolTableEntry::Fast::getAttributes):
+ (JSC::SymbolTableEntry::Fast::isFat):
+ (JSC::SymbolTableEntry::SymbolTableEntry):
+ (JSC::SymbolTableEntry::~SymbolTableEntry):
+ (JSC::SymbolTableEntry::operator=):
+ (JSC::SymbolTableEntry::isNull):
+ (JSC::SymbolTableEntry::getIndex):
+ (JSC::SymbolTableEntry::getFast):
+ (JSC::SymbolTableEntry::getAttributes):
+ (JSC::SymbolTableEntry::isReadOnly):
+ (JSC::SymbolTableEntry::watchpointSet):
+ (JSC::SymbolTableEntry::notifyWrite):
+ (FatEntry):
+ (JSC::SymbolTableEntry::FatEntry::FatEntry):
+ (JSC::SymbolTableEntry::isFat):
+ (JSC::SymbolTableEntry::fatEntry):
+ (JSC::SymbolTableEntry::inflate):
+ (JSC::SymbolTableEntry::bits):
+ (JSC::SymbolTableEntry::freeFatEntry):
+ (JSC::SymbolTableEntry::pack):
+ (JSC::SymbolTableEntry::isValidIndex):
+
+2012-06-12 Filip Pizlo <fpizlo@apple.com>
+
+ Unreviewed build fix for ARMv7 debug builds.
+
+ * jit/JITStubs.cpp:
+ (JSC::JITThunks::JITThunks):
+
+2012-06-12 Geoffrey Garen <ggaren@apple.com>
+
+ Build fix for case-sensitive file systems: use the right case.
+
+ * heap/ListableHandler.h:
+
+2012-06-11 Geoffrey Garen <ggaren@apple.com>
+
+ GC should be 1.7X faster
+ https://bugs.webkit.org/show_bug.cgi?id=88840
+
+ Reviewed by Oliver Hunt.
+
+ I profiled, and removed anything that showed up as a concurrency
+ bottleneck. Then, I added 3 threads to our max thread count, since we
+ can scale up to more threads now.
+
+ * heap/BlockAllocator.cpp:
+ (JSC::BlockAllocator::BlockAllocator):
+ (JSC::BlockAllocator::~BlockAllocator):
+ (JSC::BlockAllocator::releaseFreeBlocks):
+ (JSC::BlockAllocator::waitForRelativeTimeWhileHoldingLock):
+ (JSC::BlockAllocator::waitForRelativeTime):
+ (JSC::BlockAllocator::blockFreeingThreadMain):
+ * heap/BlockAllocator.h:
+ (BlockAllocator):
+ (JSC::BlockAllocator::allocate):
+ (JSC::BlockAllocator::deallocate): Use a spin lock for the common case
+ where we're just popping a linked list. (A pthread mutex would sleep our
+ thread even if the lock were only contended for a microsecond.)
+
+ Scope the lock to avoid holding it while allocating VM, since that's a
+ slow activity and it doesn't modify any of our data structures.
+
+ We still use a pthread mutex to handle our condition variable since we
+ have to, and it's not a hot path.
+
+ * heap/CopiedSpace.cpp:
+ (JSC::CopiedSpace::CopiedSpace):
+ (JSC::CopiedSpace::doneFillingBlock):
+ * heap/CopiedSpace.h:
+ (JSC::CopiedSpace::CopiedSpace): Use a spin lock for the to space lock,
+ since it just guards linked list and hash table manipulation.
+
+ * heap/MarkStack.cpp:
+ (JSC::MarkStackSegmentAllocator::MarkStackSegmentAllocator):
+ (JSC::MarkStackSegmentAllocator::allocate):
+ (JSC::MarkStackSegmentAllocator::release):
+ (JSC::MarkStackSegmentAllocator::shrinkReserve): Use a spin lock, since
+ we're just managing a linked list.
+
+ (JSC::MarkStackArray::donateSomeCellsTo): Changed donation to be proportional
+ to our current stack size. This fixes cases where we used to donate too
+ much. Interestingly, donating too much was starving the donor (when it
+ ran out of work later) *and* the recipient (since it had to wait on a
+ long donation operation to complete before it could acquire the lock).
+
+ In the worst case, we're still guaranteed to donate N cells in roughly log N time.
+
+ This change also fixes cases where we used to donate too little, since
+ we would always keep a fixed minimum number of cells. In the worst case,
+ with N marking threads, would could have N large object graph roots in
+ our stack for the duration of GC, and scale to only 1 thread.
+
+ It's an interesting observation that a single object in the mark stack
+ might represent an arbitrarily large object graph -- and only the act
+ of marking can find out.
+
+ (JSC::MarkStackArray::stealSomeCellsFrom): Steal in proportion to idle
+ threads. Once again, this fixes cases where constants could cause us
+ to steal too much or too little.
+
+ (JSC::SlotVisitor::donateKnownParallel): Always wake up other threads
+ if they're idle. We can afford to do this because we're conservative
+ about when we donate.
+
+ (JSC::SlotVisitor::drainFromShared):
+ * heap/MarkStack.h:
+ (MarkStackSegmentAllocator):
+ (MarkStackArray):
+ (JSC):
+ * heap/SlotVisitor.h: Merged the "should I donate?" decision into a
+ single function, for simplicity.
+
+ * runtime/Options.cpp:
+ (minimumNumberOfScansBetweenRebalance): Reduced the delay before donation
+ a lot. We can afford to do this because, in the common case, donation is
+ a single branch that decides not to donate.
+
+ (cpusToUse): Use more CPUs now, since we scale better now.
+
+ * runtime/Options.h:
+ (Options): Removed now-unused variables.
+
+2012-06-12 Filip Pizlo <fpizlo@apple.com>
+
+ REGRESSION(120121): inspector tests crash in DFG
+ https://bugs.webkit.org/show_bug.cgi?id=88941
+
+ Reviewed by Geoffrey Garen.
+
+ The CFG simplifier has two different ways of fixing up GetLocal, Phantom, and Flush. If we've
+ already fixed up the node one way, we shouldn't try the other way. The reason why we shouldn't
+ is that the second way depends on the node referring to other nodes in the to-be-jettisoned
+ block. After fixup they potentially will refer to nodes in the block being merged to.
+
+ * dfg/DFGCFGSimplificationPhase.cpp:
+ (JSC::DFG::CFGSimplificationPhase::fixPossibleGetLocal):
+ (JSC::DFG::CFGSimplificationPhase::mergeBlocks):
+
+2012-06-12 Leo Yang <leo.yang@torchmobile.com.cn>
+
+ Dynamic hash table in DOMObjectHashTableMap is wrong in multiple threads
+ https://bugs.webkit.org/show_bug.cgi?id=87334
+
+ Reviewed by Geoffrey Garen.
+
+ Add a copy member function to JSC::HasTable. This function will copy all data
+ members except for *table* which contains thread specific data that prevents
+ up copying it. When you want to copy a JSC::HashTable that was constructed
+ on another thread you should call JSC::HashTable::copy().
+
+ * runtime/Lookup.h:
+ (JSC::HashTable::copy):
+ (HashTable):
+
+2012-06-12 Filip Pizlo <fpizlo@apple.com>
+
+ DFG should not ASSERT if you have a double use of a variable that is not revealed to be a double
+ until after CFG simplification
+ https://bugs.webkit.org/show_bug.cgi?id=88927
+ <rdar://problem/11513971>
+
+ Reviewed by Geoffrey Garen.
+
+ Speculation fixup needs to run if simplification did things, because simplification can change
+ predictions - particularly if you had a control flow path that stored weird things into a
+ variable, but that path got axed by the simplifier.
+
+ Running fixup in the fixpoint requires making it idempotent, which it previously wasn't. Only
+ one place needed to be changed, namely the un-MustGenerate-ion of ValueToInt32.
+
+ * dfg/DFGDriver.cpp:
+ (JSC::DFG::compile):
+ * dfg/DFGFixupPhase.cpp:
+ (JSC::DFG::FixupPhase::fixupNode):
+
+2012-06-12 Filip Pizlo <fpizlo@apple.com>
+
+ REGRESSION (r119779): Javascript TypeError: 'undefined' is not an object
+ https://bugs.webkit.org/show_bug.cgi?id=88783
+ <rdar://problem/11640299>
+
+ Reviewed by Geoffrey Garen.
+
+ If you don't keep alive the base of an object access over the various checks
+ you do for the prototype chain, you're going to have a bad time.
+
+ * dfg/DFGByteCodeParser.cpp:
+ (JSC::DFG::ByteCodeParser::handleGetById):
+
+2012-06-12 Hojong Han <hojong.han@samsung.com>
+
+ Property names of the built-in object cannot be retrieved
+ after trying to delete one of its properties
+ https://bugs.webkit.org/show_bug.cgi?id=86461
+
+ Reviewed by Gavin Barraclough.
+
+ * runtime/JSObject.cpp:
+ (JSC::getClassPropertyNames):
+ (JSC::JSObject::getOwnPropertyNames):
+
+2012-06-11 Gyuyoung Kim <gyuyoung.kim@samsung.com>
+
+ [CMAKE][EFL] Remove duplicated executable output path
+ https://bugs.webkit.org/show_bug.cgi?id=88765
+
+ Reviewed by Daniel Bates.
+
+ CMake files for EFL port have redefined executable output path. However, EFL port doesn't
+ need to define again because it is already defined in top-level CMake file.
+
+ * shell/CMakeLists.txt:
+
+2012-06-11 Carlos Garcia Campos <cgarcia@igalia.com>
+
+ Unreviewed. Fix make distcheck issues.
+
+ * GNUmakefile.list.am: Remove non existent header file.
+
+2012-06-10 Patrick Gansterer <paroga@webkit.org>
+
+ Unreviewed. Build fix for !ENABLE(JIT) after r119844 and r119925.
+
+ * runtime/Executable.h:
+ (ExecutableBase):
+ (JSC::ExecutableBase::clearCodeVirtual):
+
+2012-06-10 Patrick Gansterer <paroga@webkit.org>
+
+ Unreviewed. Build fix for !ENABLE(JIT) after r119844.
+
+ * runtime/Executable.h:
+ (ExecutableBase):
+ (JSC):
+
+2012-06-09 Dominic Cooney <dominicc@chromium.org>
+
+ [Chromium] Remove JavaScriptCore dependencies from gyp
+ https://bugs.webkit.org/show_bug.cgi?id=88510
+
+ Reviewed by Adam Barth.
+
+ Chromium doesn't support JSC any more and there doesn't seem to be
+ a strong interest in using GYP as the common build system in other
+ ports.
+
+ * JavaScriptCore.gyp/JavaScriptCore.gyp: WebCore still depends on YARR interpreter.
+ * JavaScriptCore.gypi: Only include YARR source.
+ * gyp/JavaScriptCore.gyp: Removed.
+ * gyp/gtk.gyp: Removed.
+
+2012-06-09 Geoffrey Garen <ggaren@apple.com>
+
+ Unreviewed, rolling back in part2 of r118646.
+
+ This patch removes eager finalization.
+
+ Weak pointer finalization should be lazy
+ https://bugs.webkit.org/show_bug.cgi?id=87599
+
+ Reviewed by Sam Weinig.
+
+ * heap/Heap.cpp:
+ (JSC::Heap::collect): Don't finalize eagerly -- we'll do it lazily.
+
+ * heap/MarkedBlock.cpp:
+ (JSC::MarkedBlock::sweep): Do sweep weak sets when sweeping a block,
+ since we won't get another chance.
+
+ * heap/MarkedBlock.h:
+ (JSC::MarkedBlock::sweepWeakSet):
+ * heap/MarkedSpace.cpp:
+ (MarkedSpace::WeakSetSweep):
+ * heap/MarkedSpace.h:
+ (JSC::MarkedSpace::sweepWeakSets): Removed now-unused code.
+
+2012-06-09 Sukolsak Sakshuwong <sukolsak@google.com>
+
+ Add UNDO_MANAGER flag
+ https://bugs.webkit.org/show_bug.cgi?id=87908
+
+ Reviewed by Tony Chang.
+
+ * Configurations/FeatureDefines.xcconfig:
+
+2012-06-08 Geoffrey Garen <ggaren@apple.com>
+
+ Unreviewed, rolling back in part1 of r118646.
+
+ This patch includes everything necessary for lazy finalization, but
+ keeps eager finalization enabled for the time being.
+
+ Weak pointer finalization should be lazy
+ https://bugs.webkit.org/show_bug.cgi?id=87599
+
+ Reviewed by Sam Weinig.
+
+ * heap/MarkedBlock.cpp:
+ * heap/MarkedBlock.h:
+ (JSC::MarkedBlock::resetAllocator):
+ * heap/MarkedSpace.cpp:
+ (JSC::MarkedSpace::resetAllocators):
+ * heap/MarkedSpace.h:
+ (JSC::MarkedSpace::resetAllocators): Don't force allocator reset anymore.
+ It will happen automatically when a weak set is swept. It's simpler to
+ have only one canonical way for this to happen, and it wasn't buying
+ us anything to do it eagerly.
+ * heap/WeakBlock.cpp:
+ (JSC::WeakBlock::sweep): Don't short-circuit a sweep unless we know
+ the sweep would be a no-op. If even one finalizer is pending, we need to
+ run it, since we won't get another chance.
+ * heap/WeakSet.cpp:
+ (JSC::WeakSet::sweep): This loop can be simpler now that
+ WeakBlock::sweep() does what we mean.
+ Reset our allocator after a sweep because this is the optimal time to
+ start trying to recycle old weak pointers.
+ (JSC::WeakSet::tryFindAllocator): Don't sweep when searching for an
+ allocator because we've swept already, and forcing a new sweep would be
+ wasteful.
+ * heap/WeakSet.h:
+ (JSC::WeakSet::shrink): Be sure to reset our allocator after a shrink
+ because the shrink may have removed the block the allocator was going to
+ allocate out of.
+
+2012-06-08 Gavin Barraclough <barraclough@apple.com>
+
+ Unreviewed roll out r119795.
+
+ This broke jquery/core.html
+
+ * dfg/DFGSpeculativeJIT.h:
+ (JSC::DFG::SpeculativeJIT::emitAllocateBasicJSObject):
+ * jit/JITInlineMethods.h:
+ (JSC::JIT::emitAllocateBasicJSObject):
+ * llint/LowLevelInterpreter.asm:
+ * runtime/JSGlobalData.h:
+ (JSGlobalData):
+ * runtime/JSGlobalThis.cpp:
+ (JSC::JSGlobalThis::setUnwrappedObject):
+ * runtime/JSObject.cpp:
+ (JSC::JSObject::visitChildren):
+ (JSC::JSObject::createInheritorID):
+ * runtime/JSObject.h:
+ (JSObject):
+ (JSC::JSObject::resetInheritorID):
+ (JSC):
+ (JSC::JSObject::offsetOfInheritorID):
+ (JSC::JSObject::inheritorID):
+
+2012-06-08 Filip Pizlo <fpizlo@apple.com>
+
+ PredictedType should be called SpeculatedType
+ https://bugs.webkit.org/show_bug.cgi?id=88477
+
+ Unreviewed, fix a renaming goof from http://trac.webkit.org/changeset/119660.
+ I accidentally renamed ByteCodeParser::getPrediction to
+ ByteCodeParser::getSpeculation. That was not the intent. This changes it
+ back.
+
+ * dfg/DFGByteCodeParser.cpp:
+ (JSC::DFG::ByteCodeParser::addCall):
+ (JSC::DFG::ByteCodeParser::getPredictionWithoutOSRExit):
+ (JSC::DFG::ByteCodeParser::getPrediction):
+ (JSC::DFG::ByteCodeParser::handleCall):
+ (JSC::DFG::ByteCodeParser::parseBlock):
+
+2012-06-08 Andy Wingo <wingo@igalia.com>
+
+ Explictly mark stubs called by JIT as being internal
+ https://bugs.webkit.org/show_bug.cgi?id=88552
+
+ Reviewed by Filip Pizlo.
+
+ * dfg/DFGOSRExitCompiler.h:
+ * dfg/DFGOperations.cpp:
+ * dfg/DFGOperations.h:
+ * jit/HostCallReturnValue.h:
+ * jit/JITStubs.cpp:
+ * jit/JITStubs.h:
+ * jit/ThunkGenerators.cpp:
+ * llint/LLIntSlowPaths.h: Mark a bunch of stubs as being
+ WTF_INTERNAL. Change most calls to SYMBOL_STRING_RELOCATION to
+ LOCAL_REFERENCE, or GLOBAL_REFERENCE in the case of the wrappers
+ to truly global symbols.
+ * offlineasm/asm.rb: Generate LOCAL_REFERENCE instead of
+ SYMBOL_STRING_RELOCATION.
+
+2012-06-08 Geoffrey Garen <ggaren@apple.com>
+
+ Don't rely on weak pointers for eager CodeBlock finalization
+ https://bugs.webkit.org/show_bug.cgi?id=88465
+
+ Reviewed by Gavin Barraclough.
+
+ This is incompatible with lazy weak pointer finalization.
+
+ I considered just making CodeBlock finalization lazy-friendly, but it
+ turns out that the heap is already way up in CodeBlock's business when
+ it comes to finalization, so I decided to finish the job and move full
+ responsibility for CodeBlock finalization into the heap.
+
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: Maybe this
+ will build.
+
+ * debugger/Debugger.cpp: Updated for rename.
+
+ * heap/Heap.cpp:
+ (JSC::Heap::deleteAllCompiledCode): Renamed for consistency. Fixed a bug
+ where we would not delete code for a code block that had been previously
+ jettisoned. I don't know if this happens in practice -- I mostly did
+ this to improve consistency with deleteUnmarkedCompiledCode.
+
+ (JSC::Heap::deleteUnmarkedCompiledCode): New function, responsible for
+ eager finalization of unmarked code blocks.
+
+ (JSC::Heap::collect): Updated for rename. Updated to call
+ deleteUnmarkedCompiledCode(), which takes care of jettisoned DFG code
+ blocks too.
+
+ (JSC::Heap::addCompiledCode): Renamed, since this points to all code
+ now, not just functions.
+
+ * heap/Heap.h:
+ (Heap): Keep track of all user code, not just functions. This is a
+ negligible additional overhead, since most code is function code.
+
+ * runtime/Executable.cpp:
+ (JSC::*::finalize): Removed these functions, since we don't rely on
+ weak pointer finalization anymore.
+
+ (JSC::FunctionExecutable::FunctionExecutable): Moved linked-list stuff
+ into base class so all executables can be in the list.
+
+ (JSC::EvalExecutable::clearCode):
+ (JSC::ProgramExecutable::clearCode):
+ (JSC::FunctionExecutable::clearCode): All we need to do is delete our
+ CodeBlock -- that will delete all of its internal data structures.
+
+ (JSC::FunctionExecutable::clearCodeIfNotCompiling): Factored out a helper
+ function to improve clarity.
+
+ * runtime/Executable.h:
+ (JSC::ExecutableBase): Moved linked-list stuff
+ into base class so all executables can be in the list.
+
+ (JSC::NativeExecutable::create):
+ (NativeExecutable):
+ (ScriptExecutable):
+ (JSC::ScriptExecutable::finishCreation):
+ (JSC::EvalExecutable::create):
+ (EvalExecutable):
+ (JSC::ProgramExecutable::create):
+ (ProgramExecutable):
+ (FunctionExecutable):
+ (JSC::FunctionExecutable::create): Don't use a finalizer -- the heap
+ will call us back to destroy our code block.
+
+ (JSC::FunctionExecutable::discardCode): Renamed to clearCodeIfNotCompiling()
+ for clarity.
+
+ (JSC::FunctionExecutable::isCompiling): New helper function, for clarity.
+
+ (JSC::ScriptExecutable::clearCodeVirtual): New helper function, since
+ the heap needs to make polymorphic calls to clear code.
+
+ * runtime/JSGlobalData.cpp:
+ (JSC::StackPreservingRecompiler::operator()):
+ * runtime/JSGlobalObject.cpp:
+ (JSC::DynamicGlobalObjectScope::DynamicGlobalObjectScope): Updated for
+ renames.
+
+2012-06-07 Filip Pizlo <fpizlo@apple.com>
+
+ DFG should inline prototype chain accesses, and do the right things if the
+ specific function optimization is available
+ https://bugs.webkit.org/show_bug.cgi?id=88594
+
+ Reviewed by Gavin Barraclough.
+
+ Looks like a 3% win on V8.
+
+ * bytecode/CodeBlock.h:
+ (JSC::Structure::prototypeForLookup):
+ (JSC):
+ * bytecode/GetByIdStatus.cpp:
+ (JSC::GetByIdStatus::computeFromLLInt):
+ (JSC):
+ (JSC::GetByIdStatus::computeForChain):
+ (JSC::GetByIdStatus::computeFor):
+ * bytecode/GetByIdStatus.h:
+ (JSC::GetByIdStatus::GetByIdStatus):
+ (JSC::GetByIdStatus::isSimple):
+ (JSC::GetByIdStatus::chain):
+ (JSC::GetByIdStatus::specificValue):
+ (GetByIdStatus):
+ * bytecode/StructureSet.h:
+ (StructureSet):
+ (JSC::StructureSet::singletonStructure):
+ * bytecode/StructureStubInfo.h:
+ (JSC::StructureStubInfo::initGetByIdProto):
+ (JSC::StructureStubInfo::initGetByIdChain):
+ * dfg/DFGByteCodeParser.cpp:
+ (JSC::DFG::ByteCodeParser::handleGetById):
+ * dfg/DFGRepatch.cpp:
+ (JSC::DFG::tryCacheGetByID):
+ * jit/JITStubs.cpp:
+ (JSC::JITThunks::tryCacheGetByID):
+ * runtime/JSGlobalObject.h:
+ (JSC::Structure::prototypeForLookup):
+ (JSC):
+ * runtime/Structure.h:
+ (Structure):
+
+2012-06-07 Gavin Barraclough <barraclough@apple.com>
+
+ Remove JSObject::m_inheritorID
+ https://bugs.webkit.org/show_bug.cgi?id=88378
+
+ Reviewed by Geoff Garen.
+
+ This is rarely used, and not performance critical (the commonly accessed copy is cached on JSFunction),
+ and most objects don't need an inheritorID (this value is only used if the object is used as a prototype).
+ Instead use a private named value in the object's property storage.
+
+ * dfg/DFGSpeculativeJIT.h:
+ (JSC::DFG::SpeculativeJIT::emitAllocateBasicJSObject):
+ - No need m_inheritorID to initialize!
+ * jit/JITInlineMethods.h:
+ (JSC::JIT::emitAllocateBasicJSObject):
+ - No need m_inheritorID to initialize!
+ * llint/LowLevelInterpreter.asm:
+ - No need m_inheritorID to initialize!
+ * runtime/JSGlobalData.h:
+ (JSGlobalData):
+ - Added private name 'm_inheritorIDKey'.
+ * runtime/JSGlobalThis.cpp:
+ (JSC::JSGlobalThis::setUnwrappedObject):
+ - resetInheritorID is now passed a JSGlobalData&.
+ * runtime/JSObject.cpp:
+ (JSC::JSObject::visitChildren):
+ - No m_inheritorID to be marked.
+ (JSC::JSObject::createInheritorID):
+ - Store the newly created inheritorID in the property map.
+ * runtime/JSObject.h:
+ (JSC::JSObject::resetInheritorID):
+ - Remove the inheritorID from property storage.
+ (JSC::JSObject::inheritorID):
+ - Read the inheritorID from property storage.
+
+2012-06-07 Gavin Barraclough <barraclough@apple.com>
+
+ Math.pow on iOS does not support denormal numbers.
+ https://bugs.webkit.org/show_bug.cgi?id=88592
+
+ Reviewed by Filip Pizlo.
+
+ Import an implementation from fdlibm, detect cases where it is safe to use the system
+ implementation & where we should fall back to fdlibm.
+
+ * runtime/MathObject.cpp:
+ (JSC::isDenormal):
+ (JSC::isEdgeCase):
+ (JSC::mathPow):
+ - On iOS, detect cases where denormal support may be required & use fdlibm in these cases.
+ (JSC::mathProtoFuncPow):
+ - Changed to use mathPow.
+ (JSC::fdlibmScalbn):
+ (JSC::fdlibmPow):
+ - These functions imported from fdlibm; original style retained to ease future merging.
+
+2012-06-07 Patrick Gansterer <paroga@webkit.org>
+
+ Unreviewed. Build fix for !ENABLE(JIT) after r119441.
+
+ * interpreter/Interpreter.cpp:
+ (JSC::Interpreter::privateExecute):
+
+2012-06-07 Andy Wingo <wingo@igalia.com>
+
+ Unreviewed build fix after r119593.
+
+ * llint/LLIntOfflineAsmConfig.h (OFFLINE_ASM_GLOBAL_LABEL): Fix
+ uses of "name" to be "label", the macro's parameter. Otherwise we
+ serialize mentions of the literal symbol "name" into the objcode.
+ Causes a build error using GNU ld (not gold).
+
+2012-06-06 Ryosuke Niwa <rniwa@webkit.org>
+
+ Chromium build fix attempt. Why do we need to list these files in gyp!?
+
+ * JavaScriptCore.gypi:
+
+2012-06-06 Filip Pizlo <fpizlo@apple.com>
+
+ PredictedType should be called SpeculatedType
+ https://bugs.webkit.org/show_bug.cgi?id=88477
+
+ Rubber stamped by Gavin Barraclough.
+
+ * CMakeLists.txt:
+ * GNUmakefile.list.am:
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * Target.pri:
+ * bytecode/CodeBlock.cpp:
+ (JSC::CodeBlock::shouldOptimizeNow):
+ (JSC::CodeBlock::dumpValueProfiles):
+ * bytecode/CodeBlock.h:
+ (JSC::CodeBlock::valueProfilePredictionForBytecodeOffset):
+ * bytecode/LazyOperandValueProfile.cpp:
+ (JSC::LazyOperandValueProfileParser::prediction):
+ * bytecode/LazyOperandValueProfile.h:
+ (LazyOperandValueProfileParser):
+ * bytecode/PredictedType.cpp: Removed.
+ * bytecode/PredictedType.h: Removed.
+ * bytecode/SpeculatedType.cpp: Copied from Source/JavaScriptCore/bytecode/PredictedType.cpp.
+ (JSC::speculationToString):
+ (JSC::speculationToAbbreviatedString):
+ (JSC::speculationFromClassInfo):
+ (JSC::speculationFromStructure):
+ (JSC::speculationFromCell):
+ (JSC::speculationFromValue):
+ * bytecode/SpeculatedType.h: Copied from Source/JavaScriptCore/bytecode/PredictedType.h.
+ (JSC):
+ (JSC::isAnySpeculation):
+ (JSC::isCellSpeculation):
+ (JSC::isObjectSpeculation):
+ (JSC::isFinalObjectSpeculation):
+ (JSC::isFinalObjectOrOtherSpeculation):
+ (JSC::isFixedIndexedStorageObjectSpeculation):
+ (JSC::isStringSpeculation):
+ (JSC::isArraySpeculation):
+ (JSC::isFunctionSpeculation):
+ (JSC::isInt8ArraySpeculation):
+ (JSC::isInt16ArraySpeculation):
+ (JSC::isInt32ArraySpeculation):
+ (JSC::isUint8ArraySpeculation):
+ (JSC::isUint8ClampedArraySpeculation):
+ (JSC::isUint16ArraySpeculation):
+ (JSC::isUint32ArraySpeculation):
+ (JSC::isFloat32ArraySpeculation):
+ (JSC::isFloat64ArraySpeculation):
+ (JSC::isArgumentsSpeculation):
+ (JSC::isActionableIntMutableArraySpeculation):
+ (JSC::isActionableFloatMutableArraySpeculation):
+ (JSC::isActionableTypedMutableArraySpeculation):
+ (JSC::isActionableMutableArraySpeculation):
+ (JSC::isActionableArraySpeculation):
+ (JSC::isArrayOrOtherSpeculation):
+ (JSC::isMyArgumentsSpeculation):
+ (JSC::isInt32Speculation):
+ (JSC::isDoubleRealSpeculation):
+ (JSC::isDoubleSpeculation):
+ (JSC::isNumberSpeculation):
+ (JSC::isBooleanSpeculation):
+ (JSC::isOtherSpeculation):
+ (JSC::isEmptySpeculation):
+ (JSC::mergeSpeculations):
+ (JSC::mergeSpeculation):
+ * bytecode/StructureSet.h:
+ (JSC::StructureSet::speculationFromStructures):
+ * bytecode/ValueProfile.h:
+ (JSC::ValueProfileBase::ValueProfileBase):
+ (JSC::ValueProfileBase::dump):
+ (JSC::ValueProfileBase::computeUpdatedPrediction):
+ (ValueProfileBase):
+ * dfg/DFGAbstractState.cpp:
+ (JSC::DFG::AbstractState::initialize):
+ (JSC::DFG::AbstractState::execute):
+ (JSC::DFG::AbstractState::mergeStateAtTail):
+ * dfg/DFGAbstractState.h:
+ (JSC::DFG::AbstractState::speculateInt32Unary):
+ (JSC::DFG::AbstractState::speculateNumberUnary):
+ (JSC::DFG::AbstractState::speculateBooleanUnary):
+ (JSC::DFG::AbstractState::speculateInt32Binary):
+ (JSC::DFG::AbstractState::speculateNumberBinary):
+ * dfg/DFGAbstractValue.h:
+ (JSC::DFG::StructureAbstractValue::filter):
+ (JSC::DFG::StructureAbstractValue::speculationFromStructures):
+ (JSC::DFG::AbstractValue::AbstractValue):
+ (JSC::DFG::AbstractValue::clear):
+ (JSC::DFG::AbstractValue::isClear):
+ (JSC::DFG::AbstractValue::makeTop):
+ (JSC::DFG::AbstractValue::clobberStructures):
+ (JSC::DFG::AbstractValue::isTop):
+ (JSC::DFG::AbstractValue::set):
+ (JSC::DFG::AbstractValue::merge):
+ (JSC::DFG::AbstractValue::filter):
+ (JSC::DFG::AbstractValue::validateIgnoringValue):
+ (JSC::DFG::AbstractValue::validate):
+ (JSC::DFG::AbstractValue::checkConsistency):
+ (JSC::DFG::AbstractValue::dump):
+ (AbstractValue):
+ * dfg/DFGArgumentPosition.h:
+ (JSC::DFG::ArgumentPosition::ArgumentPosition):
+ (JSC::DFG::ArgumentPosition::mergeArgumentAwareness):
+ (JSC::DFG::ArgumentPosition::prediction):
+ (ArgumentPosition):
+ * dfg/DFGArgumentsSimplificationPhase.cpp:
+ (JSC::DFG::ArgumentsSimplificationPhase::run):
+ * dfg/DFGByteCodeParser.cpp:
+ (ByteCodeParser):
+ (JSC::DFG::ByteCodeParser::injectLazyOperandSpeculation):
+ (JSC::DFG::ByteCodeParser::getLocal):
+ (JSC::DFG::ByteCodeParser::getArgument):
+ (JSC::DFG::ByteCodeParser::addCall):
+ (JSC::DFG::ByteCodeParser::getSpeculationWithoutOSRExit):
+ (JSC::DFG::ByteCodeParser::getSpeculation):
+ (InlineStackEntry):
+ (JSC::DFG::ByteCodeParser::handleCall):
+ (JSC::DFG::ByteCodeParser::handleIntrinsic):
+ (JSC::DFG::ByteCodeParser::handleGetById):
+ (JSC::DFG::ByteCodeParser::parseBlock):
+ (JSC::DFG::ByteCodeParser::fixVariableAccessSpeculations):
+ (JSC::DFG::ByteCodeParser::parse):
+ * dfg/DFGCSEPhase.cpp:
+ (JSC::DFG::CSEPhase::getIndexedPropertyStorageLoadElimination):
+ (JSC::DFG::CSEPhase::performNodeCSE):
+ * dfg/DFGConstantFoldingPhase.cpp:
+ (JSC::DFG::ConstantFoldingPhase::run):
+ * dfg/DFGFixupPhase.cpp:
+ (JSC::DFG::FixupPhase::fixupNode):
+ (JSC::DFG::FixupPhase::fixDoubleEdge):
+ * dfg/DFGGraph.cpp:
+ (JSC::DFG::Graph::nameOfVariableAccessData):
+ (JSC::DFG::Graph::dump):
+ (JSC::DFG::Graph::predictArgumentTypes):
+ * dfg/DFGGraph.h:
+ (JSC::DFG::Graph::getJSConstantSpeculation):
+ (JSC::DFG::Graph::isPredictedNumerical):
+ (JSC::DFG::Graph::byValIsPure):
+ * dfg/DFGJITCompiler.h:
+ (JSC::DFG::JITCompiler::getSpeculation):
+ * dfg/DFGNode.h:
+ (JSC::DFG::Node::Node):
+ (JSC::DFG::Node::getHeapPrediction):
+ (JSC::DFG::Node::predictHeap):
+ (JSC::DFG::Node::prediction):
+ (JSC::DFG::Node::predict):
+ (JSC::DFG::Node::shouldSpeculateInteger):
+ (JSC::DFG::Node::shouldSpeculateDouble):
+ (JSC::DFG::Node::shouldSpeculateNumber):
+ (JSC::DFG::Node::shouldSpeculateBoolean):
+ (JSC::DFG::Node::shouldSpeculateFinalObject):
+ (JSC::DFG::Node::shouldSpeculateFinalObjectOrOther):
+ (JSC::DFG::Node::shouldSpeculateArray):
+ (JSC::DFG::Node::shouldSpeculateArguments):
+ (JSC::DFG::Node::shouldSpeculateInt8Array):
+ (JSC::DFG::Node::shouldSpeculateInt16Array):
+ (JSC::DFG::Node::shouldSpeculateInt32Array):
+ (JSC::DFG::Node::shouldSpeculateUint8Array):
+ (JSC::DFG::Node::shouldSpeculateUint8ClampedArray):
+ (JSC::DFG::Node::shouldSpeculateUint16Array):
+ (JSC::DFG::Node::shouldSpeculateUint32Array):
+ (JSC::DFG::Node::shouldSpeculateFloat32Array):
+ (JSC::DFG::Node::shouldSpeculateFloat64Array):
+ (JSC::DFG::Node::shouldSpeculateArrayOrOther):
+ (JSC::DFG::Node::shouldSpeculateObject):
+ (JSC::DFG::Node::shouldSpeculateCell):
+ (Node):
+ * dfg/DFGPredictionPropagationPhase.cpp:
+ (JSC::DFG::PredictionPropagationPhase::setPrediction):
+ (JSC::DFG::PredictionPropagationPhase::mergePrediction):
+ (JSC::DFG::PredictionPropagationPhase::propagate):
+ (JSC::DFG::PredictionPropagationPhase::doRoundOfDoubleVoting):
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::fillStorage):
+ (JSC::DFG::SpeculativeJIT::writeBarrier):
+ (JSC::DFG::GPRTemporary::GPRTemporary):
+ (JSC::DFG::FPRTemporary::FPRTemporary):
+ (JSC::DFG::SpeculativeJIT::compilePeepHoleDoubleBranch):
+ (JSC::DFG::SpeculativeJIT::compilePeepHoleObjectEquality):
+ (JSC::DFG::SpeculativeJIT::compilePeepHoleBranch):
+ (JSC::DFG::SpeculativeJIT::compile):
+ (JSC::DFG::SpeculativeJIT::checkArgumentTypes):
+ (JSC::DFG::SpeculativeJIT::compileGetCharCodeAt):
+ (JSC::DFG::SpeculativeJIT::compileGetByValOnString):
+ (JSC::DFG::SpeculativeJIT::compileValueToInt32):
+ (JSC::DFG::SpeculativeJIT::compileDoubleAsInt32):
+ (JSC::DFG::SpeculativeJIT::compileInt32ToDouble):
+ (JSC::DFG::SpeculativeJIT::compileGetTypedArrayLength):
+ (JSC::DFG::SpeculativeJIT::compileGetByValOnIntTypedArray):
+ (JSC::DFG::SpeculativeJIT::compilePutByValForIntTypedArray):
+ (JSC::DFG::SpeculativeJIT::compileGetByValOnFloatTypedArray):
+ (JSC::DFG::SpeculativeJIT::compilePutByValForFloatTypedArray):
+ (JSC::DFG::SpeculativeJIT::compileInstanceOf):
+ (JSC::DFG::SpeculativeJIT::compileAdd):
+ (JSC::DFG::SpeculativeJIT::compileArithSub):
+ (JSC::DFG::SpeculativeJIT::compileArithNegate):
+ (JSC::DFG::SpeculativeJIT::compileArithMul):
+ (JSC::DFG::SpeculativeJIT::compileArithMod):
+ (JSC::DFG::SpeculativeJIT::compare):
+ (JSC::DFG::SpeculativeJIT::compileStrictEq):
+ (JSC::DFG::SpeculativeJIT::compileGetIndexedPropertyStorage):
+ (JSC::DFG::SpeculativeJIT::compileGetByValOnArguments):
+ (JSC::DFG::SpeculativeJIT::compileGetArgumentsLength):
+ (JSC::DFG::SpeculativeJIT::compileRegExpExec):
+ * dfg/DFGSpeculativeJIT.h:
+ (DFG):
+ (JSC::DFG::ValueSource::forSpeculation):
+ (SpeculativeJIT):
+ (GPRTemporary):
+ (FPRTemporary):
+ (JSC::DFG::SpecDoubleOperand::SpecDoubleOperand):
+ (JSC::DFG::SpecDoubleOperand::~SpecDoubleOperand):
+ (JSC::DFG::SpecDoubleOperand::fpr):
+ (JSC::DFG::SpecCellOperand::SpecCellOperand):
+ (JSC::DFG::SpecCellOperand::~SpecCellOperand):
+ (JSC::DFG::SpecCellOperand::gpr):
+ (JSC::DFG::SpecBooleanOperand::SpecBooleanOperand):
+ (JSC::DFG::SpecBooleanOperand::~SpecBooleanOperand):
+ (JSC::DFG::SpecBooleanOperand::gpr):
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::fillSpeculateIntInternal):
+ (JSC::DFG::SpeculativeJIT::fillSpecDouble):
+ (JSC::DFG::SpeculativeJIT::fillSpecCell):
+ (JSC::DFG::SpeculativeJIT::fillSpecBoolean):
+ (JSC::DFG::SpeculativeJIT::compileObjectEquality):
+ (JSC::DFG::SpeculativeJIT::compileObjectToObjectOrOtherEquality):
+ (JSC::DFG::SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality):
+ (JSC::DFG::SpeculativeJIT::compileDoubleCompare):
+ (JSC::DFG::SpeculativeJIT::compileLogicalNot):
+ (JSC::DFG::SpeculativeJIT::emitBranch):
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::fillSpeculateIntInternal):
+ (JSC::DFG::SpeculativeJIT::fillSpecDouble):
+ (JSC::DFG::SpeculativeJIT::fillSpecCell):
+ (JSC::DFG::SpeculativeJIT::fillSpecBoolean):
+ (JSC::DFG::SpeculativeJIT::compileObjectEquality):
+ (JSC::DFG::SpeculativeJIT::compileObjectToObjectOrOtherEquality):
+ (JSC::DFG::SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality):
+ (JSC::DFG::SpeculativeJIT::compileDoubleCompare):
+ (JSC::DFG::SpeculativeJIT::compileLogicalNot):
+ (JSC::DFG::SpeculativeJIT::emitBranch):
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGVariableAccessData.h:
+ (JSC::DFG::VariableAccessData::VariableAccessData):
+ (JSC::DFG::VariableAccessData::predict):
+ (JSC::DFG::VariableAccessData::nonUnifiedPrediction):
+ (JSC::DFG::VariableAccessData::prediction):
+ (JSC::DFG::VariableAccessData::argumentAwarePrediction):
+ (JSC::DFG::VariableAccessData::mergeArgumentAwarePrediction):
+ (JSC::DFG::VariableAccessData::shouldUseDoubleFormatAccordingToVote):
+ (JSC::DFG::VariableAccessData::makePredictionForDoubleFormat):
+ (VariableAccessData):
+
+2012-06-06 Filip Pizlo <fpizlo@apple.com>
+
+ Global object variable accesses should not require an extra load
+ https://bugs.webkit.org/show_bug.cgi?id=88385
+
+ Reviewed by Gavin Barraclough and Geoffrey Garen.
+
+ Previously, if you wanted to access a global variable, you'd first have
+ to load the register array from the appropriate global object and then
+ either load or store at an offset to the register array. This is because
+ JSGlobalObject inherited from JSVariableObject, and JSVariableObject is
+ designed with the pessimistic assumption that its register array may
+ point into the call stack. This is never the case for global objects.
+ Hence, even though the global object may add more registers at any time,
+ it does not need to store them in a contiguous array. It can use a
+ SegmentedVector or similar.
+
+ This patch refactors global objects and variable objects as follows:
+
+ - The functionality to track variables in an indexable array using a
+ SymbolTable to map names to indices is moved into JSSymbolTableObject,
+ which is now a supertype of JSVariableObject. JSVariableObject is now
+ just a holder for a registers array and implements the registerAt()
+ method that is left abstract in JSSymbolTableObject. Because all users
+ of JSVariableObject know whether they are a JSStaticScopeObject,
+ JSActivation, or JSGlobalObject, this "abstract" method is not virtual;
+ instead the utility methods that would call registerAt() are now
+ template functions that require you to know statically what subtype of
+ JSSymbolTableObject you're using (JSVariableObject or something else),
+ so that registerAt() can be statically bound.
+
+ - A new class is added called JSSegmentedVariableObject, which only
+ differs from JSVariableObject in how it allocates registers. It uses a
+ SegmentedVector instead of manually managing a pointer to a contiguous
+ slab of registers. This changes the interface somewhat; for example
+ with JSVariableObject if you wanted to add a register you had to do
+ it yourself since the JSVariableObject didn't know how the registers
+ array ought to be allocated. With JSSegmentedVariableObject you can
+ just call addRegisters(). JSSegmentedVariableObject preserves the
+ invariant that once you get a pointer into a register, that pointer
+ will continue to be valid so long as the JSSegmentedVariableObject is
+ alive. This allows the JITs and interpreters to skip the extra load.
+
+ - JSGlobalObject now inherits from JSSegmentedVariableObject. For now
+ (and possibly forever) it is the only subtype of this new class.
+
+ - The bytecode format is changed so that get_global_var and
+ put_global_var have a pointer to the register directly rather than
+ having an index. A convenience method is provided in
+ JSSegmentedVariableObject to get the index given a a pointer, which is
+ used for assertions and debug dumps.
+
+ This appears to be a 1% across the board win.
+
+ * CMakeLists.txt:
+ * GNUmakefile.list.am:
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * Target.pri:
+ * bytecode/CodeBlock.cpp:
+ (JSC::CodeBlock::dump):
+ * bytecode/Instruction.h:
+ (Instruction):
+ (JSC::Instruction::Instruction):
+ * bytecompiler/BytecodeGenerator.cpp:
+ (JSC::ResolveResult::registerPointer):
+ (JSC):
+ (JSC::BytecodeGenerator::BytecodeGenerator):
+ (JSC::BytecodeGenerator::retrieveLastUnaryOp):
+ (JSC::BytecodeGenerator::resolve):
+ (JSC::BytecodeGenerator::resolveConstDecl):
+ (JSC::BytecodeGenerator::emitGetStaticVar):
+ (JSC::BytecodeGenerator::emitPutStaticVar):
+ * bytecompiler/BytecodeGenerator.h:
+ (ResolveResult):
+ (BytecodeGenerator):
+ * dfg/DFGAssemblyHelpers.h:
+ (AssemblyHelpers):
+ * dfg/DFGByteCodeParser.cpp:
+ (JSC::DFG::ByteCodeParser::parseBlock):
+ * dfg/DFGCSEPhase.cpp:
+ (JSC::DFG::CSEPhase::globalVarLoadElimination):
+ (JSC::DFG::CSEPhase::globalVarStoreElimination):
+ (JSC::DFG::CSEPhase::performNodeCSE):
+ * dfg/DFGGraph.cpp:
+ (JSC::DFG::Graph::dump):
+ * dfg/DFGGraph.h:
+ (JSC::DFG::Graph::globalObjectFor):
+ (Graph):
+ * dfg/DFGNode.h:
+ (JSC::DFG::Node::hasVarNumber):
+ (Node):
+ (JSC::DFG::Node::hasRegisterPointer):
+ (JSC::DFG::Node::registerPointer):
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * heap/Heap.h:
+ (Heap):
+ (JSC::Heap::isWriteBarrierEnabled):
+ (JSC):
+ * interpreter/Interpreter.cpp:
+ (JSC::Interpreter::execute):
+ (JSC::Interpreter::privateExecute):
+ * jit/JITPropertyAccess.cpp:
+ (JSC::JIT::emit_op_get_global_var):
+ (JSC::JIT::emit_op_put_global_var):
+ * jit/JITPropertyAccess32_64.cpp:
+ (JSC::JIT::emit_op_get_global_var):
+ (JSC::JIT::emit_op_put_global_var):
+ * llint/LowLevelInterpreter32_64.asm:
+ * llint/LowLevelInterpreter64.asm:
+ * runtime/JSGlobalObject.cpp:
+ (JSC):
+ (JSC::JSGlobalObject::put):
+ (JSC::JSGlobalObject::putDirectVirtual):
+ (JSC::JSGlobalObject::defineOwnProperty):
+ (JSC::JSGlobalObject::visitChildren):
+ (JSC::JSGlobalObject::addStaticGlobals):
+ (JSC::JSGlobalObject::getOwnPropertySlot):
+ (JSC::JSGlobalObject::getOwnPropertyDescriptor):
+ * runtime/JSGlobalObject.h:
+ (JSGlobalObject):
+ (JSC::JSGlobalObject::JSGlobalObject):
+ (JSC):
+ (JSC::JSGlobalObject::hasOwnPropertyForWrite):
+ * runtime/JSSegmentedVariableObject.cpp: Added.
+ (JSC):
+ (JSC::JSSegmentedVariableObject::findRegisterIndex):
+ (JSC::JSSegmentedVariableObject::addRegisters):
+ (JSC::JSSegmentedVariableObject::visitChildren):
+ * runtime/JSSegmentedVariableObject.h: Added.
+ (JSC):
+ (JSSegmentedVariableObject):
+ (JSC::JSSegmentedVariableObject::registerAt):
+ (JSC::JSSegmentedVariableObject::assertRegisterIsInThisObject):
+ (JSC::JSSegmentedVariableObject::JSSegmentedVariableObject):
+ (JSC::JSSegmentedVariableObject::finishCreation):
+ * runtime/JSStaticScopeObject.cpp:
+ (JSC::JSStaticScopeObject::put):
+ (JSC::JSStaticScopeObject::putDirectVirtual):
+ (JSC::JSStaticScopeObject::getOwnPropertySlot):
+ * runtime/JSSymbolTableObject.cpp: Added.
+ (JSC):
+ (JSC::JSSymbolTableObject::destroy):
+ (JSC::JSSymbolTableObject::deleteProperty):
+ (JSC::JSSymbolTableObject::getOwnPropertyNames):
+ (JSC::JSSymbolTableObject::putDirectVirtual):
+ (JSC::JSSymbolTableObject::isDynamicScope):
+ * runtime/JSSymbolTableObject.h: Added.
+ (JSC):
+ (JSSymbolTableObject):
+ (JSC::JSSymbolTableObject::symbolTable):
+ (JSC::JSSymbolTableObject::JSSymbolTableObject):
+ (JSC::JSSymbolTableObject::finishCreation):
+ (JSC::symbolTableGet):
+ (JSC::symbolTablePut):
+ (JSC::symbolTablePutWithAttributes):
+ * runtime/JSVariableObject.cpp:
+ (JSC):
+ * runtime/JSVariableObject.h:
+ (JSVariableObject):
+ (JSC::JSVariableObject::JSVariableObject):
+ (JSC::JSVariableObject::finishCreation):
+ (JSC):
+ * runtime/WriteBarrier.h:
+
+2012-06-06 Filip Pizlo <fpizlo@apple.com>
+
+ DFG arguments access slow path should not crash if the arguments haven't been created
+ https://bugs.webkit.org/show_bug.cgi?id=88471
+
+ Reviewed by Gavin Barraclough.
+
+ * dfg/DFGCCallHelpers.h:
+ (JSC::DFG::CCallHelpers::setupArgumentsWithExecState):
+ (CCallHelpers):
+ * dfg/DFGOperations.cpp:
+ * dfg/DFGOperations.h:
+ * dfg/DFGSpeculativeJIT.h:
+ (JSC::DFG::SpeculativeJIT::callOperation):
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+
+2012-06-06 Michael Saboff <msaboff@apple.com>
+
+ ENH: Add Logging to GC Marking Phase
+ https://bugs.webkit.org/show_bug.cgi?id=88364
+
+ Reviewed by Filip Pizlo.
+
+ Log GC marking to stderr or a file. The logging in controlled
+ with the define ENABLE_OBJECT_MARK_LOGGING in wtf/Platform.h.
+ If DATA_LOG_TO_FILE in wtf/DataLog.cpp is set to 1, output is
+ logged to a file otherwise it is logged to stderr.
+
+ When logging is enabled, the GC is built single threaded since the
+ log output from the various threads isn't buffered and output in a
+ thread safe manner.
+
+ * heap/Heap.cpp:
+ (JSC::Heap::markRoots):
+ * heap/MarkStack.cpp:
+ (JSC::MarkStackThreadSharedData::resetChildren):
+ (JSC::MarkStackThreadSharedData::childVisitCount):
+ (JSC::MarkStackThreadSharedData::markingThreadMain):
+ (JSC::MarkStackThreadSharedData::markingThreadStartFunc):
+ (JSC::MarkStackThreadSharedData::MarkStackThreadSharedData):
+ (JSC::MarkStackThreadSharedData::reset):
+ * heap/MarkStack.h:
+ (MarkStackThreadSharedData):
+ (MarkStack):
+ (JSC::MarkStack::sharedData):
+ (JSC::MarkStack::resetChildCount):
+ (JSC::MarkStack::childCount):
+ (JSC::MarkStack::incrementChildCount):
+ * runtime/JSArray.cpp:
+ (JSC::JSArray::visitChildren):
+ * runtime/JSCell.cpp:
+ (JSC::JSCell::className):
+ * runtime/JSCell.h:
+ (JSCell):
+ (JSC::JSCell::visitChildren):
+ * runtime/JSString.cpp:
+ (JSC::JSString::visitChildren):
+ * runtime/JSString.h:
+ (JSString):
+ * runtime/Structure.h:
+ (JSC::MarkStack::internalAppend):
+
+2012-06-06 Gavin Barraclough <barraclough@apple.com>
+
+ Assigning to a static property should not change iteration order
+ https://bugs.webkit.org/show_bug.cgi?id=88401
+
+ Reviewed by Geoff Garen.
+
+ A specific iteration order is not defined by the spec, but test-262 somewhat tenuously
+ requires that it is at least stable, e.g. ch10/10.4/10.4.2/S10.4.2_A1.1_T1.js
+
+ Whilst it is not clear that this behavior really arises from the specification, it
+ would seem like common sense to conform to this.
+
+ The problem here is that we allow properties in the structure to shadow those in the
+ static table, and we iterate the properties in the structure first - which means that
+ as values of existing properties are modified, their iteration order changes too.
+
+ The easy fix is to iterate the properties from the static table first. This has a
+ further benefit, since it will mean that user added properties will come after those
+ present in the static table (respected the expected insertion-order).
+
+ * runtime/JSObject.cpp:
+ (JSC::JSObject::getOwnPropertyNames):
+ - Iterate static properties first.
+
+2012-06-06 Andy Wingo <wingo@igalia.com>
+
+ Ensure consistent order of evaluation in LLInt slow paths
+ https://bugs.webkit.org/show_bug.cgi?id=88409
+
+ Reviewed by Geoffrey Garen.
+
+ * llint/LLIntSlowPaths.cpp:
+ (slow_path_mul)
+ (slow_path_sub)
+ (slow_path_div)
+ (slow_path_mod)
+ (slow_path_lshift)
+ (slow_path_rshift)
+ (slow_path_urshift)
+ (slow_path_bitand)
+ (slow_path_bitor)
+ (slow_path_bitxor): Avoid calling toNumber, toInt32, or toUInt32
+ multiple times without intervening sequence points. Fixes
+ fast/js/exception-sequencing-binops.html with GCC 4.7 on x86-64
+ Linux, which reordered evaluation of the arguments to fmod.
+
+2012-06-06 Andy Wingo <wingo@igalia.com>
+
+ [GTK] Enable the LLInt
+ https://bugs.webkit.org/show_bug.cgi?id=88315
+
+ Reviewed by Filip Pizlo.
+
+ * GNUmakefile.am: Add rules to generate LLIntDesiredOffsets.h and
+ LLIntAssembly.h.
+ * GNUmakefile.list.am: Add offlineasm and llint files to the
+ dist. Add LLInt source files to the build.
+ * llint/LowLevelInterpreter.asm (crash): Generate a store of
+ 0xbbadbeef to a register, not to a constant. Otherwise, gas was
+ failing to assemble result.
+ * offlineasm/asm.rb (labelReference): Generate a
+ SYMBOL_STRING_RELOCATION instead of a SYMBOL_STRING, so that we go
+ through the PLT on ELF systems.
+
+2012-06-06 Andy Wingo <wingo@igalia.com>
+
+ REGRESSION (r106478): None of the Paper.js JavaScript examples work
+ https://bugs.webkit.org/show_bug.cgi?id=87158
+
+ Reviewed by Michael Saboff.
+
+ * bytecompiler/BytecodeGenerator.cpp:
+ (JSC::BytecodeGenerator::resolve): If we have to bail out to
+ dynamicResolve(), only skip static scopes from the head of the
+ scope chain. Before, we were also skipping activations with
+ direct eval as well, which was incorrect.
+
+2012-06-06 Dan Bernstein <mitz@apple.com>
+
+ Reverted r119567, the fix for <http://webkit.org/b/88378>, because it broke the 32-bit build.
+
+ * dfg/DFGSpeculativeJIT.h:
+ (JSC::DFG::SpeculativeJIT::emitAllocateBasicJSObject):
+ * jit/JITInlineMethods.h:
+ (JSC::JIT::emitAllocateBasicJSObject):
+ * llint/LowLevelInterpreter.asm:
+ * runtime/JSGlobalData.h:
+ (JSGlobalData):
+ * runtime/JSGlobalThis.cpp:
+ (JSC::JSGlobalThis::setUnwrappedObject):
+ * runtime/JSObject.cpp:
+ (JSC::JSObject::visitChildren):
+ (JSC::JSObject::createInheritorID):
+ * runtime/JSObject.h:
+ (JSObject):
+ (JSC::JSObject::resetInheritorID):
+ (JSC):
+ (JSC::JSObject::offsetOfInheritorID):
+ (JSC::JSObject::inheritorID):
+
+2012-06-05 Yuqiang Xian <yuqiang.xian@intel.com>
+
+ Improve Math.round and Math.floor intrinsic
+ https://bugs.webkit.org/show_bug.cgi?id=88314
+
+ Reviewed by Filip Pizlo.
+
+ Currently we call a native function from the JIT code to complete the
+ "round" and "floor" operations. We could inline some fast paths
+ especially for those positive values on the platforms where floating
+ point truncation is supported.
+ This brings 3% gain on Kraken, especially 32% on audio-oscillator,
+ and slight win on SunSpider, measured on IA32.
+
+ * jit/ThunkGenerators.cpp:
+ (JSC::floorThunkGenerator):
+ (JSC):
+ (JSC::roundThunkGenerator):
+
+2012-06-05 Gavin Barraclough <barraclough@apple.com>
+
+ Remove JSObject::m_inheritorID
+ https://bugs.webkit.org/show_bug.cgi?id=88378
+
+ Reviewed by Geoff Garen.
+
+ This is rarely used, and not performance critical (the commonly accessed copy is cached on JSFunction),
+ and most objects don't need an inheritorID (this value is only used if the object is used as a prototype).
+ Instead use a private named value in the object's property storage.
+
+ * dfg/DFGSpeculativeJIT.h:
+ (JSC::DFG::SpeculativeJIT::emitAllocateBasicJSObject):
+ - No need m_inheritorID to initialize!
+ * jit/JITInlineMethods.h:
+ (JSC::JIT::emitAllocateBasicJSObject):
+ - No need m_inheritorID to initialize!
+ * llint/LowLevelInterpreter.asm:
+ - No need m_inheritorID to initialize!
+ * runtime/JSGlobalData.h:
+ (JSGlobalData):
+ - Added private name 'm_inheritorIDKey'.
+ * runtime/JSGlobalThis.cpp:
+ (JSC::JSGlobalThis::setUnwrappedObject):
+ - resetInheritorID is now passed a JSGlobalData&.
+ * runtime/JSObject.cpp:
+ (JSC::JSObject::visitChildren):
+ - No m_inheritorID to be marked.
+ (JSC::JSObject::createInheritorID):
+ - Store the newly created inheritorID in the property map.
+ * runtime/JSObject.h:
+ (JSC::JSObject::resetInheritorID):
+ - Remove the inheritorID from property storage.
+ (JSC::JSObject::inheritorID):
+ - Read the inheritorID from property storage.
+
+2012-06-05 Filip Pizlo <fpizlo@apple.com>
+
+ DFG CFG simplification should not attempt to deref nodes inside of an unreachable subgraph
+ https://bugs.webkit.org/show_bug.cgi?id=88362
+
+ Reviewed by Gavin Barraclough.
+
+ * dfg/DFGCFGSimplificationPhase.cpp:
+ (JSC::DFG::CFGSimplificationPhase::fixPhis):
+ (JSC::DFG::CFGSimplificationPhase::removePotentiallyDeadPhiReference):
+
+2012-06-05 Mark Hahnenberg <mhahnenberg@apple.com>
+
+ Entry into JSC should CRASH() if the Heap is busy
+ https://bugs.webkit.org/show_bug.cgi?id=88355
+
+ Reviewed by Geoffrey Garen.
+
+ Interpreter::execute() returns jsNull() right now if we try to enter it while
+ the Heap is busy (e.g. with a collection), which is okay, but some code paths
+ that call Interpreter::execute() allocate objects before checking if the Heap
+ is busy. Attempting to execute JS code while the Heap is busy should not be
+ allowed and should be enforced by a release-mode CRASH() to prevent vague,
+ unhelpful backtraces later on if somebody makes a mistake. Normally, recursively
+ executing JS code is okay, e.g. for evals, but it should not occur during a
+ Heap allocation or collection because the Heap is not guaranteed to be in a
+ consistent state (especially during collections). We are protected from
+ executing JS on the same Heap concurrently on two separate threads because
+ they must each take a JSLock first. However, we are not protected from reentrant
+ execution of JS on the same thread because JSLock allows reentrancy. Therefore,
+ we should fail early if we detect an entrance into JS code while the Heap is busy.
+
+ * heap/Heap.cpp: Changed Heap::collect so that it sets the m_operationInProgress field
+ at the beginning of collection and then unsets it at the end so that it is set at all
+ times throughout the duration of a collection rather than sporadically during various
+ phases. There is no reason to unset during a collection because our collector does
+ not currently support running additional JS between the phases of a collection.
+ (JSC::Heap::getConservativeRegisterRoots):
+ (JSC::Heap::markRoots):
+ (JSC::Heap::collect):
+ * interpreter/Interpreter.cpp:
+ (JSC::Interpreter::execute): Crash if the Heap is busy.
+ * runtime/Completion.cpp: Crash if the Heap is busy. We do it here before we call
+ Interpreter::execute() because we do some allocation prior to calling execute() which
+ could cause Heap corruption if, for example, that allocation caused a collection.
+ (JSC::evaluate):
+
+2012-06-05 Dongwoo Im <dw.im@samsung.com>
+
+ Add 'isProtocolHandlerRegistered' and 'unregisterProtocolHandler'.
+ https://bugs.webkit.org/show_bug.cgi?id=73176
+
+ Reviewed by Adam Barth.
+
+ Two more APIs are added in Custom Scheme Handler specification.
+ http://dev.w3.org/html5/spec/Overview.html#custom-handlers
+ One is 'isProtocolHandlerRegistered' to query whether the specific URL
+ is registered or not.
+ The other is 'unregisterProtocolHandler' to remove the registered URL.
+
+ * Configurations/FeatureDefines.xcconfig: Add a macro 'ENABLE_CUSTOM_SCHEME_HANDLER'.
+
+2012-06-04 Filip Pizlo <fpizlo@apple.com>
+
+ DFG CFG simplification should correct the variables at the head of the predecessor block
+ https://bugs.webkit.org/show_bug.cgi?id=88284
+
+ Reviewed by Geoffrey Garen.
+
+ * dfg/DFGCFGSimplificationPhase.cpp:
+ (JSC::DFG::CFGSimplificationPhase::mergeBlocks):
+
+2012-06-04 Geoffrey Garen <ggaren@apple.com>
+
+ Unreviewed.
+
+ Rolled out r119364 because it's still causing crashes (when running
+ v8-earley in release builds of DRT)
+
+ This time for sure!
+
+ * heap/Heap.cpp:
+ (JSC::Heap::collect):
+ * heap/MarkedBlock.cpp:
+ (JSC::MarkedBlock::sweep):
+ * heap/MarkedBlock.h:
+ (JSC::MarkedBlock::resetAllocator):
+ (JSC):
+ * heap/MarkedSpace.cpp:
+ (JSC::ResetAllocator::operator()):
+ (JSC):
+ (JSC::MarkedSpace::resetAllocators):
+ (JSC::MarkedSpace::sweepWeakSets):
+ * heap/MarkedSpace.h:
+ (MarkedSpace):
+ * heap/WeakBlock.cpp:
+ (JSC::WeakBlock::sweep):
+ * heap/WeakSet.cpp:
+ (JSC::WeakSet::sweep):
+ (JSC::WeakSet::tryFindAllocator):
+ * heap/WeakSet.h:
+ (JSC::WeakSet::shrink):
+
+2012-06-04 Filip Pizlo <fpizlo@apple.com>
+
+ DFG arguments simplification should have rationalized handling of TearOffArguments
+ https://bugs.webkit.org/show_bug.cgi?id=88206
+
+ Reviewed by Geoffrey Garen.
+
+ - Accesses to the unmodified arguments register ought to have the same effect on
+ alias/escape analysis of arguments as accesses to the mutable arguments register.
+
+ - The existence of TearOffArguments should not get in the way of arguments aliasing.
+
+ - TearOffArguments should be eliminated if CreateArguments is eliminated.
+
+ * dfg/DFGArgumentsSimplificationPhase.cpp:
+ (JSC::DFG::ArgumentsSimplificationPhase::run):
+ (JSC::DFG::ArgumentsSimplificationPhase::observeBadArgumentsUse):
+
+2012-06-04 Gavin Barraclough <barraclough@apple.com>
+
+ Remove enabledProfilerReference
+ https://bugs.webkit.org/show_bug.cgi?id=88258
+
+ Reviewed by Michael Saboff.
+
+ Make the enabled profiler a member of JSGlobalData, and switch code that accesses it to do so directly
+ via the JSGlobalData, rather than holding a Profiler** reference to it. Do not pass the Profiler**
+ reference to JIT code. This patch does not change the stack layout on entry into JIT code (passing an
+ unused void* instead), since this is an intrusive change better handled in a separate patch.
+
+ * interpreter/Interpreter.cpp:
+ (JSC::Interpreter::throwException):
+ (JSC::Interpreter::execute):
+ (JSC::Interpreter::executeCall):
+ (JSC::Interpreter::executeConstruct):
+ (JSC::Interpreter::privateExecute):
+ * jit/JITCode.h:
+ (JSC::JITCode::execute):
+ - Don't pass Profiler** to JIT code.
+ * jit/JITOpcodes.cpp:
+ (JSC::JIT::emit_op_profile_will_call):
+ (JSC::JIT::emit_op_profile_did_call):
+ * jit/JITOpcodes32_64.cpp:
+ (JSC::JIT::emit_op_profile_will_call):
+ (JSC::JIT::emit_op_profile_did_call):
+ * jit/JITStubs.cpp:
+ (JSC):
+ (JSC::ctiTrampoline):
+ (JSC::ctiVMThrowTrampoline):
+ (JSC::ctiOpThrowNotCaught):
+ (JSC::JITThunks::JITThunks):
+ (JSC::DEFINE_STUB_FUNCTION):
+ - For ARM_THUMB2, rename ENABLE_PROFILER_REFERENCE_OFFSET to FIRST_STACK_ARGUMENT (which is how it is being used).
+ - For MIPS, remove ENABLE_PROFILER_REFERENCE_OFFSET.
+ * jit/JITStubs.h:
+ (JITStackFrame):
+ (JSC):
+ - Renamed enabledProfilerReference to unusedX.
+ * llint/LLIntSlowPaths.cpp:
+ (JSC::LLInt::LLINT_SLOW_PATH_DECL):
+ * llint/LowLevelInterpreter.asm:
+ * profiler/Profiler.cpp:
+ (JSC):
+ (JSC::Profiler::startProfiling):
+ (JSC::Profiler::stopProfiling):
+ * profiler/Profiler.h:
+ (Profiler):
+ - Removed s_sharedEnabledProfilerReference, enabledProfilerReference().
+ * runtime/JSGlobalData.cpp:
+ (JSC::JSGlobalData::JSGlobalData):
+ * runtime/JSGlobalData.h:
+ (JSC):
+ (JSC::JSGlobalData::enabledProfiler):
+ (JSGlobalData):
+ - Added m_enabledProfiler, enabledProfiler().
+ * runtime/JSGlobalObject.cpp:
+ (JSC::JSGlobalObject::~JSGlobalObject):
+
+2012-06-04 Filip Pizlo <fpizlo@apple.com>
+
+ get_argument_by_val should be profiled everywhere
+ https://bugs.webkit.org/show_bug.cgi?id=88205
+
+ Reviewed by Geoffrey Garen.
+
+ * jit/JITOpcodes32_64.cpp:
+ (JSC::JIT::emitSlow_op_get_argument_by_val):
+ * llint/LLIntSlowPaths.cpp:
+ (JSC::LLInt::LLINT_SLOW_PATH_DECL):
+
+2012-06-04 Filip Pizlo <fpizlo@apple.com>
+
+ DFG arguments simplification takes unkindly to direct accesses to the arguments register
+ https://bugs.webkit.org/show_bug.cgi?id=88261
+
+ Reviewed by Geoffrey Garen.
+
+ Fixed arguments simplification for direct accesses to the arguments register, which may
+ arise if CSE had not run. Fixed CSE so that it does run prior to arguments simplification,
+ by making it a full-fledged member of the fixpoint. Fixed other issues in arguments
+ simplification, like realizing that it needs to bail if there is a direct assignment to
+ the arguments register, and failing to turn CreateArguments into PhantomArguments. Also
+ fixed CSE's handling of store elimination of captured locals in the presence of a
+ GetMyArgumentByVal (or one of its friends), and fixed CSE to correctly fixup variables at
+ tail if the Flush it removes is the last operation on a local in a basic block.
+
+ * bytecode/CodeBlock.cpp:
+ (JSC::CodeBlock::dump):
+ * dfg/DFGArgumentsSimplificationPhase.cpp:
+ (JSC::DFG::ArgumentsSimplificationPhase::run):
+ (JSC::DFG::ArgumentsSimplificationPhase::isOKToOptimize):
+ * dfg/DFGCSEPhase.cpp:
+ (JSC::DFG::CSEPhase::run):
+ (JSC::DFG::CSEPhase::setLocalStoreElimination):
+ (JSC::DFG::CSEPhase::performNodeCSE):
+ (CSEPhase):
+ * dfg/DFGDriver.cpp:
+ (JSC::DFG::compile):
+
+2012-06-04 Anders Carlsson <andersca@apple.com>
+
+ Fix a struct/class mismatch.
+
+ * heap/Handle.h:
+ (Handle):
+
+2012-06-04 David Kilzer <ddkilzer@apple.com>
+
+ BUILD FIX: FeatureDefines.xcconfig should match across projects
+
+ * Configurations/FeatureDefines.xcconfig:
+ - Add missing ENABLE_LEGACY_CSS_VENDOR_PREFIXES.
+
+2012-06-02 Geoffrey Garen <ggaren@apple.com>
+
+ Weak pointer finalization should be lazy
+ https://bugs.webkit.org/show_bug.cgi?id=87599
+
+ Reviewed by Sam Weinig.
+
+ This time for sure!
+
+ * heap/Heap.cpp:
+ (JSC::Heap::collect): Don't sweep eagerly -- we'll sweep lazily instead.
+
+ * heap/MarkedBlock.cpp:
+ (JSC::MarkedBlock::sweep): Sweep our weak set before we sweep our other
+ destructors -- this is our last chance to run weak set finalizers before
+ we recycle our memory.
+
+ * heap/MarkedBlock.h:
+ (JSC::MarkedBlock::resetAllocator):
+ * heap/MarkedSpace.cpp:
+ (JSC::MarkedSpace::resetAllocators):
+ * heap/MarkedSpace.h:
+ (JSC::MarkedSpace::resetAllocators): Don't force allocator reset anymore.
+ It will happen automatically when a weak set is swept. It's simpler to
+ have only one canonical way for this to happen, and it wasn't buying
+ us anything to do it eagerly.
+
+ * heap/WeakBlock.cpp:
+ (JSC::WeakBlock::sweep): Don't short-circuit a sweep unless we know
+ the sweep would be a no-op. If even one finalizer is pending, we need to
+ run it, since we won't get another chance.
+
+ * heap/WeakSet.cpp:
+ (JSC::WeakSet::sweep): This loop can be simpler now that
+ WeakBlock::sweep() does what we mean.
+
+ Reset our allocator after a sweep because this is the optimal time to
+ start trying to recycle old weak pointers.
+
+ (JSC::WeakSet::tryFindAllocator): Don't sweep when searching for an
+ allocator because we've swept already, and forcing a new sweep would be
+ wasteful.
+
+ * heap/WeakSet.h:
+ (JSC::WeakSet::shrink): Be sure to reset our allocator after a shrink
+ because the shrink may have removed the block the allocator was going to
+ allocate out of.
+
+2012-06-02 Filip Pizlo <fpizlo@apple.com>
+
+ If the DFG bytecode parser detects that op_method_check has gone polymorphic, it
+ shouldn't revert all the way to GetById/GetByIdFlush
+ https://bugs.webkit.org/show_bug.cgi?id=88176
+
+ Reviewed by Geoffrey Garen.
+
+ Refactored the code so that the op_method_check case of the parser gracefully falls
+ through to all of the goodness of the normal op_get_by_id case.
+
+ * dfg/DFGByteCodeParser.cpp:
+ (ByteCodeParser):
+ (JSC::DFG::ByteCodeParser::handleGetById):
+ (DFG):
+ (JSC::DFG::ByteCodeParser::parseBlock):
+
+2012-06-02 Filip Pizlo <fpizlo@apple.com>
+
+ DFG CSE should be able to eliminate unnecessary flushes of arguments and captured variables
+ https://bugs.webkit.org/show_bug.cgi?id=87929
+
+ Reviewed by Geoffrey Garen.
+
+ Slight speed-up on V8. Big win (up to 50%) on programs that inline very small functions.
+
+ This required a bunch of changes:
+
+ - The obvious change is making CSE essentially ignore whether or not the set of
+ operations between the Flush and the SetLocal can exit, and instead focus on whether or
+ not that set of operations can clobber the world or access local variables. This code
+ is now refactored to return a set of flags indicating any of these events, and the CSE
+ decides what to do based on those flags. If the set of operations is non-clobbering
+ and non-accessing, then the Flush is turned into a Phantom on the child of the
+ SetLocal. This expands the liveness of the relevant variable but virtually guarantees
+ that it will be register allocated and not flushed to the stack. So, yeah, this patch
+ is a lot of work to save a few stores to the stack.
+
+ - Previously, CheckArgumentsNotCreated was optimized "lazily" in that you only knew if
+ it was a no-op if you were holding onto a CFA abstract state. But this would make the
+ CSE act pessimistically, since it doesn't use the CFA. Hence, this patch changes the
+ constant folding phase into something more broad; it now fixes up
+ CheckArgumentsNotCreated nodes by turning them into phantoms if it knows that they are
+ no-ops.
+
+ - Arguments simplification was previously relying on this very strange PhantomArguments
+ node, which had two different meanings: for normal execution it meant the empty value
+ but for OSR exit it meant that the arguments should be reified. This produces problems
+ when set SetLocals to the captured arguments registers are CSE'd away, since we'd be
+ triggering reification of arguments without having initialized the arguments registers
+ to empty. The cleanest solution was to fix PhantomArguments to have one meaning:
+ namely, arguments reification on OSR exit. Hence, this patch changes arguments
+ simplification to change SetLocal of CreateArguments on the arguments registers to be
+ a SetLocal of Empty.
+
+ - Argument value recoveries were previously derived from the value source of the
+ arguments at the InlineStart. But that relies on all SetLocals to arguments having
+ been flushed. It's possible that we could have elided the SetLocal to the arguments
+ at the callsite because there were subsequent SetLocals to the arguments inside of the
+ callee, in which case the InlineStart would get the wrong information. Hence, this
+ patch changes argument value recovery computation to operate over the ArgumentPositions
+ directly.
+
+ - But that doesn't actually work, because previously, there was no way to link an
+ InlineStart back to the corresponding ArgumentPositions, at least not without some
+ ugliness. So this patch instates the rule that the m_argumentPositions vector consists
+ of disjoint subsequences such that each subsequence corresponds to an inline callsite
+ and can be identified by its first index, and within each subsequence are the
+ ArgumentPositions of all of the arguments ordered by argument index. This required
+ flipping the order in which ArgumentPositions are added to the vector, and giving
+ InlineStart an operand that indicates the start of that inline callsite's
+ ArgumentPosition subsequence.
+
+ - This patch also revealed a nasty bug in the reification of arguments in inline call
+ frames on OSR exit. Since the reification was happening after the values of virtual
+ registers were recovered, the value recoveries of the inline arguments were wrong.
+ Hence using operationCreateInlinedArguments is wrong. For example a value recovery
+ might say that you have to box a double, but if we had already boxed it then boxing
+ it a second time will result in garbage. The specific case of this bug was this patch
+ uncovered was that now it is possible for an inline call frame to not have any valid
+ value recoveries for any inline arguments, if the optimization elides all argument
+ flushes, while at the same time optimizing away arguments creation. Then OSR exit
+ would try to recover the arguments using the inline call frame, which had bogus
+ information, and humorous crashes would ensue. This patch fixes this issue by moving
+ arguments reification to after call frame reification, so that arguments reification
+ can always use operationCreateArguments instead of operationCreateInlinedArguments.
+
+ - This patch may turn a Flush into a Phantom. That's kind of the whole point. But that
+ broke forward speculation checks, which knew to look for a Flush prior to a SetLocal
+ but didn't know that there could alternatively be a Phantom in place of the Flush.
+ This patch fixes that by augmenting the forward speculation check logic.
+
+ - Finally, in the process of having fun with all of the above, I realized that my DFG
+ validation was not actually running on every phase like I had originally designed it
+ to. In fact it was only running just after bytecode parsing. I initially tried to
+ make it run in every phase but found that this causes some tests to timeout
+ (specifically the evil fuzzing ones), so I decided on a compromise where: (i) in
+ release mode validation never runs, (ii) in debug mode validation will run just
+ after parsing and just before the backend, and (iii) it's possible with a simple
+ switch to enable validation to run on every phase.
+
+ Luckily all of the above issues were already covered by the 77 or so DFG-specific
+ layout tests. Hence, this patch does not introduce any new tests despite being so
+ meaty.
+
+ * dfg/DFGAbstractState.cpp:
+ (JSC::DFG::AbstractState::execute):
+ * dfg/DFGArgumentPosition.h:
+ (JSC::DFG::ArgumentPosition::prediction):
+ (JSC::DFG::ArgumentPosition::doubleFormatState):
+ (JSC::DFG::ArgumentPosition::shouldUseDoubleFormat):
+ (ArgumentPosition):
+ * dfg/DFGArgumentsSimplificationPhase.cpp:
+ (JSC::DFG::ArgumentsSimplificationPhase::run):
+ * dfg/DFGByteCodeParser.cpp:
+ (JSC::DFG::ByteCodeParser::handleInlining):
+ (JSC::DFG::ByteCodeParser::InlineStackEntry::InlineStackEntry):
+ * dfg/DFGCSEPhase.cpp:
+ (JSC::DFG::CSEPhase::SetLocalStoreEliminationResult::SetLocalStoreEliminationResult):
+ (SetLocalStoreEliminationResult):
+ (JSC::DFG::CSEPhase::setLocalStoreElimination):
+ (JSC::DFG::CSEPhase::performNodeCSE):
+ * dfg/DFGCommon.h:
+ * dfg/DFGConstantFoldingPhase.cpp:
+ (JSC::DFG::ConstantFoldingPhase::run):
+ * dfg/DFGDriver.cpp:
+ (JSC::DFG::compile):
+ * dfg/DFGNode.h:
+ (Node):
+ (JSC::DFG::Node::hasArgumentPositionStart):
+ (JSC::DFG::Node::argumentPositionStart):
+ * dfg/DFGOSRExitCompiler32_64.cpp:
+ (JSC::DFG::OSRExitCompiler::compileExit):
+ * dfg/DFGOSRExitCompiler64.cpp:
+ (JSC::DFG::OSRExitCompiler::compileExit):
+ * dfg/DFGPhase.cpp:
+ (DFG):
+ * dfg/DFGPhase.h:
+ (Phase):
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGSpeculativeJIT.h:
+ (JSC::DFG::SpeculativeJIT::forwardSpeculationCheck):
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+
+2012-06-02 Geoffrey Garen <ggaren@apple.com>
+
+ DOM string cache should hash pointers, not characters
+ https://bugs.webkit.org/show_bug.cgi?id=88175
+
+ Reviewed by Phil Pizlo and Sam Weinig.
+
+ * heap/Weak.h:
+ (JSC::weakAdd):
+ (JSC::weakRemove): Made these function templates slightly more generic
+ to accommodate new client types.
+
+2012-06-01 Filip Pizlo <fpizlo@apple.com>
+
+ DFG CFA should know that PutByVal can clobber the world
+ https://bugs.webkit.org/show_bug.cgi?id=88155
+
+ Reviewed by Gavin Barraclough.
+
+ * dfg/DFGAbstractState.cpp:
+ (JSC::DFG::AbstractState::execute):
+
+2012-06-01 Filip Pizlo <fpizlo@apple.com>
+
+ DFG CFA should mark basic blocks as having constants if local accesses yield constants
+ https://bugs.webkit.org/show_bug.cgi?id=88153
+
+ Reviewed by Gavin Barraclough.
+
+ * dfg/DFGAbstractState.cpp:
+ (JSC::DFG::AbstractState::execute):
+
+2012-06-01 Filip Pizlo <fpizlo@apple.com>
+
+ DFG arguments simplification phase uses a node.codeOrigin after appending a node
+ https://bugs.webkit.org/show_bug.cgi?id=88151
+
+ Reviewed by Geoffrey Garen.
+
+ The right thing to do is to save the CodeOrigin before appending to the graph.
+
+ * dfg/DFGArgumentsSimplificationPhase.cpp:
+ (JSC::DFG::ArgumentsSimplificationPhase::run):
+
+2012-06-01 Filip Pizlo <fpizlo@apple.com>
+
+ DFG should not emit unnecessary speculation checks when performing an int32 to double conversion on
+ a value that is proved to be a number, predicted to be an int32, but not proved to be an int32
+ https://bugs.webkit.org/show_bug.cgi?id=88146
+
+ Reviewed by Gavin Barraclough.
+
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::compileInt32ToDouble):
+
+2012-06-01 Filip Pizlo <fpizlo@apple.com>
+
+ DFG constant folding search for the last local access skips the immediately previous local access
+ https://bugs.webkit.org/show_bug.cgi?id=88141
+
+ Reviewed by Michael Saboff.
+
+ If you use a loop in the style of:
+
+ for (i = start; i--;)
+
+ then you need to remember that the first value of 'i' that the loop body will see is 'start - 1'.
+ Hence the following is probably wrong:
+
+ for (i = start - 1; i--;)
+
+ * dfg/DFGConstantFoldingPhase.cpp:
+ (JSC::DFG::ConstantFoldingPhase::run):
+
+2012-06-01 Filip Pizlo <fpizlo@apple.com>
+
+ DFG constant folding should be OK with GetLocal of captured variables having a constant
+ https://bugs.webkit.org/show_bug.cgi?id=88137
+
+ Reviewed by Gavin Barraclough.
+
+ * dfg/DFGConstantFoldingPhase.cpp:
+ (JSC::DFG::ConstantFoldingPhase::run):
+
2012-05-31 Mark Hahnenberg <mhahnenberg@apple.com>
JSGlobalObject does not mark m_privateNameStructure
diff --git a/Source/JavaScriptCore/Configurations/FeatureDefines.xcconfig b/Source/JavaScriptCore/Configurations/FeatureDefines.xcconfig
index 76440b0a6..b96b21db3 100644
--- a/Source/JavaScriptCore/Configurations/FeatureDefines.xcconfig
+++ b/Source/JavaScriptCore/Configurations/FeatureDefines.xcconfig
@@ -36,12 +36,14 @@ ENABLE_ACCELERATED_2D_CANVAS = ;
ENABLE_ANIMATION_API = ;
ENABLE_BLOB = ENABLE_BLOB;
ENABLE_CHANNEL_MESSAGING = ENABLE_CHANNEL_MESSAGING;
+ENABLE_CSP_NEXT = ;
ENABLE_CSS3_FLEXBOX = ENABLE_CSS3_FLEXBOX;
ENABLE_CSS_EXCLUSIONS = ENABLE_CSS_EXCLUSIONS;
ENABLE_CSS_FILTERS = ENABLE_CSS_FILTERS;
ENABLE_CSS_IMAGE_RESOLUTION = ;
ENABLE_CSS_REGIONS = ENABLE_CSS_REGIONS;
ENABLE_CSS_VARIABLES = ;
+ENABLE_CUSTOM_SCHEME_HANDLER = ;
ENABLE_DASHBOARD_SUPPORT = $(ENABLE_DASHBOARD_SUPPORT_$(REAL_PLATFORM_NAME));
ENABLE_DASHBOARD_SUPPORT_macosx = ENABLE_DASHBOARD_SUPPORT;
ENABLE_DATALIST = ;
@@ -82,6 +84,7 @@ ENABLE_INPUT_TYPE_WEEK = $(ENABLE_INPUT_TYPE_WEEK_$(REAL_PLATFORM_NAME));
ENABLE_INPUT_TYPE_WEEK_iphoneos = ENABLE_INPUT_TYPE_WEEK;
ENABLE_INPUT_TYPE_WEEK_iphonesimulator = ENABLE_INPUT_TYPE_WEEK;
ENABLE_JAVASCRIPT_DEBUGGER = ENABLE_JAVASCRIPT_DEBUGGER;
+ENABLE_LEGACY_CSS_VENDOR_PREFIXES = ENABLE_LEGACY_CSS_VENDOR_PREFIXES;
ENABLE_LEGACY_NOTIFICATIONS = $(ENABLE_LEGACY_NOTIFICATIONS_$(REAL_PLATFORM_NAME));
ENABLE_LEGACY_NOTIFICATIONS_macosx = $(ENABLE_LEGACY_NOTIFICATIONS_macosx_$(TARGET_MAC_OS_X_VERSION_MAJOR));
ENABLE_LEGACY_NOTIFICATIONS_macosx_1070 = ;
@@ -117,6 +120,7 @@ ENABLE_SVG_DOM_OBJC_BINDINGS_macosx = ENABLE_SVG_DOM_OBJC_BINDINGS;
ENABLE_SVG_FONTS = ENABLE_SVG_FONTS;
ENABLE_TEXT_NOTIFICATIONS_ONLY = ENABLE_TEXT_NOTIFICATIONS_ONLY;
ENABLE_TOUCH_ICON_LOADING = ;
+ENABLE_UNDO_MANAGER = ;
ENABLE_VIDEO = ENABLE_VIDEO;
ENABLE_VIDEO_TRACK = $(ENABLE_VIDEO_TRACK_$(REAL_PLATFORM_NAME));
ENABLE_VIDEO_TRACK_macosx = ENABLE_VIDEO_TRACK;
@@ -127,4 +131,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_CSS3_FLEXBOX) $(ENABLE_CSS_EXCLUSIONS) $(ENABLE_CSS_FILTERS) $(ENABLE_CSS_IMAGE_RESOLUTION) $(ENABLE_CSS_REGIONS) $(ENABLE_CSS_SHADERS) $(ENABLE_CSS_VARIABLES) $(ENABLE_DASHBOARD_SUPPORT) $(ENABLE_DATALIST) $(ENABLE_DATA_TRANSFER_ITEMS) $(ENABLE_DETAILS) $(ENABLE_DEVICE_ORIENTATION) $(ENABLE_DIRECTORY_UPLOAD) $(ENABLE_FILE_SYSTEM) $(ENABLE_FILTERS) $(ENABLE_FONT_BOOSTING) $(ENABLE_FULLSCREEN_API) $(ENABLE_GAMEPAD) $(ENABLE_GEOLOCATION) $(ENABLE_HIGH_DPI_CANVAS) $(ENABLE_ICONDATABASE) $(ENABLE_IFRAME_SEAMLESS) $(ENABLE_INDEXED_DATABASE) $(ENABLE_INPUT_TYPE_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_LEGACY_NOTIFICATIONS) $(ENABLE_LINK_PREFETCH) $(ENABLE_LINK_PRERENDER) $(ENABLE_MATHML) $(ENABLE_MEDIA_SOURCE) $(ENABLE_MEDIA_STATISTICS) $(ENABLE_METER_TAG) $(ENABLE_MICRODATA) $(ENABLE_MUTATION_OBSERVERS) $(ENABLE_NOTIFICATIONS) $(ENABLE_PAGE_VISIBILITY_API) $(ENABLE_PROGRESS_TAG) $(ENABLE_QUOTA) $(ENABLE_REGISTER_PROTOCOL_HANDLER) $(ENABLE_REQUEST_ANIMATION_FRAME) $(ENABLE_SCRIPTED_SPEECH) $(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);
+FEATURE_DEFINES = $(ENABLE_3D_RENDERING) $(ENABLE_ACCELERATED_2D_CANVAS) $(ENABLE_ANIMATION_API) $(ENABLE_BLOB) $(ENABLE_CHANNEL_MESSAGING) $(ENABLE_CSP_NEXT) $(ENABLE_CSS3_FLEXBOX) $(ENABLE_CSS_EXCLUSIONS) $(ENABLE_CSS_FILTERS) $(ENABLE_CSS_IMAGE_RESOLUTION) $(ENABLE_CSS_REGIONS) $(ENABLE_CSS_SHADERS) $(ENABLE_CSS_VARIABLES) $(ENABLE_CUSTOM_SCHEME_HANDLER) $(ENABLE_DASHBOARD_SUPPORT) $(ENABLE_DATALIST) $(ENABLE_DATA_TRANSFER_ITEMS) $(ENABLE_DETAILS) $(ENABLE_DEVICE_ORIENTATION) $(ENABLE_DIRECTORY_UPLOAD) $(ENABLE_FILE_SYSTEM) $(ENABLE_FILTERS) $(ENABLE_FONT_BOOSTING) $(ENABLE_FULLSCREEN_API) $(ENABLE_GAMEPAD) $(ENABLE_GEOLOCATION) $(ENABLE_HIGH_DPI_CANVAS) $(ENABLE_ICONDATABASE) $(ENABLE_IFRAME_SEAMLESS) $(ENABLE_INDEXED_DATABASE) $(ENABLE_INPUT_TYPE_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_LEGACY_CSS_VENDOR_PREFIXES) $(ENABLE_LEGACY_NOTIFICATIONS) $(ENABLE_LINK_PREFETCH) $(ENABLE_LINK_PRERENDER) $(ENABLE_MATHML) $(ENABLE_MEDIA_SOURCE) $(ENABLE_MEDIA_STATISTICS) $(ENABLE_METER_TAG) $(ENABLE_MICRODATA) $(ENABLE_MUTATION_OBSERVERS) $(ENABLE_NOTIFICATIONS) $(ENABLE_PAGE_VISIBILITY_API) $(ENABLE_PROGRESS_TAG) $(ENABLE_QUOTA) $(ENABLE_REGISTER_PROTOCOL_HANDLER) $(ENABLE_REQUEST_ANIMATION_FRAME) $(ENABLE_SCRIPTED_SPEECH) $(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_UNDO_MANAGER) $(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/DerivedSources.make b/Source/JavaScriptCore/DerivedSources.make
index fb60d30ca..b0b637e88 100644
--- a/Source/JavaScriptCore/DerivedSources.make
+++ b/Source/JavaScriptCore/DerivedSources.make
@@ -59,6 +59,7 @@ all : \
StringConstructor.lut.h \
StringPrototype.lut.h \
docs/bytecode.html \
+ udis86_itab.h \
#
# lookup tables for classes
@@ -79,6 +80,11 @@ RegExpJitTables.h: create_regex_tables
KeywordLookup.h: KeywordLookupGenerator.py Keywords.table
python $^ > $@
+# udis86 instruction tables
+
+udis86_itab.h: $(JavaScriptCore)/disassembler/udis86/itab.py $(JavaScriptCore)/disassembler/udis86/optable.xml
+ (PYTHONPATH=$(JavaScriptCore)/disassembler/udis86 python $(JavaScriptCore)/disassembler/udis86/itab.py $(JavaScriptCore)/disassembler/udis86/optable.xml || exit 1)
+
# header detection
ifeq ($(OS),MACOS)
diff --git a/Source/JavaScriptCore/GNUmakefile.am b/Source/JavaScriptCore/GNUmakefile.am
index 1ad42fd1c..96a23f288 100644
--- a/Source/JavaScriptCore/GNUmakefile.am
+++ b/Source/JavaScriptCore/GNUmakefile.am
@@ -51,6 +51,7 @@ javascriptcore_cppflags += \
-I$(srcdir)/Source/JavaScriptCore/bytecode \
-I$(srcdir)/Source/JavaScriptCore/bytecompiler \
-I$(srcdir)/Source/JavaScriptCore/dfg \
+ -I$(srcdir)/Source/JavaScriptCore/disassembler \
-I$(srcdir)/Source/JavaScriptCore/heap \
-I$(srcdir)/Source/JavaScriptCore/debugger \
-I$(srcdir)/Source/JavaScriptCore/ForwardingHeaders \
@@ -89,6 +90,16 @@ DerivedSources/JavaScriptCore/RegExpJitTables.h: $(srcdir)/Source/JavaScriptCore
DerivedSources/JavaScriptCore/KeywordLookup.h: $(srcdir)/Source/JavaScriptCore/KeywordLookupGenerator.py $(srcdir)/Source/JavaScriptCore/parser/Keywords.table
$(AM_V_GEN)$(PYTHON) $^ > $@
+DerivedSources/JavaScriptCore/LLIntDesiredOffsets.h: $(javascriptcore_sources) $(llint_nosources) $(offlineasm_nosources)
+ $(AM_V_GEN)$(RUBY) $(srcdir)/Source/JavaScriptCore/offlineasm/generate_offset_extractor.rb $(srcdir)/Source/JavaScriptCore/llint/LowLevelInterpreter.asm $@
+
+$(Programs_LLIntOffsetsExtractor_OBJECTS): DerivedSources/JavaScriptCore/LLIntDesiredOffsets.h
+
+DerivedSources/JavaScriptCore/LLIntAssembly.h: Programs/LLIntOffsetsExtractor$(EXEEXT)
+ $(AM_V_GEN)$(RUBY) $(srcdir)/Source/JavaScriptCore/offlineasm/asm.rb $(srcdir)/Source/JavaScriptCore/llint/LowLevelInterpreter.asm Programs/LLIntOffsetsExtractor$(EXEEXT) $@
+
+$(libjavascriptcoregtk_@WEBKITGTK_API_MAJOR_VERSION@_@WEBKITGTK_API_MINOR_VERSION@_la_OBJECTS): DerivedSources/JavaScriptCore/LLIntAssembly.h
+
jsc: $(javascriptcore_built_nosources) Programs/jsc$(EXEEXT)
bin_PROGRAMS += \
@@ -96,7 +107,8 @@ bin_PROGRAMS += \
noinst_PROGRAMS += \
Programs/jsc \
- Programs/minidom
+ Programs/minidom \
+ Programs/LLIntOffsetsExtractor
Programs_minidom_CPPFLAGS = \
$(global_cppflags) \
@@ -119,6 +131,30 @@ Programs_minidom_LDFLAGS = \
-no-install \
-no-fast-install
+Programs_LLIntOffsetsExtractor_CPPFLAGS = \
+ $(global_cppflags) \
+ $(javascriptcore_cppflags)
+
+Programs_LLIntOffsetsExtractor_CFLAGS = \
+ -ansi \
+ -fno-strict-aliasing \
+ $(global_cflags) \
+ $(GLOBALDEPS_CFLAGS)
+
+Programs_LLIntOffsetsExtractor_LDADD = \
+ -lpthread \
+ libWTF.la \
+ $(UNICODE_LIBS) \
+ $(GLIB_LIBS) \
+ $(WINMM_LIBS) \
+ -lm \
+ -lpthread \
+ -lstdc++
+
+Programs_LLIntOffsetsExtractor_LDFLAGS = \
+ -no-install \
+ -no-fast-install
+
# jsc
Programs/jsc$(EXEEXT): Programs/jsc-@WEBKITGTK_API_MAJOR_VERSION@$(EXEEXT)
$(AM_V_GEN)cp -f Programs/jsc-@WEBKITGTK_API_MAJOR_VERSION@$(EXEEXT) Programs/jsc$(EXEEXT)
@@ -151,12 +187,15 @@ EXTRA_DIST += \
Source/JavaScriptCore/icu/README \
Source/JavaScriptCore/KeywordLookupGenerator.py \
Source/JavaScriptCore/parser/Keywords.table \
- Source/JavaScriptCore/THANKS
+ Source/JavaScriptCore/THANKS \
+ $(llint_nosources) \
+ $(offlineasm_nosources)
CLEANFILES += \
$(javascriptcore_built_nosources) \
Programs/jsc \
Programs/jsc-@WEBKITGTK_API_MAJOR_VERSION@ \
+ Programs/LLIntOffsetsExtractor \
Programs/minidom
DISTCLEANFILES += \
diff --git a/Source/JavaScriptCore/GNUmakefile.list.am b/Source/JavaScriptCore/GNUmakefile.list.am
index efd4b5fd8..77409fe93 100644
--- a/Source/JavaScriptCore/GNUmakefile.list.am
+++ b/Source/JavaScriptCore/GNUmakefile.list.am
@@ -20,7 +20,7 @@ javascriptcore_built_nosources += \
DerivedSources/JavaScriptCore/JSGlobalObject.lut.h \
DerivedSources/JavaScriptCore/JSONObject.lut.h \
DerivedSources/JavaScriptCore/MathObject.lut.h \
- DerivedSources/JavaScriptCore/NamePrototype.lut.h \
+ DerivedSources/JavaScriptCore/NamePrototype.lut.h \
DerivedSources/JavaScriptCore/NumberConstructor.lut.h \
DerivedSources/JavaScriptCore/NumberPrototype.lut.h \
DerivedSources/JavaScriptCore/ObjectConstructor.lut.h \
@@ -29,7 +29,9 @@ javascriptcore_built_nosources += \
DerivedSources/JavaScriptCore/RegExpObject.lut.h \
DerivedSources/JavaScriptCore/RegExpPrototype.lut.h \
DerivedSources/JavaScriptCore/StringConstructor.lut.h \
- DerivedSources/JavaScriptCore/StringPrototype.lut.h
+ DerivedSources/JavaScriptCore/StringPrototype.lut.h \
+ DerivedSources/JavaScriptCore/LLIntDesiredOffsets.h \
+ DerivedSources/JavaScriptCore/LLIntAssembly.h
javascriptcore_sources += \
Source/JavaScriptCore/API/APICast.h \
@@ -63,6 +65,7 @@ javascriptcore_sources += \
Source/JavaScriptCore/assembler/AssemblerBuffer.h \
Source/JavaScriptCore/assembler/AssemblerBufferWithConstantPool.h \
Source/JavaScriptCore/assembler/CodeLocation.h \
+ Source/JavaScriptCore/assembler/LinkBuffer.cpp \
Source/JavaScriptCore/assembler/LinkBuffer.h \
Source/JavaScriptCore/assembler/MacroAssembler.h \
Source/JavaScriptCore/assembler/MacroAssemblerARM.cpp \
@@ -118,8 +121,8 @@ javascriptcore_sources += \
Source/JavaScriptCore/bytecode/Operands.h \
Source/JavaScriptCore/bytecode/PolymorphicPutByIdList.cpp \
Source/JavaScriptCore/bytecode/PolymorphicPutByIdList.h \
- Source/JavaScriptCore/bytecode/PredictedType.cpp \
- Source/JavaScriptCore/bytecode/PredictedType.h \
+ Source/JavaScriptCore/bytecode/SpeculatedType.cpp \
+ Source/JavaScriptCore/bytecode/SpeculatedType.h \
Source/JavaScriptCore/bytecode/PutByIdStatus.cpp \
Source/JavaScriptCore/bytecode/PutByIdStatus.h \
Source/JavaScriptCore/bytecode/PutKind.h \
@@ -131,6 +134,8 @@ javascriptcore_sources += \
Source/JavaScriptCore/bytecode/ValueProfile.h \
Source/JavaScriptCore/bytecode/ValueRecovery.h \
Source/JavaScriptCore/bytecode/VirtualRegister.h \
+ Source/JavaScriptCore/bytecode/Watchpoint.cpp \
+ Source/JavaScriptCore/bytecode/Watchpoint.h \
Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp \
Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h \
Source/JavaScriptCore/bytecompiler/Label.h \
@@ -217,6 +222,7 @@ javascriptcore_sources += \
Source/JavaScriptCore/dfg/DFGVariableAccessData.h \
Source/JavaScriptCore/dfg/DFGVirtualRegisterAllocationPhase.cpp \
Source/JavaScriptCore/dfg/DFGVirtualRegisterAllocationPhase.h \
+ Source/JavaScriptCore/disassembler/Disassembler.h \
Source/JavaScriptCore/heap/CopiedAllocator.h \
Source/JavaScriptCore/heap/CopiedBlock.h \
Source/JavaScriptCore/heap/CopiedSpace.cpp \
@@ -232,8 +238,10 @@ javascriptcore_sources += \
Source/JavaScriptCore/heap/HandleSet.cpp \
Source/JavaScriptCore/heap/HandleSet.h \
Source/JavaScriptCore/heap/HeapBlock.h \
- Source/JavaScriptCore/heap/IncrementalSweeper.h \
- Source/JavaScriptCore/heap/IncrementalSweeper.cpp \
+ Source/JavaScriptCore/heap/HeapTimer.h \
+ Source/JavaScriptCore/heap/HeapTimer.cpp \
+ Source/JavaScriptCore/heap/IncrementalSweeper.h \
+ Source/JavaScriptCore/heap/IncrementalSweeper.cpp \
Source/JavaScriptCore/heap/SlotVisitor.h \
Source/JavaScriptCore/heap/HandleStack.cpp \
Source/JavaScriptCore/heap/HandleStack.h \
@@ -357,9 +365,18 @@ javascriptcore_sources += \
Source/JavaScriptCore/jit/SpecializedThunkJIT.h \
Source/JavaScriptCore/jit/ThunkGenerators.cpp \
Source/JavaScriptCore/jit/ThunkGenerators.h \
+ Source/JavaScriptCore/llint/LLIntCommon.h \
+ Source/JavaScriptCore/llint/LLIntData.cpp \
Source/JavaScriptCore/llint/LLIntData.h \
Source/JavaScriptCore/llint/LLIntEntrypoints.cpp \
Source/JavaScriptCore/llint/LLIntEntrypoints.h \
+ Source/JavaScriptCore/llint/LLIntExceptions.cpp \
+ Source/JavaScriptCore/llint/LLIntExceptions.h \
+ Source/JavaScriptCore/llint/LLIntOfflineAsmConfig.h \
+ Source/JavaScriptCore/llint/LLIntSlowPaths.cpp \
+ Source/JavaScriptCore/llint/LLIntSlowPaths.h \
+ Source/JavaScriptCore/llint/LLIntThunks.cpp \
+ Source/JavaScriptCore/llint/LLIntThunks.h \
Source/JavaScriptCore/llint/LowLevelInterpreter.cpp \
Source/JavaScriptCore/llint/LowLevelInterpreter.h \
Source/JavaScriptCore/os-win32/stdbool.h \
@@ -490,6 +507,8 @@ javascriptcore_sources += \
Source/JavaScriptCore/runtime/JSONObject.h \
Source/JavaScriptCore/runtime/JSPropertyNameIterator.cpp \
Source/JavaScriptCore/runtime/JSPropertyNameIterator.h \
+ Source/JavaScriptCore/runtime/JSSegmentedVariableObject.cpp \
+ Source/JavaScriptCore/runtime/JSSegmentedVariableObject.h \
Source/JavaScriptCore/runtime/JSStaticScopeObject.cpp \
Source/JavaScriptCore/runtime/JSStaticScopeObject.h \
Source/JavaScriptCore/runtime/JSStringBuilder.h \
@@ -497,6 +516,8 @@ javascriptcore_sources += \
Source/JavaScriptCore/runtime/JSStringJoiner.h \
Source/JavaScriptCore/runtime/JSString.cpp \
Source/JavaScriptCore/runtime/JSString.h \
+ Source/JavaScriptCore/runtime/JSSymbolTableObject.cpp \
+ Source/JavaScriptCore/runtime/JSSymbolTableObject.h \
Source/JavaScriptCore/runtime/JSType.h \
Source/JavaScriptCore/runtime/JSTypeInfo.h \
Source/JavaScriptCore/runtime/JSValue.cpp \
@@ -588,6 +609,7 @@ javascriptcore_sources += \
Source/JavaScriptCore/runtime/Structure.cpp \
Source/JavaScriptCore/runtime/Structure.h \
Source/JavaScriptCore/runtime/StructureTransitionTable.h \
+ Source/JavaScriptCore/runtime/SymbolTable.cpp \
Source/JavaScriptCore/runtime/SymbolTable.h \
Source/JavaScriptCore/runtime/Terminator.h \
Source/JavaScriptCore/runtime/TimeoutChecker.cpp \
@@ -626,6 +648,27 @@ javascriptcore_sources += \
Source/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp
endif
+llint_nosources += \
+ Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm \
+ Source/JavaScriptCore/llint/LowLevelInterpreter64.asm \
+ Source/JavaScriptCore/llint/LowLevelInterpreter.asm
+
+offlineasm_nosources += \
+ Source/JavaScriptCore/offlineasm/armv7.rb \
+ Source/JavaScriptCore/offlineasm/asm.rb \
+ Source/JavaScriptCore/offlineasm/ast.rb \
+ Source/JavaScriptCore/offlineasm/backends.rb \
+ Source/JavaScriptCore/offlineasm/generate_offset_extractor.rb \
+ Source/JavaScriptCore/offlineasm/instructions.rb \
+ Source/JavaScriptCore/offlineasm/offsets.rb \
+ Source/JavaScriptCore/offlineasm/opt.rb \
+ Source/JavaScriptCore/offlineasm/parser.rb \
+ Source/JavaScriptCore/offlineasm/registers.rb \
+ Source/JavaScriptCore/offlineasm/self_hash.rb \
+ Source/JavaScriptCore/offlineasm/settings.rb \
+ Source/JavaScriptCore/offlineasm/transform.rb \
+ Source/JavaScriptCore/offlineasm/x86.rb
+
# minidom
Programs_minidom_SOURCES = \
Source/JavaScriptCore/API/tests/JSNode.c \
@@ -638,6 +681,9 @@ Programs_minidom_SOURCES = \
Source/JavaScriptCore/API/tests/NodeList.h \
Source/JavaScriptCore/API/tests/minidom.c
+Programs_LLIntOffsetsExtractor_SOURCES = \
+ Source/JavaScriptCore/llint/LLIntOffsetsExtractor.cpp
+
Programs_jsc_@WEBKITGTK_API_MAJOR_VERSION@_SOURCES = \
Source/JavaScriptCore/JSCTypedArrayStubs.h \
Source/JavaScriptCore/jsc.cpp
diff --git a/Source/JavaScriptCore/JavaScriptCore.gyp/JavaScriptCore.gyp b/Source/JavaScriptCore/JavaScriptCore.gyp/JavaScriptCore.gyp
index f0de2f073..8da950f5e 100644
--- a/Source/JavaScriptCore/JavaScriptCore.gyp/JavaScriptCore.gyp
+++ b/Source/JavaScriptCore/JavaScriptCore.gyp/JavaScriptCore.gyp
@@ -84,15 +84,7 @@
'../runtime',
],
'sources': [
- '<@(javascriptcore_files)',
- ],
- 'sources/': [
- # First exclude everything ...
- ['exclude', '../'],
- # ... Then include what we want.
- ['include', '../yarr/'],
- # The Yarr JIT isn't used in WebCore.
- ['exclude', '../yarr/YarrJIT\\.(h|cpp)$'],
+ '<@(javascriptcore_yarr_files)',
],
'export_dependent_settings': [
'../../WTF/WTF.gyp/WTF.gyp:wtf',
diff --git a/Source/JavaScriptCore/JavaScriptCore.gypi b/Source/JavaScriptCore/JavaScriptCore.gypi
index 6f4598f41..1f1802bde 100644
--- a/Source/JavaScriptCore/JavaScriptCore.gypi
+++ b/Source/JavaScriptCore/JavaScriptCore.gypi
@@ -1,595 +1,14 @@
{
'variables': {
'project_dir': ['.'],
- # These headers are part of JavaScriptCore's public API in the Apple Mac build.
- 'javascriptcore_publicheader_files': [
- 'API/APICast.h',
- 'API/APIShims.h',
- 'API/JSBase.h',
- 'API/JSContextRef.h',
- 'API/JSContextRefPrivate.h',
- 'API/JSObjectRef.h',
- 'API/JSObjectRefPrivate.h',
- 'API/JSRetainPtr.h',
- 'API/JSStringRef.h',
- 'API/JSStringRefBSTR.h',
- 'API/JSStringRefCF.h',
- 'API/JSValueRef.h',
- 'API/JSWeakObjectMapRefInternal.h',
- 'API/JSWeakObjectMapRefPrivate.h',
- 'API/JavaScript.h',
- 'API/JavaScriptCore.h',
- 'API/OpaqueJSString.h',
- 'API/WebKitAvailability.h',
- ],
- # These headers are part of JavaScriptCore's private API in the Apple Mac build.
- 'javascriptcore_privateheader_files': [
- 'assembler/AbstractMacroAssembler.h',
- 'assembler/ARMAssembler.h',
- 'assembler/ARMv7Assembler.h',
- 'assembler/AssemblerBuffer.h',
- 'assembler/AssemblerBufferWithConstantPool.h',
- 'assembler/CodeLocation.h',
- 'assembler/LinkBuffer.h',
- 'assembler/MacroAssembler.h',
- 'assembler/MacroAssemblerARM.h',
- 'assembler/MacroAssemblerARMv7.h',
- 'assembler/MacroAssemblerCodeRef.h',
- 'assembler/MacroAssemblerMIPS.h',
- 'assembler/MacroAssemblerSH4.h',
- 'assembler/MacroAssemblerX86.h',
- 'assembler/MacroAssemblerX86Common.h',
- 'assembler/MacroAssemblerX86_64.h',
- 'assembler/MIPSAssembler.h',
- 'assembler/RepatchBuffer.h',
- 'assembler/SH4Assembler.h',
- 'assembler/X86Assembler.h',
- 'bytecode/BytecodeConventions.h',
- 'bytecode/CallLinkInfo.h',
- 'bytecode/CallLinkStatus.h',
- 'bytecode/CallReturnOffsetToBytecodeOffset.h',
- 'bytecode/CodeBlock.h',
- 'bytecode/CodeOrigin.h',
- 'bytecode/CodeType.h',
- 'bytecode/DataFormat.h',
- 'bytecode/DFGExitProfile.h',
- 'bytecode/EvalCodeCache.h',
- 'bytecode/ExecutionCounter.h',
- 'bytecode/ExpressionRangeInfo.h',
- 'bytecode/GetByIdStatus.h',
- 'bytecode/GlobalResolveInfo.h',
- 'bytecode/HandlerInfo.h',
- 'bytecode/Instruction.h',
- 'bytecode/JumpTable.h',
- 'bytecode/LazyOperandValueProfile.h',
- 'bytecode/LineInfo.h',
- 'bytecode/LLIntCallLinkInfo.h',
- 'bytecode/MethodCallLinkInfo.h',
- 'bytecode/MethodCallLinkStatus.h',
- 'bytecode/MethodOfGettingAValueProfile.h',
- 'bytecode/Opcode.h',
- 'bytecode/Operands.h',
- 'bytecode/PolymorphicPutByIdList.h',
- 'bytecode/PredictedType.h',
- 'bytecode/PredictionTracker.h',
- 'bytecode/PutByIdStatus.h',
- 'bytecode/PutKind.h',
- 'bytecode/SamplingTool.h',
- 'bytecode/StructureSet.h',
- 'bytecode/StructureStubInfo.h',
- 'bytecode/ValueProfile.h',
- 'bytecode/ValueRecovery.h',
- 'bytecode/VirtualRegister.h',
- 'dfg/DFGAbstractState.h',
- 'dfg/DFGAbstractValue.h',
- 'dfg/DFGAdjacencyList.h',
- 'dfg/DFGAssemblyHelpers.h',
- 'dfg/DFGBasicBlock.h',
- 'dfg/DFGByteCodeCache.h',
- 'dfg/DFGByteCodeParser.h',
- 'dfg/DFGCapabilities.h',
- 'dfg/DFGCCallHelpers.h',
- 'dfg/DFGCFAPhase.h',
- 'dfg/DFGCommon.h',
- 'dfg/DFGCorrectableJumpPoint.h',
- 'dfg/DFGCSEPhase.h',
- 'dfg/DFGDriver.h',
- 'dfg/DFGEdge.h',
- 'dfg/DFGFixupPhase.h',
- 'dfg/DFGFPRInfo.h',
- 'dfg/DFGGenerationInfo.h',
- 'dfg/DFGGPRInfo.h',
- 'dfg/DFGGraph.h',
- 'dfg/DFGInsertionSet.h',
- 'dfg/DFGJITCompiler.h',
- 'dfg/DFGNode.h',
- 'dfg/DFGNodeFlags.h',
- 'dfg/DFGNodeType.h',
- 'dfg/DFGOperations.h',
- 'dfg/DFGOSREntry.h',
- 'dfg/DFGOSRExit.h',
- 'dfg/DFGOSRExitCompiler.h',
- 'dfg/DFGPhase.h',
- 'dfg/DFGPredictionPropagationPhase.h',
- 'dfg/DFGRedundantPhiEliminationPhase.h',
- 'dfg/DFGRegisterBank.h',
- 'dfg/DFGRepatch.h',
- 'dfg/DFGScoreBoard.h',
- 'dfg/DFGSpeculativeJIT.h',
- 'dfg/DFGThunks.h',
- 'dfg/DFGVariableAccessData.h',
- 'dfg/DFGVirtualRegisterAllocationPhase.h',
- 'heap/CardSet.h',
- 'heap/ConservativeRoots.h',
- 'heap/CopiedAllocator.h',
- 'heap/CopiedBlock.h',
- 'heap/CopiedSpace.h',
- 'heap/CopiedSpaceInlineMethods.h',
- 'heap/DFGCodeBlocks.h',
- 'heap/GCAssertions.h',
- 'heap/Handle.h',
- 'heap/HandleSet.h',
- 'heap/HandleStack.h',
- 'heap/HandleTypes.h',
- 'heap/Heap.h',
- 'heap/HeapBlock.h',
- 'heap/HeapRootVisitor.h',
- 'heap/IncrementalSweeper.h',
- 'heap/ListableHandler.h',
- 'heap/Local.h',
- 'heap/LocalScope.h',
- 'heap/MachineStackMarker.h',
- 'heap/MarkedAllocator.h',
- 'heap/MarkedBlock.h',
- 'heap/MarkedBlockSet.h',
- 'heap/MarkedSpace.h',
- 'heap/MarkStack.h',
- 'heap/PassWeak.h',
- 'heap/SlotVisitor.h',
- 'heap/Strong.h',
- 'heap/StrongInlines.h',
- 'heap/TinyBloomFilter.h',
- 'heap/UnconditionalFinalizer.h',
- 'heap/VTableSpectrum.h',
- 'heap/Weak.h',
- 'heap/WeakBlock.h',
- 'heap/WeakHandleOwner.h',
- 'heap/WeakImpl.h',
- 'heap/WeakReferenceHarvester.h',
- 'heap/WeakSet.h',
- 'heap/WeakSetInlines.h',
- 'heap/WriteBarrierSupport.h',
- 'debugger/Debugger.h',
- 'debugger/DebuggerActivation.h',
- 'debugger/DebuggerCallFrame.h',
- 'interpreter/AbstractPC.h',
- 'interpreter/CachedCall.h',
- 'interpreter/CallFrame.h',
- 'interpreter/CallFrameClosure.h',
- 'interpreter/Interpreter.h',
- 'interpreter/Register.h',
- 'interpreter/RegisterFile.h',
- 'jit/CompactJITCodeMap.h',
- 'jit/ExecutableAllocator.h',
- 'jit/HostCallReturnValue.h',
- 'jit/JIT.h',
- 'jit/JITCode.h',
- 'jit/JITCompilationEffort.h',
- 'jit/JITDriver.h',
- 'jit/JITExceptions.h',
- 'jit/JITInlineMethods.h',
- 'jit/JITStubCall.h',
- 'jit/JITStubs.h',
- 'jit/JITWriteBarrier.h',
- 'jit/JSInterfaceJIT.h',
- 'jit/SpecializedThunkJIT.h',
- 'jit/ThunkGenerators.h',
- 'parser/ASTBuilder.h',
- 'parser/Lexer.h',
- 'parser/NodeConstructors.h',
- 'parser/NodeInfo.h',
- 'parser/Nodes.h',
- 'parser/Parser.h',
- 'parser/ParserArena.h',
- 'parser/ParserTokens.h',
- 'parser/ResultType.h',
- 'parser/SourceCode.h',
- 'parser/SourceProvider.h',
- 'parser/SourceProviderCache.h',
- 'parser/SourceProviderCacheItem.h',
- 'parser/SyntaxChecker.h',
- 'profiler/CallIdentifier.h',
- 'profiler/Profile.h',
- 'profiler/ProfileGenerator.h',
- 'profiler/ProfileNode.h',
- 'profiler/Profiler.h',
- 'runtime/ArgList.h',
- 'runtime/Arguments.h',
- 'runtime/ArrayConstructor.h',
- 'runtime/ArrayPrototype.h',
- 'runtime/BatchedTransitionOptimizer.h',
- 'runtime/BigInteger.h',
- 'runtime/BooleanConstructor.h',
- 'runtime/BooleanObject.h',
- 'runtime/BooleanPrototype.h',
- 'runtime/CachedTranscendentalFunction.h',
- 'runtime/CallData.h',
- 'runtime/ClassInfo.h',
- 'runtime/CodeSpecializationKind.h',
- 'runtime/CommonIdentifiers.h',
- 'runtime/CommonSlowPaths.h',
- 'runtime/Completion.h',
- 'runtime/ConstructData.h',
- 'runtime/DateConstructor.h',
- 'runtime/DateConversion.h',
- 'runtime/DateInstance.h',
- 'runtime/DateInstanceCache.h',
- 'runtime/DatePrototype.h',
- 'runtime/Error.h',
- 'runtime/ErrorConstructor.h',
- 'runtime/ErrorInstance.h',
- 'runtime/ErrorPrototype.h',
- 'runtime/ExceptionHelpers.h',
- 'runtime/Executable.h',
- 'runtime/ExecutionHarness.h',
- 'runtime/FunctionConstructor.h',
- 'runtime/FunctionPrototype.h',
- 'runtime/GCActivityCallback.h',
- 'runtime/GetterSetter.h',
- 'runtime/Identifier.h',
- 'runtime/InitializeThreading.h',
- 'runtime/InternalFunction.h',
- 'runtime/Intrinsic.h',
- 'runtime/JSActivation.h',
- 'runtime/JSAPIValueWrapper.h',
- 'runtime/JSArray.h',
- 'runtime/JSBoundFunction.h',
- 'runtime/JSCell.h',
- 'runtime/JSChunk.h',
- 'runtime/JSDateMath.h',
- 'runtime/JSExportMacros.h',
- 'runtime/JSFunction.h',
- 'runtime/JSGlobalData.h',
- 'runtime/JSGlobalObject.h',
- 'runtime/JSGlobalObjectFunctions.h',
- 'runtime/JSGlobalThis.h',
- 'runtime/JSLock.h',
- 'runtime/JSNotAnObject.h',
- 'runtime/JSObject.h',
- 'runtime/JSONObject.h',
- 'runtime/JSPropertyNameIterator.h',
- 'runtime/JSStaticScopeObject.h',
- 'runtime/JSString.h',
- 'runtime/JSStringBuilder.h',
- 'runtime/JSStringJoiner.h',
- 'runtime/JSType.h',
- 'runtime/JSTypeInfo.h',
- 'runtime/JSValue.h',
- 'runtime/JSValueInlineMethods.h',
- 'runtime/JSVariableObject.h',
- 'runtime/JSWrapperObject.h',
- 'runtime/LiteralParser.h',
- 'runtime/Lookup.h',
- 'runtime/MatchResult.h',
- 'runtime/MathObject.h',
- 'runtime/MemoryStatistics.h',
- 'runtime/NameConstructor.h',
- 'runtime/NameInstance.h',
- 'runtime/NamePrototype.h',
- 'runtime/NativeErrorConstructor.h',
- 'runtime/NativeErrorPrototype.h',
- 'runtime/NumberConstructor.h',
- 'runtime/NumberObject.h',
- 'runtime/NumberPrototype.h',
- 'runtime/NumericStrings.h',
- 'runtime/ObjectConstructor.h',
- 'runtime/ObjectPrototype.h',
- 'runtime/Operations.h',
- 'runtime/Options.h',
- 'runtime/PropertyDescriptor.h',
- 'runtime/PropertyMapHashTable.h',
- 'runtime/PropertyNameArray.h',
- 'runtime/PropertySlot.h',
- 'runtime/Protect.h',
- 'runtime/PutPropertySlot.h',
- 'runtime/RegExp.h',
- 'runtime/RegExpCache.h',
- 'runtime/RegExpCachedResult.h',
- 'runtime/RegExpConstructor.h',
- 'runtime/RegExpKey.h',
- 'runtime/RegExpMatchesArray.h',
- 'runtime/RegExpObject.h',
- 'runtime/RegExpPrototype.h',
- 'runtime/SamplingCounter.h',
- 'runtime/ScopeChain.h',
- 'runtime/ScopeChainMark.h',
- 'runtime/SmallStrings.h',
- 'runtime/StorageBarrier.h',
- 'runtime/StrictEvalActivation.h',
- 'runtime/StringConstructor.h',
- 'runtime/StringObject.h',
- 'runtime/StringPrototype.h',
- 'runtime/StringRecursionChecker.h',
- 'runtime/Structure.h',
- 'runtime/StructureChain.h',
- 'runtime/StructureTransitionTable.h',
- 'runtime/SymbolTable.h',
- 'runtime/Terminator.h',
- 'runtime/TimeoutChecker.h',
- 'runtime/Tracing.h',
- 'runtime/Uint16WithFraction.h',
- 'runtime/UString.h',
- 'runtime/UStringBuilder.h',
- 'runtime/UStringConcatenate.h',
- 'runtime/WeakGCMap.h',
- 'runtime/WeakRandom.h',
- 'runtime/WriteBarrier.h',
- 'yarr/Yarr.h',
- 'yarr/YarrCanonicalizeUCS2.h',
- 'yarr/YarrInterpreter.h',
- 'yarr/YarrJIT.h',
- 'yarr/YarrParser.h',
- 'yarr/YarrPattern.h',
- 'yarr/YarrSyntaxChecker.h',
- ],
- 'javascriptcore_files': [
- 'API/JSBase.cpp',
- 'API/JSCallbackConstructor.cpp',
- 'API/JSCallbackFunction.cpp',
- 'API/JSCallbackObject.cpp',
- 'API/JSClassRef.cpp',
- 'API/JSContextRef.cpp',
- 'API/JSObjectRef.cpp',
- 'API/JSProfilerPrivate.cpp',
- 'API/JSStringRef.cpp',
- 'API/JSStringRefBSTR.cpp',
- 'API/JSStringRefCF.cpp',
- 'API/JSValueRef.cpp',
- 'API/JSWeakObjectMapRefPrivate.cpp',
- 'API/OpaqueJSString.cpp',
- 'assembler/ARMAssembler.cpp',
- 'assembler/ARMv7Assembler.cpp',
- 'assembler/MacroAssemblerARM.cpp',
- 'assembler/MacroAssemblerSH4.cpp',
- 'bytecode/CallLinkInfo.cpp',
- 'bytecode/CallLinkStatus.cpp',
- 'bytecode/CodeBlock.cpp',
- 'bytecode/DFGExitProfile.cpp',
- 'bytecode/ExecutionCounter.cpp',
- 'bytecode/GetByIdStatus.cpp',
- 'bytecode/JumpTable.cpp',
- 'bytecode/LazyOperandValueProfile.cpp',
- 'bytecode/MethodCallLinkInfo.cpp',
- 'bytecode/MethodCallLinkStatus.cpp',
- 'bytecode/MethodOfGettingAValueProfile.cpp',
- 'bytecode/Opcode.cpp',
- 'bytecode/PolymorphicPutByIdList.cpp',
- 'bytecode/PredictedType.cpp',
- 'bytecode/PutByIdStatus.cpp',
- 'bytecode/SamplingTool.cpp',
- 'bytecode/StructureStubInfo.cpp',
- 'bytecompiler/BytecodeGenerator.cpp',
- 'bytecompiler/NodesCodegen.cpp',
- 'debugger/Debugger.cpp',
- 'debugger/DebuggerActivation.cpp',
- 'debugger/DebuggerCallFrame.cpp',
- 'dfg/DFGAbstractState.cpp',
- 'dfg/DFGAssemblyHelpers.cpp',
- 'dfg/DFGByteCodeParser.cpp',
- 'dfg/DFGCapabilities.cpp',
- 'dfg/DFGCFAPhase.cpp',
- 'dfg/DFGCorrectableJumpPoint.cpp',
- 'dfg/DFGCSEPhase.cpp',
- 'dfg/DFGDriver.cpp',
- 'dfg/DFGFixupPhase.cpp',
- 'dfg/DFGGraph.cpp',
- 'dfg/DFGJITCompiler.cpp',
- 'dfg/DFGNodeFlags.cpp',
- 'dfg/DFGOperations.cpp',
- 'dfg/DFGOSREntry.cpp',
- 'dfg/DFGOSRExit.cpp',
- 'dfg/DFGOSRExitCompiler.cpp',
- 'dfg/DFGOSRExitCompiler32_64.cpp',
- 'dfg/DFGOSRExitCompiler64.cpp',
- 'dfg/DFGPhase.cpp',
- 'dfg/DFGPredictionPropagationPhase.cpp',
- 'dfg/DFGRedundantPhiEliminationPhase.cpp',
- 'dfg/DFGRepatch.cpp',
- 'dfg/DFGSpeculativeJIT.cpp',
- 'dfg/DFGSpeculativeJIT32_64.cpp',
- 'dfg/DFGSpeculativeJIT64.cpp',
- 'dfg/DFGThunks.cpp',
- 'dfg/DFGVirtualRegisterAllocationPhase.cpp',
- 'heap/ConservativeRoots.cpp',
- 'heap/CopiedSpace.cpp',
- 'heap/DFGCodeBlocks.cpp',
- 'heap/HandleSet.cpp',
- 'heap/HandleStack.cpp',
- 'heap/BlockAllocator.cpp',
- 'heap/Heap.cpp',
- 'heap/IncrementalSweeper.cpp',
- 'heap/MachineStackMarker.cpp',
- 'heap/MarkedAllocator.cpp',
- 'heap/MarkedBlock.cpp',
- 'heap/MarkedSpace.cpp',
- 'heap/MarkStack.cpp',
- 'heap/VTableSpectrum.cpp',
- 'heap/WeakBlock.cpp',
- 'heap/WeakHandleOwner.cpp',
- 'heap/WeakSet.cpp',
- 'heap/WriteBarrierSupport.cpp',
- 'interpreter/AbstractPC.cpp',
- 'interpreter/CallFrame.cpp',
- 'interpreter/Interpreter.cpp',
- 'interpreter/RegisterFile.cpp',
- 'jit/ExecutableAllocator.cpp',
- 'jit/ExecutableAllocatorFixedVMPool.cpp',
- 'jit/HostCallReturnValue.cpp',
- 'jit/JIT.cpp',
- 'jit/JITArithmetic.cpp',
- 'jit/JITArithmetic32_64.cpp',
- 'jit/JITCall.cpp',
- 'jit/JITCall32_64.cpp',
- 'jit/JITExceptions.cpp',
- 'jit/JITOpcodes.cpp',
- 'jit/JITOpcodes32_64.cpp',
- 'jit/JITPropertyAccess.cpp',
- 'jit/JITPropertyAccess32_64.cpp',
- 'jit/JITStubs.cpp',
- 'jit/ThunkGenerators.cpp',
- 'parser/Lexer.cpp',
- 'parser/Nodes.cpp',
- 'parser/Parser.cpp',
- 'parser/ParserArena.cpp',
- 'parser/SourceProviderCache.cpp',
- 'profiler/Profile.cpp',
- 'profiler/ProfileGenerator.cpp',
- 'profiler/ProfileNode.cpp',
- 'profiler/Profiler.cpp',
- 'runtime/ArgList.cpp',
- 'runtime/Arguments.cpp',
- 'runtime/ArrayConstructor.cpp',
- 'runtime/ArrayPrototype.cpp',
- 'runtime/BooleanConstructor.cpp',
- 'runtime/BooleanObject.cpp',
- 'runtime/BooleanPrototype.cpp',
- 'runtime/CallData.cpp',
- 'runtime/CommonIdentifiers.cpp',
- 'runtime/Completion.cpp',
- 'runtime/ConstructData.cpp',
- 'runtime/DateConstructor.cpp',
- 'runtime/DateConversion.cpp',
- 'runtime/DateInstance.cpp',
- 'runtime/DatePrototype.cpp',
- 'runtime/Error.cpp',
- 'runtime/ErrorConstructor.cpp',
- 'runtime/ErrorInstance.cpp',
- 'runtime/ErrorPrototype.cpp',
- 'runtime/ExceptionHelpers.cpp',
- 'runtime/Executable.cpp',
- 'runtime/FunctionConstructor.cpp',
- 'runtime/FunctionPrototype.cpp',
- 'runtime/GCActivityCallback.cpp',
- 'runtime/GCActivityCallbackCF.cpp',
- 'runtime/GetterSetter.cpp',
- 'runtime/Identifier.cpp',
- 'runtime/InitializeThreading.cpp',
- 'runtime/InternalFunction.cpp',
- 'runtime/JSActivation.cpp',
- 'runtime/JSAPIValueWrapper.cpp',
- 'runtime/JSArray.cpp',
- 'runtime/JSBoundFunction.cpp',
- 'runtime/JSCell.cpp',
- 'runtime/JSChunk.cpp',
- 'runtime/JSDateMath.cpp',
- 'runtime/JSFunction.cpp',
- 'runtime/JSGlobalData.cpp',
- 'runtime/JSGlobalObject.cpp',
- 'runtime/JSGlobalObjectFunctions.cpp',
- 'runtime/JSGlobalThis.cpp',
- 'runtime/JSLock.cpp',
- 'runtime/JSNotAnObject.cpp',
- 'runtime/JSObject.cpp',
- 'runtime/JSONObject.cpp',
- 'runtime/JSPropertyNameIterator.cpp',
- 'runtime/JSStaticScopeObject.cpp',
- 'runtime/JSString.cpp',
- 'runtime/JSStringJoiner.cpp',
- 'runtime/JSValue.cpp',
- 'runtime/JSVariableObject.cpp',
- 'runtime/JSWrapperObject.cpp',
- 'runtime/LiteralParser.cpp',
- 'runtime/Lookup.cpp',
- 'runtime/MathObject.cpp',
- 'runtime/MemoryStatistics.cpp',
- 'runtime/NameConstructor.cpp',
- 'runtime/NameInstance.cpp',
- 'runtime/NamePrototype.cpp',
- 'runtime/NativeErrorConstructor.cpp',
- 'runtime/NativeErrorPrototype.cpp',
- 'runtime/NumberConstructor.cpp',
- 'runtime/NumberObject.cpp',
- 'runtime/NumberPrototype.cpp',
- 'runtime/ObjectConstructor.cpp',
- 'runtime/ObjectPrototype.cpp',
- 'runtime/Operations.cpp',
- 'runtime/Options.cpp',
- 'runtime/PropertyDescriptor.cpp',
- 'runtime/PropertyNameArray.cpp',
- 'runtime/PropertySlot.cpp',
- 'runtime/RegExp.cpp',
- 'runtime/RegExpCache.cpp',
- 'runtime/RegExpCachedResult.cpp',
- 'runtime/RegExpConstructor.cpp',
- 'runtime/RegExpMatchesArray.cpp',
- 'runtime/RegExpObject.cpp',
- 'runtime/RegExpPrototype.cpp',
- 'runtime/SamplingCounter.cpp',
- 'runtime/ScopeChain.cpp',
- 'runtime/SmallStrings.cpp',
- 'runtime/StrictEvalActivation.cpp',
- 'runtime/StringConstructor.cpp',
- 'runtime/StringObject.cpp',
- 'runtime/StringPrototype.cpp',
- 'runtime/StringRecursionChecker.cpp',
- 'runtime/Structure.cpp',
- 'runtime/StructureChain.cpp',
- 'runtime/TimeoutChecker.cpp',
- 'runtime/UString.cpp',
- 'tools/CodeProfile.cpp',
- 'tools/CodeProfiling.cpp',
+ 'javascriptcore_yarr_files': [
'yarr/YarrCanonicalizeUCS2.cpp',
'yarr/YarrInterpreter.cpp',
- 'yarr/YarrJIT.cpp',
'yarr/YarrPattern.cpp',
'yarr/YarrSyntaxChecker.cpp',
],
'javascriptcore_derived_source_files': [
- '<(PRODUCT_DIR)/DerivedSources/JavaScriptCore/Lexer.lut.h',
'<(PRODUCT_DIR)/DerivedSources/JavaScriptCore/RegExpJitTables.h',
- '<(PRODUCT_DIR)/DerivedSources/JavaScriptCore/TracingDtrace.h',
- '<(PRODUCT_DIR)/DerivedSources/JavaScriptCore/ArrayConstructor.lut.h',
- '<(PRODUCT_DIR)/DerivedSources/JavaScriptCore/ArrayPrototype.lut.h',
- '<(PRODUCT_DIR)/DerivedSources/JavaScriptCore/BooleanPrototype.lut.h',
- '<(PRODUCT_DIR)/DerivedSources/JavaScriptCore/DateConstructor.lut.h',
- '<(PRODUCT_DIR)/DerivedSources/JavaScriptCore/DatePrototype.lut.h',
- '<(PRODUCT_DIR)/DerivedSources/JavaScriptCore/ErrorPrototype.lut.h',
- '<(PRODUCT_DIR)/DerivedSources/JavaScriptCore/JSGlobalObject.lut.h',
- '<(PRODUCT_DIR)/DerivedSources/JavaScriptCore/JSONObject.lut.h',
- '<(PRODUCT_DIR)/DerivedSources/JavaScriptCore/MathObject.lut.h',
- '<(PRODUCT_DIR)/DerivedSources/JavaScriptCore/NamePrototype.lut.h',
- '<(PRODUCT_DIR)/DerivedSources/JavaScriptCore/NumberConstructor.lut.h',
- '<(PRODUCT_DIR)/DerivedSources/JavaScriptCore/NumberPrototype.lut.h',
- '<(PRODUCT_DIR)/DerivedSources/JavaScriptCore/ObjectConstructor.lut.h',
- '<(PRODUCT_DIR)/DerivedSources/JavaScriptCore/ObjectPrototype.lut.h',
- '<(PRODUCT_DIR)/DerivedSources/JavaScriptCore/RegExpConstructor.lut.h',
- '<(PRODUCT_DIR)/DerivedSources/JavaScriptCore/RegExpObject.lut.h',
- '<(PRODUCT_DIR)/DerivedSources/JavaScriptCore/RegExpPrototype.lut.h',
- '<(PRODUCT_DIR)/DerivedSources/JavaScriptCore/StringConstructor.lut.h',
- '<(PRODUCT_DIR)/DerivedSources/JavaScriptCore/StringPrototype.lut.h',
- ],
- 'minidom_files': [
- 'API/tests/JSNode.c',
- 'API/tests/JSNode.h',
- 'API/tests/JSNodeList.c',
- 'API/tests/JSNodeList.h',
- 'API/tests/Node.c',
- 'API/tests/Node.h',
- 'API/tests/NodeList.c',
- 'API/tests/NodeList.h',
- 'API/tests/minidom.c',
- ],
- 'minidom_support_files': [
- 'API/tests/minidom.js',
- ],
- 'testapi_files': [
- 'API/tests/testapi.c',
- ],
- 'testapi_support_files': [
- 'API/tests/testapi.js',
- ],
- 'jsc_files': [
- 'jsc.cpp',
],
}
}
diff --git a/Source/JavaScriptCore/JavaScriptCore.pri b/Source/JavaScriptCore/JavaScriptCore.pri
index 94b663a18..380bbaf1b 100644
--- a/Source/JavaScriptCore/JavaScriptCore.pri
+++ b/Source/JavaScriptCore/JavaScriptCore.pri
@@ -19,6 +19,7 @@ INCLUDEPATH += \
$$SOURCE_DIR/heap \
$$SOURCE_DIR/dfg \
$$SOURCE_DIR/debugger \
+ $$SOURCE_DIR/disassembler \
$$SOURCE_DIR/interpreter \
$$SOURCE_DIR/jit \
$$SOURCE_DIR/llint \
diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def
index 6d5828c44..365038cee 100755
--- a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def
+++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def
@@ -140,7 +140,7 @@ EXPORTS
?deleteOwnedPtr@WTF@@YAXPAUHFONT__@@@Z
?deleteOwnedPtr@WTF@@YAXPAUHRGN__@@@Z
?deleteProperty@JSObject@JSC@@SA_NPAVJSCell@2@PAVExecState@2@VPropertyName@2@@Z
- ?deleteProperty@JSVariableObject@JSC@@SA_NPAVJSCell@2@PAVExecState@2@VPropertyName@2@@Z
+ ?deleteProperty@JSSymbolTableObject@JSC@@SA_NPAVJSCell@2@PAVExecState@2@VPropertyName@2@@Z
?deletePropertyByIndex@JSObject@JSC@@SA_NPAVJSCell@2@PAVExecState@2@I@Z
?deleteTable@HashTable@JSC@@QBEXXZ
?despecifyDictionaryFunction@Structure@JSC@@QAEXAAVJSGlobalData@2@VPropertyName@2@@Z
@@ -151,7 +151,7 @@ EXPORTS
?detach@Debugger@JSC@@UAEXPAVJSGlobalObject@2@@Z
?detachThread@WTF@@YAXI@Z
?didTimeOut@TimeoutChecker@JSC@@QAE_NPAVExecState@2@@Z
- ?discardAllCompiledCode@Heap@JSC@@QAEXXZ
+ ?deleteAllCompiledCode@Heap@JSC@@QAEXXZ
?displayName@JSFunction@JSC@@QAE?BVUString@2@PAVExecState@2@@Z
?dtoa@WTF@@YAXQADNAA_NAAHAAI@Z
?dumpSampleData@JSGlobalData@JSC@@QAEXPAVExecState@2@@Z
@@ -181,6 +181,7 @@ EXPORTS
?finishCreation@RegExpObject@JSC@@IAEXPAVJSGlobalObject@2@@Z
?finishCreation@StringObject@JSC@@IAEXAAVJSGlobalData@2@PAVJSString@2@@Z
?focus@Profile@JSC@@QAEXPBVProfileNode@2@@Z
+ ?freeFatEntrySlow@SymbolTableEntry@JSC@@AAEXXZ
?from@Identifier@JSC@@SA?AV12@PAVExecState@2@H@Z
?from@Identifier@JSC@@SA?AV12@PAVExecState@2@I@Z
?functionGetter@PropertySlot@JSC@@ABE?AVJSValue@2@PAVExecState@2@@Z
@@ -194,7 +195,7 @@ EXPORTS
?getOwnPropertyDescriptor@JSGlobalObject@JSC@@SA_NPAVJSObject@2@PAVExecState@2@VPropertyName@2@AAVPropertyDescriptor@2@@Z
?getOwnPropertyDescriptor@JSObject@JSC@@SA_NPAV12@PAVExecState@2@VPropertyName@2@AAVPropertyDescriptor@2@@Z
?getOwnPropertyNames@JSObject@JSC@@SAXPAV12@PAVExecState@2@AAVPropertyNameArray@2@W4EnumerationMode@2@@Z
- ?getOwnPropertyNames@JSVariableObject@JSC@@SAXPAVJSObject@2@PAVExecState@2@AAVPropertyNameArray@2@W4EnumerationMode@2@@Z
+ ?getOwnPropertyNames@JSSymbolTableObject@JSC@@SAXPAVJSObject@2@PAVExecState@2@AAVPropertyNameArray@2@W4EnumerationMode@2@@Z
?getOwnPropertySlot@JSGlobalObject@JSC@@SA_NPAVJSCell@2@PAVExecState@2@VPropertyName@2@AAVPropertySlot@2@@Z
?getOwnPropertySlotByIndex@JSArray@JSC@@SA_NPAVJSCell@2@PAVExecState@2@IAAVPropertySlot@2@@Z
?getOwnPropertySlotByIndex@JSObject@JSC@@SA_NPAVJSCell@2@PAVExecState@2@IAAVPropertySlot@2@@Z
@@ -246,6 +247,7 @@ EXPORTS
?name@JSFunction@JSC@@QAEABVUString@2@PAVExecState@2@@Z
?neuter@ArrayBufferView@WTF@@MAEXXZ
?newUninitialized@CString@WTF@@SA?AV12@IAAPAD@Z
+ ?notifyWriteSlow@SymbolTableEntry@JSC@@AAEXXZ
?nullptr@@3Vnullptr_t@std@@A
?number@String@WTF@@SA?AV12@NII@Z
?number@UString@JSC@@SA?AV12@H@Z
diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj
index 21884df96..78ca7dd6e 100644
--- a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj
+++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj
@@ -874,6 +874,14 @@
>
</File>
<File
+ RelativePath="..\..\runtime\JSSegmentedVariableObject.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\runtime\JSSegmentedVariableObject.h"
+ >
+ </File>
+ <File
RelativePath="..\..\runtime\JSStaticScopeObject.cpp"
>
</File>
@@ -898,6 +906,14 @@
>
</File>
<File
+ RelativePath="..\..\runtime\JSSymbolTableObject.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\runtime\JSSymbolTableObject.h"
+ >
+ </File>
+ <File
RelativePath="..\..\runtime\JSType.h"
>
</File>
@@ -1238,6 +1254,10 @@
>
</File>
<File
+ RelativePath="..\..\runtime\SymbolTable.cpp"
+ >
+ </File>
+ <File
RelativePath="..\..\runtime\SymbolTable.h"
>
</File>
@@ -1630,11 +1650,11 @@
>
</File>
<File
- RelativePath="..\..\bytecode\PredictedType.cpp"
+ RelativePath="..\..\bytecode\SpeculatedType.cpp"
>
</File>
<File
- RelativePath="..\..\bytecode\PredictedType.h"
+ RelativePath="..\..\bytecode\SpeculatedType.h"
>
</File>
<File
@@ -1665,6 +1685,14 @@
RelativePath="..\..\bytecode\ValueProfile.h"
>
</File>
+ <File
+ RelativePath="..\..\bytecode\Watchpoint.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\bytecode\Watchpoint.h"
+ >
+ </File>
</Filter>
<Filter
Name="debugger"
@@ -1710,6 +1738,10 @@
>
</File>
<File
+ RelativePath="..\..\assembler\LinkBuffer.cpp"
+ >
+ </File>
+ <File
RelativePath="..\..\assembler\LinkBuffer.h"
>
</File>
@@ -1911,6 +1943,14 @@
</File>
</Filter>
<Filter
+ Name="disassembler"
+ >
+ <File
+ RelativePath="..\..\disassembler\Disassembler.h"
+ >
+ </File>
+ </Filter>
+ <Filter
Name="interpreter"
>
<File
@@ -2158,6 +2198,14 @@
>
</File>
<File
+ RelativePath="..\..\heap\HeapTimer.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\heap\HeapTimer.h"
+ >
+ </File>
+ <File
RelativePath="..\..\heap\IncrementalSweeper.h"
>
</File>
diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreCommon.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreCommon.vsprops
index fac0af564..df0724e7c 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/;../../llint/;../../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;$(ConfigurationBuildDir)\include\private\JavaScriptCore&quot;;&quot;$(WebKitLibrariesDir)\include\pthreads&quot;"
+ AdditionalIncludeDirectories="&quot;$(ConfigurationBuildDir)\obj\JavaScriptCore\DerivedSources\&quot;;../../;../../API/;../../parser/;../../bytecompiler/;../../dfg/;../../disassembler;../../jit/;../../llint/;../../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;$(ConfigurationBuildDir)\include\private\JavaScriptCore&quot;;&quot;$(WebKitLibrariesDir)\include\pthreads&quot;"
PreprocessorDefinitions="__STD_C"
ForcedIncludeFiles="ICUVersion.h"
/>
diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/copy-files.cmd b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/copy-files.cmd
index 524e38037..0a32c319a 100755
--- a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/copy-files.cmd
+++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/copy-files.cmd
@@ -39,6 +39,7 @@ for %%d in (
assembler
bytecode
dfg
+ disassembler
heap
debugger
interpreter
diff --git a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj b/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
index 386fcd391..2ffc9e266 100644
--- a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
+++ b/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
@@ -135,6 +135,13 @@
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, ); }; };
+ 0F919D0C157EE09F004A4E7D /* JSSymbolTableObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F919D09157EE09D004A4E7D /* JSSymbolTableObject.cpp */; };
+ 0F919D0D157EE0A2004A4E7D /* JSSymbolTableObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F919D0A157EE09D004A4E7D /* JSSymbolTableObject.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 0F919D10157F3329004A4E7D /* JSSegmentedVariableObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F919D0E157F3327004A4E7D /* JSSegmentedVariableObject.cpp */; };
+ 0F919D11157F332C004A4E7D /* JSSegmentedVariableObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F919D0F157F3327004A4E7D /* JSSegmentedVariableObject.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 0F919D2515853CE0004A4E7D /* Watchpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F919D2215853CDE004A4E7D /* Watchpoint.cpp */; };
+ 0F919D2615853CE3004A4E7D /* Watchpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F919D2315853CDE004A4E7D /* Watchpoint.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 0F919D2815856773004A4E7D /* SymbolTable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F919D2715856770004A4E7D /* SymbolTable.cpp */; };
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 */; };
@@ -180,12 +187,28 @@
0FD81AD3154FB4F000983E72 /* DFGDominators.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD81AD0154FB4EB00983E72 /* DFGDominators.h */; settings = {ATTRIBUTES = (Private, ); }; };
0FD82E2114172CE300179C94 /* DFGCapabilities.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FD82E1E14172C2F00179C94 /* DFGCapabilities.cpp */; };
0FD82E39141AB14D00179C94 /* CompactJITCodeMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD82E37141AB14200179C94 /* CompactJITCodeMap.h */; settings = {ATTRIBUTES = (Private, ); }; };
- 0FD82E54141DAEEE00179C94 /* PredictedType.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD82E4F141DAEA100179C94 /* PredictedType.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 0FD82E54141DAEEE00179C94 /* SpeculatedType.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD82E4F141DAEA100179C94 /* SpeculatedType.h */; settings = {ATTRIBUTES = (Private, ); }; };
0FD82E56141DAF0800179C94 /* DFGOSREntry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FD82E52141DAEDE00179C94 /* DFGOSREntry.cpp */; };
0FD82E57141DAF1000179C94 /* DFGOSREntry.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD82E53141DAEDE00179C94 /* DFGOSREntry.h */; settings = {ATTRIBUTES = (Private, ); }; };
- 0FD82E86141F3FF100179C94 /* PredictedType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FD82E84141F3FDA00179C94 /* PredictedType.cpp */; };
+ 0FD82E86141F3FF100179C94 /* SpeculatedType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FD82E84141F3FDA00179C94 /* SpeculatedType.cpp */; };
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 */; };
+ 0FF42731158EBD54004CB9FF /* Disassembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FF4272F158EBD44004CB9FF /* Disassembler.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 0FF42732158EBD58004CB9FF /* UDis86Disassembler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FF42730158EBD44004CB9FF /* UDis86Disassembler.cpp */; };
+ 0FF42740158EBE8B004CB9FF /* udis86_decode.c in Sources */ = {isa = PBXBuildFile; fileRef = 0FF42734158EBD94004CB9FF /* udis86_decode.c */; };
+ 0FF42741158EBE8D004CB9FF /* udis86_decode.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FF42735158EBD94004CB9FF /* udis86_decode.h */; };
+ 0FF42742158EBE91004CB9FF /* udis86_extern.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FF42736158EBD94004CB9FF /* udis86_extern.h */; };
+ 0FF42743158EBE91004CB9FF /* udis86_input.c in Sources */ = {isa = PBXBuildFile; fileRef = 0FF42737158EBD94004CB9FF /* udis86_input.c */; };
+ 0FF42744158EBE91004CB9FF /* udis86_input.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FF42738158EBD94004CB9FF /* udis86_input.h */; };
+ 0FF42745158EBE91004CB9FF /* udis86_syn-att.c in Sources */ = {isa = PBXBuildFile; fileRef = 0FF42739158EBD94004CB9FF /* udis86_syn-att.c */; };
+ 0FF42746158EBE91004CB9FF /* udis86_syn-intel.c in Sources */ = {isa = PBXBuildFile; fileRef = 0FF4273A158EBD94004CB9FF /* udis86_syn-intel.c */; };
+ 0FF42747158EBE91004CB9FF /* udis86_syn.c in Sources */ = {isa = PBXBuildFile; fileRef = 0FF4273B158EBD94004CB9FF /* udis86_syn.c */; };
+ 0FF42748158EBE91004CB9FF /* udis86_syn.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FF4273C158EBD94004CB9FF /* udis86_syn.h */; };
+ 0FF42749158EBE91004CB9FF /* udis86_types.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FF4273D158EBD94004CB9FF /* udis86_types.h */; };
+ 0FF4274A158EBE91004CB9FF /* udis86.c in Sources */ = {isa = PBXBuildFile; fileRef = 0FF4273E158EBD94004CB9FF /* udis86.c */; };
+ 0FF4274B158EBE91004CB9FF /* udis86.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FF4273F158EBD94004CB9FF /* udis86.h */; };
+ 0FF4274D158EBFE6004CB9FF /* udis86_itab_holder.c in Sources */ = {isa = PBXBuildFile; fileRef = 0FF4274C158EBFE1004CB9FF /* udis86_itab_holder.c */; };
+ 0FF4275715914A20004CB9FF /* LinkBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FF4275615914A20004CB9FF /* LinkBuffer.cpp */; };
0FF922D414F46B410041A24E /* LLIntOffsetsExtractor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F4680A114BA7F8200BFE272 /* LLIntOffsetsExtractor.cpp */; };
0FFFC95714EF90A000C72532 /* DFGCFAPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FFFC94B14EF909500C72532 /* DFGCFAPhase.cpp */; };
0FFFC95814EF90A200C72532 /* DFGCFAPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFFC94C14EF909500C72532 /* DFGCFAPhase.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -366,10 +389,10 @@
7E4EE70F0EBB7A5B005934AA /* StructureChain.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7E4EE70E0EBB7A5B005934AA /* StructureChain.cpp */; };
7EFF00640EC05A9A00AA7C93 /* NodeInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 7EFF00630EC05A9A00AA7C93 /* NodeInfo.h */; };
840480131021A1D9008E7F01 /* JSAPIValueWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = BC0894D60FAFBA2D00001865 /* JSAPIValueWrapper.h */; settings = {ATTRIBUTES = (Private, ); }; };
- 860161E30F3A83C100F84710 /* AbstractMacroAssembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 860161DF0F3A83C100F84710 /* AbstractMacroAssembler.h */; };
- 860161E40F3A83C100F84710 /* MacroAssemblerX86.h in Headers */ = {isa = PBXBuildFile; fileRef = 860161E00F3A83C100F84710 /* MacroAssemblerX86.h */; };
- 860161E50F3A83C100F84710 /* MacroAssemblerX86_64.h in Headers */ = {isa = PBXBuildFile; fileRef = 860161E10F3A83C100F84710 /* MacroAssemblerX86_64.h */; };
- 860161E60F3A83C100F84710 /* MacroAssemblerX86Common.h in Headers */ = {isa = PBXBuildFile; fileRef = 860161E20F3A83C100F84710 /* MacroAssemblerX86Common.h */; };
+ 860161E30F3A83C100F84710 /* AbstractMacroAssembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 860161DF0F3A83C100F84710 /* AbstractMacroAssembler.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 860161E40F3A83C100F84710 /* MacroAssemblerX86.h in Headers */ = {isa = PBXBuildFile; fileRef = 860161E00F3A83C100F84710 /* MacroAssemblerX86.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 860161E50F3A83C100F84710 /* MacroAssemblerX86_64.h in Headers */ = {isa = PBXBuildFile; fileRef = 860161E10F3A83C100F84710 /* MacroAssemblerX86_64.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 860161E60F3A83C100F84710 /* MacroAssemblerX86Common.h in Headers */ = {isa = PBXBuildFile; fileRef = 860161E20F3A83C100F84710 /* MacroAssemblerX86Common.h */; settings = {ATTRIBUTES = (Private, ); }; };
8604F505143CE1C200B295F5 /* JSGlobalThis.h in Headers */ = {isa = PBXBuildFile; fileRef = 8604F503143CE1C100B295F5 /* JSGlobalThis.h */; settings = {ATTRIBUTES = (Private, ); }; };
860BD801148EA6F200112B2F /* Intrinsic.h in Headers */ = {isa = PBXBuildFile; fileRef = 86BF642A148DB2B5004DE36A /* Intrinsic.h */; settings = {ATTRIBUTES = (Private, ); }; };
8612E4CD152389EC00C836BE /* MatchResult.h in Headers */ = {isa = PBXBuildFile; fileRef = 8612E4CB1522918400C836BE /* MatchResult.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -397,11 +420,11 @@
869D04AF1193B54D00803475 /* CachedTranscendentalFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = 869D04AE1193B54D00803475 /* CachedTranscendentalFunction.h */; settings = {ATTRIBUTES = (Private, ); }; };
869EBCB70E8C6D4A008722CC /* ResultType.h in Headers */ = {isa = PBXBuildFile; fileRef = 869EBCB60E8C6D4A008722CC /* ResultType.h */; settings = {ATTRIBUTES = (Private, ); }; };
86A90ED00EE7D51F00AB350D /* JITArithmetic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86A90ECF0EE7D51F00AB350D /* JITArithmetic.cpp */; };
- 86ADD1450FDDEA980006EEC2 /* ARMv7Assembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 86ADD1430FDDEA980006EEC2 /* ARMv7Assembler.h */; };
- 86ADD1460FDDEA980006EEC2 /* MacroAssemblerARMv7.h in Headers */ = {isa = PBXBuildFile; fileRef = 86ADD1440FDDEA980006EEC2 /* MacroAssemblerARMv7.h */; };
+ 86ADD1450FDDEA980006EEC2 /* ARMv7Assembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 86ADD1430FDDEA980006EEC2 /* ARMv7Assembler.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 86ADD1460FDDEA980006EEC2 /* MacroAssemblerARMv7.h in Headers */ = {isa = PBXBuildFile; fileRef = 86ADD1440FDDEA980006EEC2 /* MacroAssemblerARMv7.h */; settings = {ATTRIBUTES = (Private, ); }; };
86AE64A8135E5E1C00963012 /* MacroAssemblerSH4.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86AE64A5135E5E1C00963012 /* MacroAssemblerSH4.cpp */; };
- 86AE64A9135E5E1C00963012 /* MacroAssemblerSH4.h in Headers */ = {isa = PBXBuildFile; fileRef = 86AE64A6135E5E1C00963012 /* MacroAssemblerSH4.h */; };
- 86AE64AA135E5E1C00963012 /* SH4Assembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 86AE64A7135E5E1C00963012 /* SH4Assembler.h */; };
+ 86AE64A9135E5E1C00963012 /* MacroAssemblerSH4.h in Headers */ = {isa = PBXBuildFile; fileRef = 86AE64A6135E5E1C00963012 /* MacroAssemblerSH4.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 86AE64AA135E5E1C00963012 /* SH4Assembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 86AE64A7135E5E1C00963012 /* SH4Assembler.h */; settings = {ATTRIBUTES = (Private, ); }; };
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 */; };
@@ -410,8 +433,8 @@
86BB09C1138E381B0056702F /* DFGRepatch.h in Headers */ = {isa = PBXBuildFile; fileRef = 86BB09BF138E381B0056702F /* DFGRepatch.h */; };
86C36EEA0EE1289D00B3DF59 /* MacroAssembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 86C36EE90EE1289D00B3DF59 /* MacroAssembler.h */; settings = {ATTRIBUTES = (Private, ); }; };
86C568E011A213EE0007F7F0 /* MacroAssemblerARM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86C568DD11A213EE0007F7F0 /* MacroAssemblerARM.cpp */; };
- 86C568E111A213EE0007F7F0 /* MacroAssemblerMIPS.h in Headers */ = {isa = PBXBuildFile; fileRef = 86C568DE11A213EE0007F7F0 /* MacroAssemblerMIPS.h */; };
- 86C568E211A213EE0007F7F0 /* MIPSAssembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 86C568DF11A213EE0007F7F0 /* MIPSAssembler.h */; };
+ 86C568E111A213EE0007F7F0 /* MacroAssemblerMIPS.h in Headers */ = {isa = PBXBuildFile; fileRef = 86C568DE11A213EE0007F7F0 /* MacroAssemblerMIPS.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 86C568E211A213EE0007F7F0 /* MIPSAssembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 86C568DF11A213EE0007F7F0 /* MIPSAssembler.h */; settings = {ATTRIBUTES = (Private, ); }; };
86CA032E1038E8440028A609 /* Executable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86CA032D1038E8440028A609 /* Executable.cpp */; };
86CAFEE31035DDE60028A609 /* Executable.h in Headers */ = {isa = PBXBuildFile; fileRef = 86CAFEE21035DDE60028A609 /* Executable.h */; settings = {ATTRIBUTES = (Private, ); }; };
86CC85A10EE79A4700288682 /* JITInlineMethods.h in Headers */ = {isa = PBXBuildFile; fileRef = 86CC85A00EE79A4700288682 /* JITInlineMethods.h */; };
@@ -419,13 +442,13 @@
86CC85C40EE7A89400288682 /* JITPropertyAccess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86CC85C30EE7A89400288682 /* JITPropertyAccess.cpp */; };
86CCEFDE0F413F8900FD7F9E /* JITCode.h in Headers */ = {isa = PBXBuildFile; fileRef = 86CCEFDD0F413F8900FD7F9E /* JITCode.h */; settings = {ATTRIBUTES = (Private, ); }; };
86D3B2C310156BDE002865E7 /* ARMAssembler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86D3B2BF10156BDE002865E7 /* ARMAssembler.cpp */; };
- 86D3B2C410156BDE002865E7 /* ARMAssembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 86D3B2C010156BDE002865E7 /* ARMAssembler.h */; };
- 86D3B2C510156BDE002865E7 /* AssemblerBufferWithConstantPool.h in Headers */ = {isa = PBXBuildFile; fileRef = 86D3B2C110156BDE002865E7 /* AssemblerBufferWithConstantPool.h */; };
- 86D3B2C610156BDE002865E7 /* MacroAssemblerARM.h in Headers */ = {isa = PBXBuildFile; fileRef = 86D3B2C210156BDE002865E7 /* MacroAssemblerARM.h */; };
- 86D3B3C310159D7F002865E7 /* LinkBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = 86D3B3C110159D7F002865E7 /* LinkBuffer.h */; };
- 86D3B3C410159D7F002865E7 /* RepatchBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = 86D3B3C210159D7F002865E7 /* RepatchBuffer.h */; };
+ 86D3B2C410156BDE002865E7 /* ARMAssembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 86D3B2C010156BDE002865E7 /* ARMAssembler.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 86D3B2C510156BDE002865E7 /* AssemblerBufferWithConstantPool.h in Headers */ = {isa = PBXBuildFile; fileRef = 86D3B2C110156BDE002865E7 /* AssemblerBufferWithConstantPool.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 86D3B2C610156BDE002865E7 /* MacroAssemblerARM.h in Headers */ = {isa = PBXBuildFile; fileRef = 86D3B2C210156BDE002865E7 /* MacroAssemblerARM.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 86D3B3C310159D7F002865E7 /* LinkBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = 86D3B3C110159D7F002865E7 /* LinkBuffer.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 86D3B3C410159D7F002865E7 /* RepatchBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = 86D3B3C210159D7F002865E7 /* RepatchBuffer.h */; settings = {ATTRIBUTES = (Private, ); }; };
86DB64640F95C6FC00D7D921 /* ExecutableAllocatorFixedVMPool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86DB64630F95C6FC00D7D921 /* ExecutableAllocatorFixedVMPool.cpp */; };
- 86E116B10FE75AC800B512BC /* CodeLocation.h in Headers */ = {isa = PBXBuildFile; fileRef = 86E116B00FE75AC800B512BC /* CodeLocation.h */; };
+ 86E116B10FE75AC800B512BC /* CodeLocation.h in Headers */ = {isa = PBXBuildFile; fileRef = 86E116B00FE75AC800B512BC /* CodeLocation.h */; settings = {ATTRIBUTES = (Private, ); }; };
86E85539111B9968001AF51E /* JSStringBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = 86E85538111B9968001AF51E /* JSStringBuilder.h */; };
86EBF2FF1560F06A008E9222 /* NameConstructor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86EBF2F91560F036008E9222 /* NameConstructor.cpp */; };
86EBF3001560F06A008E9222 /* NameConstructor.h in Headers */ = {isa = PBXBuildFile; fileRef = 86EBF2FA1560F036008E9222 /* NameConstructor.h */; };
@@ -471,8 +494,8 @@
95F6E6950E5B5F970091E860 /* JSProfilerPrivate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 95988BA90E477BEC00D28D4D /* JSProfilerPrivate.cpp */; };
960097A60EBABB58007A7297 /* LabelScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 960097A50EBABB58007A7297 /* LabelScope.h */; };
960626960FB8EC02009798AB /* JITStubCall.h in Headers */ = {isa = PBXBuildFile; fileRef = 960626950FB8EC02009798AB /* JITStubCall.h */; };
- 9688CB150ED12B4E001D649F /* AssemblerBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = 9688CB130ED12B4E001D649F /* AssemblerBuffer.h */; };
- 9688CB160ED12B4E001D649F /* X86Assembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 9688CB140ED12B4E001D649F /* X86Assembler.h */; };
+ 9688CB150ED12B4E001D649F /* AssemblerBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = 9688CB130ED12B4E001D649F /* AssemblerBuffer.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 9688CB160ED12B4E001D649F /* X86Assembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 9688CB140ED12B4E001D649F /* X86Assembler.h */; settings = {ATTRIBUTES = (Private, ); }; };
969A07230ED1CE3300F1F681 /* BytecodeGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 969A07210ED1CE3300F1F681 /* BytecodeGenerator.h */; };
969A072A0ED1CE6900F1F681 /* Label.h in Headers */ = {isa = PBXBuildFile; fileRef = 969A07270ED1CE6900F1F681 /* Label.h */; };
969A072B0ED1CE6900F1F681 /* RegisterID.h in Headers */ = {isa = PBXBuildFile; fileRef = 969A07280ED1CE6900F1F681 /* RegisterID.h */; };
@@ -644,10 +667,12 @@
C2C8D02D14A3C6E000578E65 /* CopiedSpaceInlineMethods.h in Headers */ = {isa = PBXBuildFile; fileRef = C2C8D02B14A3C6B200578E65 /* CopiedSpaceInlineMethods.h */; settings = {ATTRIBUTES = (Private, ); }; };
C2C8D03014A3CEFC00578E65 /* CopiedBlock.h in Headers */ = {isa = PBXBuildFile; fileRef = C2C8D02E14A3CEFC00578E65 /* CopiedBlock.h */; settings = {ATTRIBUTES = (Private, ); }; };
C2C8D03114A3CEFC00578E65 /* HeapBlock.h in Headers */ = {isa = PBXBuildFile; fileRef = C2C8D02F14A3CEFC00578E65 /* HeapBlock.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ C2D58C3415912FEE0021A844 /* GCActivityCallback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2D58C3315912FEE0021A844 /* GCActivityCallback.cpp */; };
+ C2E526BD1590EF000054E48D /* HeapTimer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2E526BB1590EF000054E48D /* HeapTimer.cpp */; };
+ C2E526BE1590EF000054E48D /* HeapTimer.h in Headers */ = {isa = PBXBuildFile; fileRef = C2E526BC1590EF000054E48D /* HeapTimer.h */; settings = {ATTRIBUTES = (Private, ); }; };
C2EAA3FA149A835E00FCE112 /* CopiedSpace.h in Headers */ = {isa = PBXBuildFile; fileRef = C2EAA3F8149A830800FCE112 /* CopiedSpace.h */; settings = {ATTRIBUTES = (Private, ); }; };
C2EAD2FC14F0249800A4B159 /* CopiedAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = C2EAD2FB14F0249800A4B159 /* CopiedAllocator.h */; settings = {ATTRIBUTES = (Private, ); }; };
DDF7ABD411F60ED200108E36 /* GCActivityCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = DDF7ABD211F60ED200108E36 /* GCActivityCallback.h */; settings = {ATTRIBUTES = (Private, ); }; };
- DDF7ABD511F60ED200108E36 /* GCActivityCallbackCF.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DDF7ABD311F60ED200108E36 /* GCActivityCallbackCF.cpp */; };
E124A8F70E555775003091F1 /* OpaqueJSString.h in Headers */ = {isa = PBXBuildFile; fileRef = E124A8F50E555775003091F1 /* OpaqueJSString.h */; settings = {ATTRIBUTES = (Private, ); }; };
E124A8F80E555775003091F1 /* OpaqueJSString.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E124A8F60E555775003091F1 /* OpaqueJSString.cpp */; };
E178636D0D9BEEC300D74E75 /* InitializeThreading.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E178636C0D9BEEC300D74E75 /* InitializeThreading.cpp */; };
@@ -828,6 +853,13 @@
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>"; };
+ 0F919D09157EE09D004A4E7D /* JSSymbolTableObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSSymbolTableObject.cpp; sourceTree = "<group>"; };
+ 0F919D0A157EE09D004A4E7D /* JSSymbolTableObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSSymbolTableObject.h; sourceTree = "<group>"; };
+ 0F919D0E157F3327004A4E7D /* JSSegmentedVariableObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSSegmentedVariableObject.cpp; sourceTree = "<group>"; };
+ 0F919D0F157F3327004A4E7D /* JSSegmentedVariableObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSSegmentedVariableObject.h; sourceTree = "<group>"; };
+ 0F919D2215853CDE004A4E7D /* Watchpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Watchpoint.cpp; sourceTree = "<group>"; };
+ 0F919D2315853CDE004A4E7D /* Watchpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Watchpoint.h; sourceTree = "<group>"; };
+ 0F919D2715856770004A4E7D /* SymbolTable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SymbolTable.cpp; 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>"; };
@@ -875,12 +907,28 @@
0FD82E1E14172C2F00179C94 /* DFGCapabilities.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGCapabilities.cpp; path = dfg/DFGCapabilities.cpp; sourceTree = "<group>"; };
0FD82E1F14172C2F00179C94 /* DFGCapabilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGCapabilities.h; path = dfg/DFGCapabilities.h; sourceTree = "<group>"; };
0FD82E37141AB14200179C94 /* CompactJITCodeMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CompactJITCodeMap.h; sourceTree = "<group>"; };
- 0FD82E4F141DAEA100179C94 /* PredictedType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PredictedType.h; sourceTree = "<group>"; };
+ 0FD82E4F141DAEA100179C94 /* SpeculatedType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpeculatedType.h; sourceTree = "<group>"; };
0FD82E52141DAEDE00179C94 /* DFGOSREntry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGOSREntry.cpp; path = dfg/DFGOSREntry.cpp; sourceTree = "<group>"; };
0FD82E53141DAEDE00179C94 /* DFGOSREntry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGOSREntry.h; path = dfg/DFGOSREntry.h; sourceTree = "<group>"; };
- 0FD82E84141F3FDA00179C94 /* PredictedType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PredictedType.cpp; sourceTree = "<group>"; };
+ 0FD82E84141F3FDA00179C94 /* SpeculatedType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SpeculatedType.cpp; 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>"; };
+ 0FF4272F158EBD44004CB9FF /* Disassembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Disassembler.h; path = disassembler/Disassembler.h; sourceTree = "<group>"; };
+ 0FF42730158EBD44004CB9FF /* UDis86Disassembler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UDis86Disassembler.cpp; path = disassembler/UDis86Disassembler.cpp; sourceTree = "<group>"; };
+ 0FF42734158EBD94004CB9FF /* udis86_decode.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = udis86_decode.c; path = disassembler/udis86/udis86_decode.c; sourceTree = "<group>"; };
+ 0FF42735158EBD94004CB9FF /* udis86_decode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = udis86_decode.h; path = disassembler/udis86/udis86_decode.h; sourceTree = "<group>"; };
+ 0FF42736158EBD94004CB9FF /* udis86_extern.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = udis86_extern.h; path = disassembler/udis86/udis86_extern.h; sourceTree = "<group>"; };
+ 0FF42737158EBD94004CB9FF /* udis86_input.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = udis86_input.c; path = disassembler/udis86/udis86_input.c; sourceTree = "<group>"; };
+ 0FF42738158EBD94004CB9FF /* udis86_input.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = udis86_input.h; path = disassembler/udis86/udis86_input.h; sourceTree = "<group>"; };
+ 0FF42739158EBD94004CB9FF /* udis86_syn-att.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "udis86_syn-att.c"; path = "disassembler/udis86/udis86_syn-att.c"; sourceTree = "<group>"; };
+ 0FF4273A158EBD94004CB9FF /* udis86_syn-intel.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "udis86_syn-intel.c"; path = "disassembler/udis86/udis86_syn-intel.c"; sourceTree = "<group>"; };
+ 0FF4273B158EBD94004CB9FF /* udis86_syn.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = udis86_syn.c; path = disassembler/udis86/udis86_syn.c; sourceTree = "<group>"; };
+ 0FF4273C158EBD94004CB9FF /* udis86_syn.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = udis86_syn.h; path = disassembler/udis86/udis86_syn.h; sourceTree = "<group>"; };
+ 0FF4273D158EBD94004CB9FF /* udis86_types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = udis86_types.h; path = disassembler/udis86/udis86_types.h; sourceTree = "<group>"; };
+ 0FF4273E158EBD94004CB9FF /* udis86.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = udis86.c; path = disassembler/udis86/udis86.c; sourceTree = "<group>"; };
+ 0FF4273F158EBD94004CB9FF /* udis86.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = udis86.h; path = disassembler/udis86/udis86.h; sourceTree = "<group>"; };
+ 0FF4274C158EBFE1004CB9FF /* udis86_itab_holder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = udis86_itab_holder.c; path = disassembler/udis86/udis86_itab_holder.c; sourceTree = "<group>"; };
+ 0FF4275615914A20004CB9FF /* LinkBuffer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LinkBuffer.cpp; sourceTree = "<group>"; };
0FF922CF14F46B130041A24E /* JSCLLIntOffsetsExtractor */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = JSCLLIntOffsetsExtractor; sourceTree = BUILT_PRODUCTS_DIR; };
0FFFC94B14EF909500C72532 /* DFGCFAPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGCFAPhase.cpp; path = dfg/DFGCFAPhase.cpp; sourceTree = "<group>"; };
0FFFC94C14EF909500C72532 /* DFGCFAPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGCFAPhase.h; path = dfg/DFGCFAPhase.h; sourceTree = "<group>"; };
@@ -1340,12 +1388,14 @@
C2C8D02B14A3C6B200578E65 /* CopiedSpaceInlineMethods.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CopiedSpaceInlineMethods.h; sourceTree = "<group>"; };
C2C8D02E14A3CEFC00578E65 /* CopiedBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CopiedBlock.h; sourceTree = "<group>"; };
C2C8D02F14A3CEFC00578E65 /* HeapBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HeapBlock.h; sourceTree = "<group>"; };
+ C2D58C3315912FEE0021A844 /* GCActivityCallback.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GCActivityCallback.cpp; sourceTree = "<group>"; };
+ C2E526BB1590EF000054E48D /* HeapTimer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HeapTimer.cpp; sourceTree = "<group>"; };
+ C2E526BC1590EF000054E48D /* HeapTimer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HeapTimer.h; sourceTree = "<group>"; };
C2EAA3F8149A830800FCE112 /* CopiedSpace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CopiedSpace.h; sourceTree = "<group>"; };
C2EAD2FB14F0249800A4B159 /* CopiedAllocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CopiedAllocator.h; sourceTree = "<group>"; };
D21202280AD4310C00ED79B6 /* DateConversion.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DateConversion.cpp; sourceTree = "<group>"; };
D21202290AD4310C00ED79B6 /* DateConversion.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DateConversion.h; sourceTree = "<group>"; };
DDF7ABD211F60ED200108E36 /* GCActivityCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCActivityCallback.h; sourceTree = "<group>"; };
- DDF7ABD311F60ED200108E36 /* GCActivityCallbackCF.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GCActivityCallbackCF.cpp; sourceTree = "<group>"; };
E124A8F50E555775003091F1 /* OpaqueJSString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OpaqueJSString.h; sourceTree = "<group>"; };
E124A8F60E555775003091F1 /* OpaqueJSString.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OpaqueJSString.cpp; sourceTree = "<group>"; };
E178633F0D9BEC0000D74E75 /* InitializeThreading.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InitializeThreading.h; sourceTree = "<group>"; };
@@ -1481,6 +1531,7 @@
969A078F0ED1D3AE00F1F681 /* bytecode */,
7E39D81D0EC38EFA003AF11A /* bytecompiler */,
1480DB9A0DDC2231003CFDF2 /* debugger */,
+ 0FF4272E158EBCCE004CB9FF /* disassembler */,
86EC9DB31328DF44002B2AD7 /* dfg */,
142E312A134FF0A600AFADB5 /* heap */,
1429D77A0ED20D7300B89619 /* interpreter */,
@@ -1542,6 +1593,36 @@
name = llint;
sourceTree = "<group>";
};
+ 0FF4272E158EBCCE004CB9FF /* disassembler */ = {
+ isa = PBXGroup;
+ children = (
+ 0FF42733158EBD64004CB9FF /* udis86 */,
+ 0FF4272F158EBD44004CB9FF /* Disassembler.h */,
+ 0FF42730158EBD44004CB9FF /* UDis86Disassembler.cpp */,
+ );
+ name = disassembler;
+ sourceTree = "<group>";
+ };
+ 0FF42733158EBD64004CB9FF /* udis86 */ = {
+ isa = PBXGroup;
+ children = (
+ 0FF42734158EBD94004CB9FF /* udis86_decode.c */,
+ 0FF42735158EBD94004CB9FF /* udis86_decode.h */,
+ 0FF42736158EBD94004CB9FF /* udis86_extern.h */,
+ 0FF42737158EBD94004CB9FF /* udis86_input.c */,
+ 0FF42738158EBD94004CB9FF /* udis86_input.h */,
+ 0FF4274C158EBFE1004CB9FF /* udis86_itab_holder.c */,
+ 0FF42739158EBD94004CB9FF /* udis86_syn-att.c */,
+ 0FF4273A158EBD94004CB9FF /* udis86_syn-intel.c */,
+ 0FF4273B158EBD94004CB9FF /* udis86_syn.c */,
+ 0FF4273C158EBD94004CB9FF /* udis86_syn.h */,
+ 0FF4273D158EBD94004CB9FF /* udis86_types.h */,
+ 0FF4273E158EBD94004CB9FF /* udis86.c */,
+ 0FF4273F158EBD94004CB9FF /* udis86.h */,
+ );
+ name = udis86;
+ sourceTree = "<group>";
+ };
141211000A48772600480255 /* tests */ = {
isa = PBXGroup;
children = (
@@ -1613,6 +1694,8 @@
142E312A134FF0A600AFADB5 /* heap */ = {
isa = PBXGroup;
children = (
+ C2E526BB1590EF000054E48D /* HeapTimer.cpp */,
+ C2E526BC1590EF000054E48D /* HeapTimer.h */,
C25F8BCB157544A900245B71 /* IncrementalSweeper.cpp */,
C25F8BCC157544A900245B71 /* IncrementalSweeper.h */,
14816E19154CC56C00B8054C /* BlockAllocator.cpp */,
@@ -1838,6 +1921,7 @@
7EF6E0BB0EB7A1EC0079AFAF /* runtime */ = {
isa = PBXGroup;
children = (
+ C2D58C3315912FEE0021A844 /* GCActivityCallback.cpp */,
BCF605110E203EF800B9A64D /* ArgList.cpp */,
BCF605120E203EF800B9A64D /* ArgList.h */,
BC257DE50E1F51C50016B6C9 /* Arguments.cpp */,
@@ -1893,7 +1977,6 @@
F692A85C0255597D01FF60F7 /* FunctionPrototype.cpp */,
F692A85D0255597D01FF60F7 /* FunctionPrototype.h */,
DDF7ABD211F60ED200108E36 /* GCActivityCallback.h */,
- DDF7ABD311F60ED200108E36 /* GCActivityCallbackCF.cpp */,
BC02E9B80E184545000F9297 /* GetterSetter.cpp */,
BC337BDE0E1AF0B80076918A /* GetterSetter.h */,
933A349D038AE80F008635CE /* Identifier.cpp */,
@@ -1934,6 +2017,8 @@
A7F9935D0FD7325100A0B2D0 /* JSONObject.h */,
A727FF660DA3053B00E548D7 /* JSPropertyNameIterator.cpp */,
A727FF650DA3053B00E548D7 /* JSPropertyNameIterator.h */,
+ 0F919D0E157F3327004A4E7D /* JSSegmentedVariableObject.cpp */,
+ 0F919D0F157F3327004A4E7D /* JSSegmentedVariableObject.h */,
A7E42C190E3938830065A544 /* JSStaticScopeObject.cpp */,
A7E42C180E3938830065A544 /* JSStaticScopeObject.h */,
BC02E9B60E1842FA000F9297 /* JSString.cpp */,
@@ -1941,6 +2026,8 @@
86E85538111B9968001AF51E /* JSStringBuilder.h */,
2600B5A4152BAAA70091EE5F /* JSStringJoiner.cpp */,
2600B5A5152BAAA70091EE5F /* JSStringJoiner.h */,
+ 0F919D09157EE09D004A4E7D /* JSSymbolTableObject.cpp */,
+ 0F919D0A157EE09D004A4E7D /* JSSymbolTableObject.h */,
14ABB454099C2A0F00E2A24F /* JSType.h */,
6507D2970E871E4A00D7D896 /* JSTypeInfo.h */,
F692A8870255597D01FF60F7 /* JSValue.cpp */,
@@ -2033,6 +2120,7 @@
7E4EE70E0EBB7A5B005934AA /* StructureChain.cpp */,
7E4EE7080EBB7963005934AA /* StructureChain.h */,
BC9041470EB9250900FE26FA /* StructureTransitionTable.h */,
+ 0F919D2715856770004A4E7D /* SymbolTable.cpp */,
14A396A60CD2933100B5B4FF /* SymbolTable.h */,
97F6903A1169DF7F00A6BB46 /* Terminator.h */,
14A42E3D0F4F60EE00599099 /* TimeoutChecker.cpp */,
@@ -2209,6 +2297,7 @@
9688CB130ED12B4E001D649F /* AssemblerBuffer.h */,
86D3B2C110156BDE002865E7 /* AssemblerBufferWithConstantPool.h */,
86E116B00FE75AC800B512BC /* CodeLocation.h */,
+ 0FF4275615914A20004CB9FF /* LinkBuffer.cpp */,
86D3B3C110159D7F002865E7 /* LinkBuffer.h */,
86C36EE90EE1289D00B3DF59 /* MacroAssembler.h */,
86C568DD11A213EE0007F7F0 /* MacroAssemblerARM.cpp */,
@@ -2275,8 +2364,8 @@
BCFD8C910EEB2EE700283848 /* JumpTable.h */,
969A07940ED1D3AE00F1F681 /* Opcode.cpp */,
969A07950ED1D3AE00F1F681 /* Opcode.h */,
- 0FD82E84141F3FDA00179C94 /* PredictedType.cpp */,
- 0FD82E4F141DAEA100179C94 /* PredictedType.h */,
+ 0FD82E84141F3FDA00179C94 /* SpeculatedType.cpp */,
+ 0FD82E4F141DAEA100179C94 /* SpeculatedType.h */,
1429D8830ED21C3D00B89619 /* SamplingTool.cpp */,
1429D8840ED21C3D00B89619 /* SamplingTool.h */,
BCCF0D0B0EF0B8A500413C8F /* StructureStubInfo.cpp */,
@@ -2284,6 +2373,8 @@
0F963B3613FC6FDE0002D9B2 /* ValueProfile.h */,
0F426A451460CBAB00131F8F /* ValueRecovery.h */,
0F426A461460CBAB00131F8F /* VirtualRegister.h */,
+ 0F919D2215853CDE004A4E7D /* Watchpoint.cpp */,
+ 0F919D2315853CDE004A4E7D /* Watchpoint.h */,
);
path = bytecode;
sourceTree = "<group>";
@@ -2316,6 +2407,7 @@
86ADD1450FDDEA980006EEC2 /* ARMv7Assembler.h in Headers */,
C2EAD2FC14F0249800A4B159 /* CopiedAllocator.h in Headers */,
C2B916C214DA014E00CBAC86 /* MarkedAllocator.h in Headers */,
+ C2E526BE1590EF000054E48D /* HeapTimer.h in Headers */,
C25F8BCE157544A900245B71 /* IncrementalSweeper.h in Headers */,
BC18C3E60E16F5CD00B34460 /* ArrayConstructor.h in Headers */,
BC18C3E70E16F5CD00B34460 /* ArrayPrototype.h in Headers */,
@@ -2506,7 +2598,7 @@
BC18C44B0E16F5CD00B34460 /* Parser.h in Headers */,
93052C350FB792190048FDC3 /* ParserArena.h in Headers */,
65303D641447B9E100D3F904 /* ParserTokens.h in Headers */,
- 0FD82E54141DAEEE00179C94 /* PredictedType.h in Headers */,
+ 0FD82E54141DAEEE00179C94 /* SpeculatedType.h in Headers */,
BC18C4500E16F5CD00B34460 /* Profile.h in Headers */,
BC18C4510E16F5CD00B34460 /* ProfileNode.h in Headers */,
BC18C4520E16F5CD00B34460 /* Profiler.h in Headers */,
@@ -2657,6 +2749,16 @@
0F3B3A2C15475002003ED0FF /* DFGValidate.h in Headers */,
0FD81AD3154FB4F000983E72 /* DFGDominators.h in Headers */,
0F16015E156198C900C2587C /* DFGArgumentsSimplificationPhase.h in Headers */,
+ 0F919D0D157EE0A2004A4E7D /* JSSymbolTableObject.h in Headers */,
+ 0F919D11157F332C004A4E7D /* JSSegmentedVariableObject.h in Headers */,
+ 0F919D2615853CE3004A4E7D /* Watchpoint.h in Headers */,
+ 0FF42731158EBD54004CB9FF /* Disassembler.h in Headers */,
+ 0FF42741158EBE8D004CB9FF /* udis86_decode.h in Headers */,
+ 0FF42742158EBE91004CB9FF /* udis86_extern.h in Headers */,
+ 0FF42744158EBE91004CB9FF /* udis86_input.h in Headers */,
+ 0FF42748158EBE91004CB9FF /* udis86_syn.h in Headers */,
+ 0FF42749158EBE91004CB9FF /* udis86_types.h in Headers */,
+ 0FF4274B158EBE91004CB9FF /* udis86.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -2936,7 +3038,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
- shellScript = "mkdir -p \"${BUILT_PRODUCTS_DIR}/DerivedSources/JavaScriptCore/docs\"\ncd \"${BUILT_PRODUCTS_DIR}/DerivedSources/JavaScriptCore\"\n\n/bin/ln -sfh \"${SRCROOT}\" JavaScriptCore\nexport JavaScriptCore=\"JavaScriptCore\"\nexport BUILT_PRODUCTS_DIR=\"../..\"\n\nmake --no-builtin-rules -f \"JavaScriptCore/DerivedSources.make\" -j `/usr/sbin/sysctl -n hw.ncpu`\n\n/usr/bin/env ruby JavaScriptCore/offlineasm/asm.rb JavaScriptCore/llint/LowLevelInterpreter.asm ${BUILT_PRODUCTS_DIR}/JSCLLIntOffsetsExtractor LLIntAssembly.h\n";
+ shellScript = "mkdir -p \"${BUILT_PRODUCTS_DIR}/DerivedSources/JavaScriptCore/docs\"\ncd \"${BUILT_PRODUCTS_DIR}/DerivedSources/JavaScriptCore\"\n\n/bin/ln -sfh \"${SRCROOT}\" JavaScriptCore\nexport JavaScriptCore=\"JavaScriptCore\"\nexport BUILT_PRODUCTS_DIR=\"../..\"\n\nmake --no-builtin-rules -f \"JavaScriptCore/DerivedSources.make\" -j `/usr/sbin/sysctl -n hw.ncpu` || exit 1\n\n/usr/bin/env ruby JavaScriptCore/offlineasm/asm.rb JavaScriptCore/llint/LowLevelInterpreter.asm ${BUILT_PRODUCTS_DIR}/JSCLLIntOffsetsExtractor LLIntAssembly.h || exit 1\n";
};
9319586B09D9F91A00A56FD4 /* Check For Global Initializers */ = {
isa = PBXShellScriptBuildPhase;
@@ -3067,7 +3169,6 @@
86DB64640F95C6FC00D7D921 /* ExecutableAllocatorFixedVMPool.cpp in Sources */,
147F39CB107EC37600427A48 /* FunctionConstructor.cpp in Sources */,
147F39CC107EC37600427A48 /* FunctionPrototype.cpp in Sources */,
- DDF7ABD511F60ED200108E36 /* GCActivityCallbackCF.cpp in Sources */,
14280855107EC0E70013E7B2 /* GetterSetter.cpp in Sources */,
142E3135134FF0A600AFADB5 /* HandleSet.cpp in Sources */,
142E3137134FF0A600AFADB5 /* HandleStack.cpp in Sources */,
@@ -3147,7 +3248,7 @@
0FE228EE1436AB2C00196C48 /* Options.cpp in Sources */,
148F21BC107EC54D0042EC2C /* Parser.cpp in Sources */,
93052C340FB792190048FDC3 /* ParserArena.cpp in Sources */,
- 0FD82E86141F3FF100179C94 /* PredictedType.cpp in Sources */,
+ 0FD82E86141F3FF100179C94 /* SpeculatedType.cpp in Sources */,
95742F650DD11F5A000917FB /* Profile.cpp in Sources */,
95CD45760E1C4FDD0085358E /* ProfileGenerator.cpp in Sources */,
95AB83560DA43C3000BC83F3 /* ProfileNode.cpp in Sources */,
@@ -3229,6 +3330,21 @@
0FD81AD2154FB4EE00983E72 /* DFGDominators.cpp in Sources */,
0F16015D156198C900C2587C /* DFGArgumentsSimplificationPhase.cpp in Sources */,
C25F8BCD157544A900245B71 /* IncrementalSweeper.cpp in Sources */,
+ 0F919D0C157EE09F004A4E7D /* JSSymbolTableObject.cpp in Sources */,
+ 0F919D10157F3329004A4E7D /* JSSegmentedVariableObject.cpp in Sources */,
+ 0F919D2515853CE0004A4E7D /* Watchpoint.cpp in Sources */,
+ 0F919D2815856773004A4E7D /* SymbolTable.cpp in Sources */,
+ 0FF42732158EBD58004CB9FF /* UDis86Disassembler.cpp in Sources */,
+ 0FF42740158EBE8B004CB9FF /* udis86_decode.c in Sources */,
+ 0FF42743158EBE91004CB9FF /* udis86_input.c in Sources */,
+ 0FF42745158EBE91004CB9FF /* udis86_syn-att.c in Sources */,
+ 0FF42746158EBE91004CB9FF /* udis86_syn-intel.c in Sources */,
+ 0FF42747158EBE91004CB9FF /* udis86_syn.c in Sources */,
+ 0FF4274A158EBE91004CB9FF /* udis86.c in Sources */,
+ 0FF4274D158EBFE6004CB9FF /* udis86_itab_holder.c in Sources */,
+ C2E526BD1590EF000054E48D /* HeapTimer.cpp in Sources */,
+ 0FF4275715914A20004CB9FF /* LinkBuffer.cpp in Sources */,
+ C2D58C3415912FEE0021A844 /* GCActivityCallback.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
diff --git a/Source/JavaScriptCore/PlatformBlackBerry.cmake b/Source/JavaScriptCore/PlatformBlackBerry.cmake
index abfae85be..cc3cfead3 100644
--- a/Source/JavaScriptCore/PlatformBlackBerry.cmake
+++ b/Source/JavaScriptCore/PlatformBlackBerry.cmake
@@ -2,4 +2,12 @@ LIST(INSERT JavaScriptCore_INCLUDE_DIRECTORIES 0
"${BLACKBERRY_THIRD_PARTY_DIR}/icu"
)
+LIST(REMOVE_ITEM JavaScriptCore_SOURCES
+ runtime/GCActivityCallback.cpp
+)
+
+LIST(APPEND JavaScriptCore_SOURCES
+ runtime/GCActivityCallbackBlackBerry.cpp
+)
+
INSTALL(FILES "wtf/Forward.h" DESTINATION usr/include/browser/webkit/wtf)
diff --git a/Source/JavaScriptCore/Target.pri b/Source/JavaScriptCore/Target.pri
index ed682d94a..e3488c74e 100644
--- a/Source/JavaScriptCore/Target.pri
+++ b/Source/JavaScriptCore/Target.pri
@@ -47,6 +47,7 @@ SOURCES += \
API/OpaqueJSString.cpp \
assembler/ARMAssembler.cpp \
assembler/ARMv7Assembler.cpp \
+ assembler/LinkBuffer.cpp \
assembler/MacroAssemblerARM.cpp \
assembler/MacroAssemblerSH4.cpp \
bytecode/CallLinkInfo.cpp \
@@ -62,10 +63,11 @@ SOURCES += \
bytecode/MethodOfGettingAValueProfile.cpp \
bytecode/Opcode.cpp \
bytecode/PolymorphicPutByIdList.cpp \
- bytecode/PredictedType.cpp \
bytecode/PutByIdStatus.cpp \
bytecode/SamplingTool.cpp \
+ bytecode/SpeculatedType.cpp \
bytecode/StructureStubInfo.cpp \
+ bytecode/Watchpoint.cpp \
bytecompiler/BytecodeGenerator.cpp \
bytecompiler/NodesCodegen.cpp \
heap/CopiedSpace.cpp \
@@ -78,6 +80,7 @@ SOURCES += \
heap/HandleStack.cpp \
heap/BlockAllocator.cpp \
heap/Heap.cpp \
+ heap/HeapTimer.cpp \
heap/IncrementalSweeper.cpp \
heap/MachineStackMarker.cpp \
heap/MarkStack.cpp \
@@ -194,9 +197,11 @@ SOURCES += \
runtime/JSObject.cpp \
runtime/JSONObject.cpp \
runtime/JSPropertyNameIterator.cpp \
+ runtime/JSSegmentedVariableObject.cpp \
runtime/JSStaticScopeObject.cpp \
runtime/JSString.cpp \
runtime/JSStringJoiner.cpp \
+ runtime/JSSymbolTableObject.cpp \
runtime/JSValue.cpp \
runtime/JSVariableObject.cpp \
runtime/JSWrapperObject.cpp \
@@ -234,6 +239,7 @@ SOURCES += \
runtime/StringRecursionChecker.cpp \
runtime/StructureChain.cpp \
runtime/Structure.cpp \
+ runtime/SymbolTable.cpp \
runtime/TimeoutChecker.cpp \
runtime/UString.cpp \
tools/CodeProfile.cpp \
diff --git a/Source/JavaScriptCore/assembler/ARMv7Assembler.h b/Source/JavaScriptCore/assembler/ARMv7Assembler.h
index 0cbe799b4..95c812c94 100644
--- a/Source/JavaScriptCore/assembler/ARMv7Assembler.h
+++ b/Source/JavaScriptCore/assembler/ARMv7Assembler.h
@@ -483,6 +483,12 @@ public:
JumpLinkType m_linkType : 8;
Condition m_condition : 16;
};
+
+ ARMv7Assembler()
+ : m_indexOfLastWatchpoint(INT_MIN)
+ , m_indexOfTailOfLastWatchpoint(INT_MIN)
+ {
+ }
private:
@@ -1820,10 +1826,25 @@ public:
{
m_formatter.oneWordOp8Imm8(OP_NOP_T1, 0);
}
+
+ AssemblerLabel labelForWatchpoint()
+ {
+ AssemblerLabel result = m_formatter.label();
+ if (static_cast<int>(result.m_offset) != m_indexOfLastWatchpoint)
+ result = label();
+ m_indexOfLastWatchpoint = result.m_offset;
+ m_indexOfTailOfLastWatchpoint = result.m_offset + maxJumpReplacementSize();
+ return result;
+ }
AssemblerLabel label()
{
- return m_formatter.label();
+ AssemblerLabel result = m_formatter.label();
+ while (UNLIKELY(static_cast<int>(result.m_offset) < m_indexOfTailOfLastWatchpoint)) {
+ nop();
+ result = m_formatter.label();
+ }
+ return result;
}
AssemblerLabel align(int alignment)
@@ -2067,6 +2088,30 @@ public:
{
return reinterpret_cast<void*>(readInt32(where));
}
+
+ static void replaceWithJump(void* instructionStart, void* to)
+ {
+ ASSERT(!(bitwise_cast<uintptr_t>(instructionStart) & 1));
+ ASSERT(!(bitwise_cast<uintptr_t>(to) & 1));
+ uint16_t* ptr = reinterpret_cast<uint16_t*>(instructionStart) + 2;
+
+ // Ensure that we're not in one of those errata-triggering thingies. If we are, then
+ // prepend a nop.
+ bool spansTwo4K = ((reinterpret_cast<intptr_t>(ptr) & 0xfff) == 0x002);
+
+ if (spansTwo4K) {
+ ptr[-2] = OP_NOP_T1;
+ ptr++;
+ }
+
+ linkJumpT4(ptr, to);
+ cacheFlush(ptr - 2, sizeof(uint16_t) * 2);
+ }
+
+ static ptrdiff_t maxJumpReplacementSize()
+ {
+ return 6;
+ }
unsigned debugOffset() { return m_formatter.debugOffset(); }
@@ -2604,6 +2649,8 @@ private:
Vector<LinkRecord> m_jumpsToLink;
Vector<int32_t> m_offsets;
+ int m_indexOfLastWatchpoint;
+ int m_indexOfTailOfLastWatchpoint;
};
} // namespace JSC
diff --git a/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h b/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h
index a0039cb52..27b8a58d1 100644
--- a/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h
+++ b/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 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
@@ -48,6 +48,7 @@ namespace JSC {
class LinkBuffer;
class RepatchBuffer;
+class Watchpoint;
namespace DFG {
class CorrectableJumpPoint;
}
@@ -70,7 +71,6 @@ public:
// The following types are used as operands to MacroAssembler operations,
// describing immediate and memory operands to the instructions to be planted.
-
enum Scale {
TimesOne,
TimesTwo,
@@ -279,6 +279,7 @@ public:
friend class Jump;
friend class MacroAssemblerCodeRef;
friend class LinkBuffer;
+ friend class Watchpoint;
public:
Label()
@@ -559,6 +560,13 @@ public:
return Label(this);
}
+ Label watchpointLabel()
+ {
+ Label result;
+ result.m_label = m_assembler.labelForWatchpoint();
+ return result;
+ }
+
Label align()
{
m_assembler.align(16);
@@ -655,18 +663,6 @@ protected:
{
return AssemblerType::readPointer(dataLabelPtr.dataLocation());
}
-
- static void unreachableForPlatform()
- {
-#if COMPILER(CLANG)
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wmissing-noreturn"
- ASSERT_NOT_REACHED();
-#pragma clang diagnostic pop
-#else
- ASSERT_NOT_REACHED();
-#endif
- }
};
} // namespace JSC
diff --git a/Source/JavaScriptCore/assembler/AssemblerBuffer.h b/Source/JavaScriptCore/assembler/AssemblerBuffer.h
index d1deef234..6bc1b3924 100644
--- a/Source/JavaScriptCore/assembler/AssemblerBuffer.h
+++ b/Source/JavaScriptCore/assembler/AssemblerBuffer.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 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
@@ -28,11 +28,11 @@
#if ENABLE(ASSEMBLER)
+#include "ExecutableAllocator.h"
#include "JITCompilationEffort.h"
#include "JSGlobalData.h"
#include "stdint.h"
#include <string.h>
-#include <jit/ExecutableAllocator.h>
#include <wtf/Assertions.h>
#include <wtf/FastMalloc.h>
#include <wtf/StdLibExtras.h>
diff --git a/Source/JavaScriptCore/assembler/LinkBuffer.cpp b/Source/JavaScriptCore/assembler/LinkBuffer.cpp
new file mode 100644
index 000000000..58030ba7d
--- /dev/null
+++ b/Source/JavaScriptCore/assembler/LinkBuffer.cpp
@@ -0,0 +1,231 @@
+/*
+ * 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 "LinkBuffer.h"
+
+#if ENABLE(ASSEMBLER)
+
+#include "Options.h"
+
+namespace JSC {
+
+LinkBuffer::CodeRef LinkBuffer::finalizeCodeWithoutDisassembly()
+{
+ performFinalization();
+
+ return CodeRef(m_executableMemory);
+}
+
+LinkBuffer::CodeRef LinkBuffer::finalizeCodeWithDisassembly(const char* format, ...)
+{
+ ASSERT(Options::showDisassembly);
+
+ CodeRef result = finalizeCodeWithoutDisassembly();
+
+ dataLog("Generated JIT code for ");
+ va_list argList;
+ va_start(argList, format);
+ WTF::dataLogV(format, argList);
+ va_end(argList);
+ dataLog(":\n");
+
+ dataLog(" Code at [%p, %p):\n", result.code().executableAddress(), static_cast<char*>(result.code().executableAddress()) + result.size());
+ if (!tryToDisassemble(result.code(), m_size, " ", WTF::dataFile()))
+ dataLog(" <no disassembly available>");
+
+ return result;
+}
+
+void LinkBuffer::linkCode(void* ownerUID, JITCompilationEffort effort)
+{
+ ASSERT(!m_code);
+#if !ENABLE(BRANCH_COMPACTION)
+ m_executableMemory = m_assembler->m_assembler.executableCopy(*m_globalData, ownerUID, effort);
+ if (!m_executableMemory)
+ return;
+ m_code = m_executableMemory->start();
+ m_size = m_assembler->m_assembler.codeSize();
+ ASSERT(m_code);
+#else
+ m_initialSize = m_assembler->m_assembler.codeSize();
+ m_executableMemory = m_globalData->executableAllocator.allocate(*m_globalData, m_initialSize, ownerUID, effort);
+ if (!m_executableMemory)
+ return;
+ m_code = (uint8_t*)m_executableMemory->start();
+ ASSERT(m_code);
+ ExecutableAllocator::makeWritable(m_code, m_initialSize);
+ uint8_t* inData = (uint8_t*)m_assembler->unlinkedCode();
+ uint8_t* outData = reinterpret_cast<uint8_t*>(m_code);
+ int readPtr = 0;
+ int writePtr = 0;
+ Vector<LinkRecord>& jumpsToLink = m_assembler->jumpsToLink();
+ unsigned jumpCount = jumpsToLink.size();
+ for (unsigned i = 0; i < jumpCount; ++i) {
+ int offset = readPtr - writePtr;
+ ASSERT(!(offset & 1));
+
+ // Copy the instructions from the last jump to the current one.
+ size_t regionSize = jumpsToLink[i].from() - readPtr;
+ uint16_t* copySource = reinterpret_cast_ptr<uint16_t*>(inData + readPtr);
+ uint16_t* copyEnd = reinterpret_cast_ptr<uint16_t*>(inData + readPtr + regionSize);
+ uint16_t* copyDst = reinterpret_cast_ptr<uint16_t*>(outData + writePtr);
+ ASSERT(!(regionSize % 2));
+ ASSERT(!(readPtr % 2));
+ ASSERT(!(writePtr % 2));
+ while (copySource != copyEnd)
+ *copyDst++ = *copySource++;
+ m_assembler->recordLinkOffsets(readPtr, jumpsToLink[i].from(), offset);
+ readPtr += regionSize;
+ writePtr += regionSize;
+
+ // Calculate absolute address of the jump target, in the case of backwards
+ // branches we need to be precise, forward branches we are pessimistic
+ const uint8_t* target;
+ if (jumpsToLink[i].to() >= jumpsToLink[i].from())
+ target = outData + jumpsToLink[i].to() - offset; // Compensate for what we have collapsed so far
+ else
+ target = outData + jumpsToLink[i].to() - m_assembler->executableOffsetFor(jumpsToLink[i].to());
+
+ JumpLinkType jumpLinkType = m_assembler->computeJumpType(jumpsToLink[i], outData + writePtr, target);
+ // Compact branch if we can...
+ if (m_assembler->canCompact(jumpsToLink[i].type())) {
+ // Step back in the write stream
+ int32_t delta = m_assembler->jumpSizeDelta(jumpsToLink[i].type(), jumpLinkType);
+ if (delta) {
+ writePtr -= delta;
+ m_assembler->recordLinkOffsets(jumpsToLink[i].from() - delta, readPtr, readPtr - writePtr);
+ }
+ }
+ jumpsToLink[i].setFrom(writePtr);
+ }
+ // Copy everything after the last jump
+ memcpy(outData + writePtr, inData + readPtr, m_initialSize - readPtr);
+ m_assembler->recordLinkOffsets(readPtr, m_initialSize, readPtr - writePtr);
+
+ for (unsigned i = 0; i < jumpCount; ++i) {
+ uint8_t* location = outData + jumpsToLink[i].from();
+ uint8_t* target = outData + jumpsToLink[i].to() - m_assembler->executableOffsetFor(jumpsToLink[i].to());
+ m_assembler->link(jumpsToLink[i], location, target);
+ }
+
+ jumpsToLink.clear();
+ m_size = writePtr + m_initialSize - readPtr;
+ m_executableMemory->shrink(m_size);
+
+#if DUMP_LINK_STATISTICS
+ dumpLinkStatistics(m_code, m_initialSize, m_size);
+#endif
+#if DUMP_CODE
+ dumpCode(m_code, m_size);
+#endif
+#endif
+}
+
+void LinkBuffer::performFinalization()
+{
+#ifndef NDEBUG
+ ASSERT(!m_completed);
+ ASSERT(isValid());
+ m_completed = true;
+#endif
+
+#if ENABLE(BRANCH_COMPACTION)
+ ExecutableAllocator::makeExecutable(code(), m_initialSize);
+#else
+ ExecutableAllocator::makeExecutable(code(), m_size);
+#endif
+ MacroAssembler::cacheFlush(code(), m_size);
+}
+
+#if DUMP_LINK_STATISTICS
+void LinkBuffer::dumpLinkStatistics(void* code, size_t initializeSize, size_t finalSize)
+{
+ static unsigned linkCount = 0;
+ static unsigned totalInitialSize = 0;
+ static unsigned totalFinalSize = 0;
+ linkCount++;
+ totalInitialSize += initialSize;
+ totalFinalSize += finalSize;
+ dataLog("link %p: orig %u, compact %u (delta %u, %.2f%%)\n",
+ code, static_cast<unsigned>(initialSize), static_cast<unsigned>(finalSize),
+ static_cast<unsigned>(initialSize - finalSize),
+ 100.0 * (initialSize - finalSize) / initialSize);
+ dataLog("\ttotal %u: orig %u, compact %u (delta %u, %.2f%%)\n",
+ linkCount, totalInitialSize, totalFinalSize, totalInitialSize - totalFinalSize,
+ 100.0 * (totalInitialSize - totalFinalSize) / totalInitialSize);
+}
+#endif
+
+#if DUMP_CODE
+void LinkBuffer::dumpCode(void* code, size_t size)
+{
+#if CPU(ARM_THUMB2)
+ // Dump the generated code in an asm file format that can be assembled and then disassembled
+ // for debugging purposes. For example, save this output as jit.s:
+ // gcc -arch armv7 -c jit.s
+ // otool -tv jit.o
+ static unsigned codeCount = 0;
+ unsigned short* tcode = static_cast<unsigned short*>(code);
+ size_t tsize = size / sizeof(short);
+ char nameBuf[128];
+ snprintf(nameBuf, sizeof(nameBuf), "_jsc_jit%u", codeCount++);
+ dataLog("\t.syntax unified\n"
+ "\t.section\t__TEXT,__text,regular,pure_instructions\n"
+ "\t.globl\t%s\n"
+ "\t.align 2\n"
+ "\t.code 16\n"
+ "\t.thumb_func\t%s\n"
+ "# %p\n"
+ "%s:\n", nameBuf, nameBuf, code, nameBuf);
+
+ for (unsigned i = 0; i < tsize; i++)
+ dataLog("\t.short\t0x%x\n", tcode[i]);
+#elif CPU(ARM_TRADITIONAL)
+ // gcc -c jit.s
+ // objdump -D jit.o
+ static unsigned codeCount = 0;
+ unsigned int* tcode = static_cast<unsigned int*>(code);
+ size_t tsize = size / sizeof(unsigned int);
+ char nameBuf[128];
+ snprintf(nameBuf, sizeof(nameBuf), "_jsc_jit%u", codeCount++);
+ dataLog("\t.globl\t%s\n"
+ "\t.align 4\n"
+ "\t.code 32\n"
+ "\t.text\n"
+ "# %p\n"
+ "%s:\n", nameBuf, code, nameBuf);
+
+ for (unsigned i = 0; i < tsize; i++)
+ dataLog("\t.long\t0x%x\n", tcode[i]);
+#endif
+}
+#endif
+
+} // namespace JSC
+
+#endif // ENABLE(ASSEMBLER)
+
+
diff --git a/Source/JavaScriptCore/assembler/LinkBuffer.h b/Source/JavaScriptCore/assembler/LinkBuffer.h
index eff320d57..c6e003142 100644
--- a/Source/JavaScriptCore/assembler/LinkBuffer.h
+++ b/Source/JavaScriptCore/assembler/LinkBuffer.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2009, 2010, 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
@@ -193,13 +193,13 @@ public:
return applyOffset(label.m_label).m_offset;
}
- // Upon completion of all patching 'finalizeCode()' should be called once to complete generation of the code.
- CodeRef finalizeCode()
- {
- performFinalization();
-
- return CodeRef(m_executableMemory);
- }
+ // Upon completion of all patching 'FINALIZE_CODE()' should be called once to
+ // complete generation of the code. Alternatively, call
+ // finalizeCodeWithoutDisassembly() directly if you have your own way of
+ // displaying disassembly.
+
+ CodeRef finalizeCodeWithoutDisassembly();
+ CodeRef finalizeCodeWithDisassembly(const char* format, ...) WTF_ATTRIBUTE_PRINTF(2, 3);
CodePtr trampolineAt(Label label)
{
@@ -231,169 +231,16 @@ private:
return m_code;
}
- void linkCode(void* ownerUID, JITCompilationEffort effort)
- {
- ASSERT(!m_code);
-#if !ENABLE(BRANCH_COMPACTION)
- m_executableMemory = m_assembler->m_assembler.executableCopy(*m_globalData, ownerUID, effort);
- if (!m_executableMemory)
- return;
- m_code = m_executableMemory->start();
- m_size = m_assembler->m_assembler.codeSize();
- ASSERT(m_code);
-#else
- m_initialSize = m_assembler->m_assembler.codeSize();
- m_executableMemory = m_globalData->executableAllocator.allocate(*m_globalData, m_initialSize, ownerUID, effort);
- if (!m_executableMemory)
- return;
- m_code = (uint8_t*)m_executableMemory->start();
- ASSERT(m_code);
- ExecutableAllocator::makeWritable(m_code, m_initialSize);
- uint8_t* inData = (uint8_t*)m_assembler->unlinkedCode();
- uint8_t* outData = reinterpret_cast<uint8_t*>(m_code);
- int readPtr = 0;
- int writePtr = 0;
- Vector<LinkRecord>& jumpsToLink = m_assembler->jumpsToLink();
- unsigned jumpCount = jumpsToLink.size();
- for (unsigned i = 0; i < jumpCount; ++i) {
- int offset = readPtr - writePtr;
- ASSERT(!(offset & 1));
-
- // Copy the instructions from the last jump to the current one.
- size_t regionSize = jumpsToLink[i].from() - readPtr;
- uint16_t* copySource = reinterpret_cast_ptr<uint16_t*>(inData + readPtr);
- uint16_t* copyEnd = reinterpret_cast_ptr<uint16_t*>(inData + readPtr + regionSize);
- uint16_t* copyDst = reinterpret_cast_ptr<uint16_t*>(outData + writePtr);
- ASSERT(!(regionSize % 2));
- ASSERT(!(readPtr % 2));
- ASSERT(!(writePtr % 2));
- while (copySource != copyEnd)
- *copyDst++ = *copySource++;
- m_assembler->recordLinkOffsets(readPtr, jumpsToLink[i].from(), offset);
- readPtr += regionSize;
- writePtr += regionSize;
-
- // Calculate absolute address of the jump target, in the case of backwards
- // branches we need to be precise, forward branches we are pessimistic
- const uint8_t* target;
- if (jumpsToLink[i].to() >= jumpsToLink[i].from())
- target = outData + jumpsToLink[i].to() - offset; // Compensate for what we have collapsed so far
- else
- target = outData + jumpsToLink[i].to() - m_assembler->executableOffsetFor(jumpsToLink[i].to());
-
- JumpLinkType jumpLinkType = m_assembler->computeJumpType(jumpsToLink[i], outData + writePtr, target);
- // Compact branch if we can...
- if (m_assembler->canCompact(jumpsToLink[i].type())) {
- // Step back in the write stream
- int32_t delta = m_assembler->jumpSizeDelta(jumpsToLink[i].type(), jumpLinkType);
- if (delta) {
- writePtr -= delta;
- m_assembler->recordLinkOffsets(jumpsToLink[i].from() - delta, readPtr, readPtr - writePtr);
- }
- }
- jumpsToLink[i].setFrom(writePtr);
- }
- // Copy everything after the last jump
- memcpy(outData + writePtr, inData + readPtr, m_initialSize - readPtr);
- m_assembler->recordLinkOffsets(readPtr, m_initialSize, readPtr - writePtr);
-
- for (unsigned i = 0; i < jumpCount; ++i) {
- uint8_t* location = outData + jumpsToLink[i].from();
- uint8_t* target = outData + jumpsToLink[i].to() - m_assembler->executableOffsetFor(jumpsToLink[i].to());
- m_assembler->link(jumpsToLink[i], location, target);
- }
-
- jumpsToLink.clear();
- m_size = writePtr + m_initialSize - readPtr;
- m_executableMemory->shrink(m_size);
-
-#if DUMP_LINK_STATISTICS
- dumpLinkStatistics(m_code, m_initialSize, m_size);
-#endif
-#if DUMP_CODE
- dumpCode(m_code, m_size);
-#endif
-#endif
- }
+ void linkCode(void* ownerUID, JITCompilationEffort);
- void performFinalization()
- {
-#ifndef NDEBUG
- ASSERT(!m_completed);
- ASSERT(isValid());
- m_completed = true;
-#endif
-
-#if ENABLE(BRANCH_COMPACTION)
- ExecutableAllocator::makeExecutable(code(), m_initialSize);
-#else
- ExecutableAllocator::makeExecutable(code(), m_size);
-#endif
- MacroAssembler::cacheFlush(code(), m_size);
- }
+ void performFinalization();
#if DUMP_LINK_STATISTICS
- static void dumpLinkStatistics(void* code, size_t initialSize, size_t finalSize)
- {
- static unsigned linkCount = 0;
- static unsigned totalInitialSize = 0;
- static unsigned totalFinalSize = 0;
- linkCount++;
- totalInitialSize += initialSize;
- totalFinalSize += finalSize;
- dataLog("link %p: orig %u, compact %u (delta %u, %.2f%%)\n",
- code, static_cast<unsigned>(initialSize), static_cast<unsigned>(finalSize),
- static_cast<unsigned>(initialSize - finalSize),
- 100.0 * (initialSize - finalSize) / initialSize);
- dataLog("\ttotal %u: orig %u, compact %u (delta %u, %.2f%%)\n",
- linkCount, totalInitialSize, totalFinalSize, totalInitialSize - totalFinalSize,
- 100.0 * (totalInitialSize - totalFinalSize) / totalInitialSize);
- }
+ static void dumpLinkStatistics(void* code, size_t initialSize, size_t finalSize);
#endif
#if DUMP_CODE
- static void dumpCode(void* code, size_t size)
- {
-#if CPU(ARM_THUMB2)
- // Dump the generated code in an asm file format that can be assembled and then disassembled
- // for debugging purposes. For example, save this output as jit.s:
- // gcc -arch armv7 -c jit.s
- // otool -tv jit.o
- static unsigned codeCount = 0;
- unsigned short* tcode = static_cast<unsigned short*>(code);
- size_t tsize = size / sizeof(short);
- char nameBuf[128];
- snprintf(nameBuf, sizeof(nameBuf), "_jsc_jit%u", codeCount++);
- dataLog("\t.syntax unified\n"
- "\t.section\t__TEXT,__text,regular,pure_instructions\n"
- "\t.globl\t%s\n"
- "\t.align 2\n"
- "\t.code 16\n"
- "\t.thumb_func\t%s\n"
- "# %p\n"
- "%s:\n", nameBuf, nameBuf, code, nameBuf);
-
- for (unsigned i = 0; i < tsize; i++)
- dataLog("\t.short\t0x%x\n", tcode[i]);
-#elif CPU(ARM_TRADITIONAL)
- // gcc -c jit.s
- // objdump -D jit.o
- static unsigned codeCount = 0;
- unsigned int* tcode = static_cast<unsigned int*>(code);
- size_t tsize = size / sizeof(unsigned int);
- char nameBuf[128];
- snprintf(nameBuf, sizeof(nameBuf), "_jsc_jit%u", codeCount++);
- dataLog("\t.globl\t%s\n"
- "\t.align 4\n"
- "\t.code 32\n"
- "\t.text\n"
- "# %p\n"
- "%s:\n", nameBuf, code, nameBuf);
-
- for (unsigned i = 0; i < tsize; i++)
- dataLog("\t.long\t0x%x\n", tcode[i]);
-#endif
- }
+ static void dumpCode(void* code, size_t);
#endif
RefPtr<ExecutableMemoryHandle> m_executableMemory;
@@ -410,6 +257,27 @@ private:
#endif
};
+// Use this to finalize code, like so:
+//
+// CodeRef code = FINALIZE_CODE(linkBuffer, ("my super thingy number %d", number));
+//
+// Which, in disassembly mode, will print:
+//
+// Generated JIT code for my super thingy number 42:
+// Code at [0x123456, 0x234567]:
+// 0x123456: mov $0, 0
+// 0x12345a: ret
+//
+// ... and so on.
+//
+// Note that the dataLogArgumentsForHeading are only evaluated when showDisassembly
+// is true, so you can hide expensive disassembly-only computations inside there.
+
+#define FINALIZE_CODE(linkBufferReference, dataLogArgumentsForHeading) \
+ (UNLIKELY(Options::showDisassembly) \
+ ? ((linkBufferReference).finalizeCodeWithDisassembly dataLogArgumentsForHeading) \
+ : (linkBufferReference).finalizeCodeWithoutDisassembly())
+
} // namespace JSC
#endif // ENABLE(ASSEMBLER)
diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerARM.h b/Source/JavaScriptCore/assembler/MacroAssemblerARM.h
index 1775cb4cf..8ea29e3a0 100644
--- a/Source/JavaScriptCore/assembler/MacroAssemblerARM.h
+++ b/Source/JavaScriptCore/assembler/MacroAssemblerARM.h
@@ -514,6 +514,13 @@ public:
return branchTest32(cond, ARMRegisters::S1, mask);
}
+ Jump branchTest8(ResultCondition cond, AbsoluteAddress address, TrustedImm32 mask = TrustedImm32(-1))
+ {
+ move(TrustedImmPtr(address.m_ptr), ARMRegisters::S1);
+ load8(Address(ARMRegisters::S1), ARMRegisters::S1);
+ return branchTest32(cond, ARMRegisters::S1, mask);
+ }
+
Jump branchTest32(ResultCondition cond, RegisterID reg, RegisterID mask)
{
ASSERT((cond == Zero) || (cond == NonZero));
@@ -1010,6 +1017,17 @@ public:
return FunctionPtr(reinterpret_cast<void(*)()>(ARMAssembler::readCallTarget(call.dataLocation())));
}
+ static void replaceWithJump(CodeLocationLabel instructionStart, CodeLocationLabel destination)
+ {
+ ASSERT_NOT_REACHED();
+ }
+
+ static ptrdiff_t maxJumpReplacementSize()
+ {
+ ASSERT_NOT_REACHED();
+ return 0;
+ }
+
protected:
ARMAssembler::Condition ARMCondition(RelationalCondition cond)
{
diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h b/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h
index 3b62cb5be..6c0feffcf 100644
--- a/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h
+++ b/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h
@@ -608,7 +608,7 @@ public:
void load8Signed(ImplicitAddress, RegisterID)
{
- unreachableForPlatform();
+ UNREACHABLE_FOR_PLATFORM();
}
void load8(BaseIndex address, RegisterID dest)
@@ -674,7 +674,7 @@ public:
void load16Signed(ImplicitAddress, RegisterID)
{
- unreachableForPlatform();
+ UNREACHABLE_FOR_PLATFORM();
}
DataLabel32 store32WithAddressOffsetPatch(RegisterID src, Address address)
@@ -1186,6 +1186,16 @@ public:
{
m_assembler.nop();
}
+
+ static void replaceWithJump(CodeLocationLabel instructionStart, CodeLocationLabel destination)
+ {
+ ARMv7Assembler::replaceWithJump(instructionStart.dataLocation(), destination.dataLocation());
+ }
+
+ static ptrdiff_t maxJumpReplacementSize()
+ {
+ return ARMv7Assembler::maxJumpReplacementSize();
+ }
// Forwards / external control flow operations:
//
@@ -1356,6 +1366,14 @@ public:
return branchTest32(cond, addressTempRegister, mask);
}
+ Jump branchTest8(ResultCondition cond, AbsoluteAddress address, TrustedImm32 mask = TrustedImm32(-1))
+ {
+ // use addressTempRegister incase the branchTest8 we call uses dataTempRegister. :-/
+ move(TrustedImmPtr(address.m_ptr), addressTempRegister);
+ load8(Address(addressTempRegister), addressTempRegister);
+ return branchTest32(cond, addressTempRegister, mask);
+ }
+
void jump(RegisterID target)
{
m_assembler.bx(target);
@@ -1679,12 +1697,14 @@ public:
protected:
ALWAYS_INLINE Jump jump()
{
+ m_assembler.label(); // Force nop-padding if we're in the middle of a watchpoint.
moveFixedWidthEncoding(TrustedImm32(0), dataTempRegister);
return Jump(m_assembler.bx(dataTempRegister), m_makeJumpPatchable ? ARMv7Assembler::JumpNoConditionFixedSize : ARMv7Assembler::JumpNoCondition);
}
ALWAYS_INLINE Jump makeBranch(ARMv7Assembler::Condition cond)
{
+ m_assembler.label(); // Force nop-padding if we're in the middle of a watchpoint.
m_assembler.it(cond, true, true);
moveFixedWidthEncoding(TrustedImm32(0), dataTempRegister);
return Jump(m_assembler.bx(dataTempRegister), m_makeJumpPatchable ? ARMv7Assembler::JumpConditionFixedSize : ARMv7Assembler::JumpCondition, cond);
diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerCodeRef.h b/Source/JavaScriptCore/assembler/MacroAssemblerCodeRef.h
index ac62c4221..a1b3a8338 100644
--- a/Source/JavaScriptCore/assembler/MacroAssemblerCodeRef.h
+++ b/Source/JavaScriptCore/assembler/MacroAssemblerCodeRef.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2009, 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
@@ -26,7 +26,9 @@
#ifndef MacroAssemblerCodeRef_h
#define MacroAssemblerCodeRef_h
+#include "Disassembler.h"
#include "ExecutableAllocator.h"
+#include <wtf/DataLog.h>
#include <wtf/PassRefPtr.h>
#include <wtf/RefPtr.h>
#include <wtf/UnusedParam.h>
@@ -367,6 +369,11 @@ public:
return m_executableMemory->sizeInBytes();
}
+ bool tryToDisassemble(const char* prefix) const
+ {
+ return JSC::tryToDisassemble(m_codePtr, size(), prefix, WTF::dataFile());
+ }
+
bool operator!() const { return !m_codePtr; }
private:
diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h b/Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h
index f9c3457b5..5adcf9b4e 100644
--- a/Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h
+++ b/Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h
@@ -1149,6 +1149,13 @@ public:
return branchTest32(cond, dataTempRegister, mask);
}
+ Jump branchTest8(ResultCondition cond, AbsoluteAddress address, TrustedImm32 mask = TrustedImm32(-1))
+ {
+ move(TrustedImmPtr(address.m_ptr), dataTempRegister);
+ load8(Address(dataTempRegister), dataTempRegister);
+ return branchTest32(cond, dataTempRegister, mask);
+ }
+
Jump jump()
{
return branchEqual(MIPSRegisters::zero, MIPSRegisters::zero);
@@ -1868,6 +1875,17 @@ public:
return FunctionPtr(reinterpret_cast<void(*)()>(MIPSAssembler::readCallTarget(call.dataLocation())));
}
+ static void replaceWithJump(CodeLocationLabel instructionStart, CodeLocationLabel destination)
+ {
+ ASSERT_NOT_REACHED();
+ }
+
+ static ptrdiff_t maxJumpReplacementSize()
+ {
+ ASSERT_NOT_REACHED();
+ return 0;
+ }
+
private:
// If m_fixedWidth is true, we will generate a fixed number of instructions.
// Otherwise, we can emit any number of instructions.
diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerSH4.h b/Source/JavaScriptCore/assembler/MacroAssemblerSH4.h
index c132ad642..badf35f81 100644
--- a/Source/JavaScriptCore/assembler/MacroAssemblerSH4.h
+++ b/Source/JavaScriptCore/assembler/MacroAssemblerSH4.h
@@ -1293,6 +1293,16 @@ void or32(TrustedImm32 imm, RegisterID src, RegisterID dest)
return jmp;
}
+ Jump branchTest8(ResultCondition cond, AbsoluteAddress address, TrustedImm32 mask = TrustedImm32(-1))
+ {
+ RegisterID addressTempRegister = claimScratch();
+ move(TrustedImmPtr(address.m_ptr), addressTempRegister);
+ load8(Address(addressTempRegister), addressTempRegister);
+ Jump jmp = branchTest32(cond, addressTempRegister, mask);
+ releaseScratch(addressTempRegister);
+ return jmp;
+ }
+
void signExtend32ToPtr(RegisterID src, RegisterID dest)
{
if (src != dest)
@@ -1971,6 +1981,17 @@ void or32(TrustedImm32 imm, RegisterID src, RegisterID dest)
return FunctionPtr(reinterpret_cast<void(*)()>(SH4Assembler::readCallTarget(call.dataLocation())));
}
+ static void replaceWithJump(CodeLocationLabel instructionStart, CodeLocationLabel destination)
+ {
+ ASSERT_NOT_REACHED();
+ }
+
+ static ptrdiff_t maxJumpReplacementSize()
+ {
+ ASSERT_NOT_REACHED();
+ return 0;
+ }
+
protected:
SH4Assembler::Condition SH4Condition(RelationalCondition cond)
{
diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerX86.h b/Source/JavaScriptCore/assembler/MacroAssemblerX86.h
index 088fe196b..3ea40c967 100644
--- a/Source/JavaScriptCore/assembler/MacroAssemblerX86.h
+++ b/Source/JavaScriptCore/assembler/MacroAssemblerX86.h
@@ -51,6 +51,7 @@ public:
using MacroAssemblerX86Common::loadDouble;
using MacroAssemblerX86Common::storeDouble;
using MacroAssemblerX86Common::convertInt32ToDouble;
+ using MacroAssemblerX86Common::branchTest8;
void add32(TrustedImm32 imm, RegisterID src, RegisterID dest)
{
@@ -165,6 +166,16 @@ public:
m_assembler.movl_i32r(initialValue.asIntptr(), dest);
return DataLabelPtr(this);
}
+
+ Jump branchTest8(ResultCondition cond, AbsoluteAddress address, TrustedImm32 mask = TrustedImm32(-1))
+ {
+ ASSERT(mask.m_value >= -128 && mask.m_value <= 255);
+ if (mask.m_value == -1)
+ m_assembler.cmpb_im(0, address.m_ptr);
+ else
+ m_assembler.testb_im(mask.m_value, address.m_ptr);
+ return Jump(m_assembler.jCC(x86Condition(cond)));
+ }
Jump branchPtrWithPatch(RelationalCondition cond, RegisterID left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0))
{
diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h b/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h
index e398dcdad..432489dbc 100644
--- a/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h
+++ b/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h
@@ -1408,6 +1408,16 @@ public:
m_assembler.nop();
}
+ static void replaceWithJump(CodeLocationLabel instructionStart, CodeLocationLabel destination)
+ {
+ X86Assembler::replaceWithJump(instructionStart.executableAddress(), destination.executableAddress());
+ }
+
+ static ptrdiff_t maxJumpReplacementSize()
+ {
+ return X86Assembler::maxJumpReplacementSize();
+ }
+
protected:
X86Assembler::Condition x86Condition(RelationalCondition cond)
{
diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h b/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h
index 41479f996..fa95b335b 100644
--- a/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h
+++ b/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 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
@@ -513,6 +513,12 @@ public:
MacroAssemblerX86Common::move(addr, scratchRegister);
return MacroAssemblerX86Common::branchTest8(cond, BaseIndex(scratchRegister, address.base, TimesOne), mask);
}
+
+ Jump branchTest8(ResultCondition cond, AbsoluteAddress address, TrustedImm32 mask = TrustedImm32(-1))
+ {
+ MacroAssemblerX86Common::move(TrustedImmPtr(address.m_ptr), scratchRegister);
+ return MacroAssemblerX86Common::branchTest8(cond, Address(scratchRegister), mask);
+ }
static bool supportsFloatingPoint() { return true; }
// See comment on MacroAssemblerARMv7::supportsFloatingPointTruncate()
diff --git a/Source/JavaScriptCore/assembler/X86Assembler.h b/Source/JavaScriptCore/assembler/X86Assembler.h
index ff8d25bcd..8c5606972 100644
--- a/Source/JavaScriptCore/assembler/X86Assembler.h
+++ b/Source/JavaScriptCore/assembler/X86Assembler.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 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
@@ -247,6 +247,8 @@ private:
public:
X86Assembler()
+ : m_indexOfLastWatchpoint(INT_MIN)
+ , m_indexOfTailOfLastWatchpoint(INT_MIN)
{
}
@@ -798,6 +800,14 @@ public:
m_formatter.oneByteOp(OP_GROUP1_EbIb, GROUP1_OP_CMP, base, index, scale, offset);
m_formatter.immediate8(imm);
}
+
+#if CPU(X86)
+ void cmpb_im(int imm, const void* addr)
+ {
+ m_formatter.oneByteOp(OP_GROUP1_EbIb, GROUP1_OP_CMP, addr);
+ m_formatter.immediate8(imm);
+ }
+#endif
void cmpl_im(int imm, int offset, RegisterID base, RegisterID index, int scale)
{
@@ -948,6 +958,14 @@ public:
m_formatter.immediate8(imm);
}
+#if CPU(X86)
+ void testb_im(int imm, const void* addr)
+ {
+ m_formatter.oneByteOp(OP_GROUP3_EbIb, GROUP3_OP_TEST, addr);
+ m_formatter.immediate8(imm);
+ }
+#endif
+
void testl_i32m(int imm, int offset, RegisterID base, RegisterID index, int scale)
{
m_formatter.oneByteOp(OP_GROUP3_EvIz, GROUP3_OP_TEST, base, index, scale, offset);
@@ -1702,10 +1720,25 @@ public:
{
return m_formatter.codeSize();
}
+
+ AssemblerLabel labelForWatchpoint()
+ {
+ AssemblerLabel result = m_formatter.label();
+ if (static_cast<int>(result.m_offset) != m_indexOfLastWatchpoint)
+ result = label();
+ m_indexOfLastWatchpoint = result.m_offset;
+ m_indexOfTailOfLastWatchpoint = result.m_offset + maxJumpReplacementSize();
+ return result;
+ }
AssemblerLabel label()
{
- return m_formatter.label();
+ AssemblerLabel result = m_formatter.label();
+ while (UNLIKELY(static_cast<int>(result.m_offset) < m_indexOfTailOfLastWatchpoint)) {
+ nop();
+ result = m_formatter.label();
+ }
+ return result;
}
AssemblerLabel align(int alignment)
@@ -1787,6 +1820,20 @@ public:
return reinterpret_cast<void**>(where)[-1];
}
+ static void replaceWithJump(void* instructionStart, void* to)
+ {
+ uint8_t* ptr = reinterpret_cast<uint8_t*>(instructionStart);
+ uint8_t* dstPtr = reinterpret_cast<uint8_t*>(to);
+ intptr_t distance = (intptr_t)(dstPtr - (ptr + 5));
+ ptr[0] = static_cast<uint8_t>(OP_JMP_rel32);
+ *reinterpret_cast<int32_t*>(ptr + 1) = static_cast<int32_t>(distance);
+ }
+
+ static ptrdiff_t maxJumpReplacementSize()
+ {
+ return 5;
+ }
+
static unsigned getCallReturnOffset(AssemblerLabel call)
{
ASSERT(call.isSet());
@@ -2339,6 +2386,8 @@ private:
AssemblerBuffer m_buffer;
} m_formatter;
+ int m_indexOfLastWatchpoint;
+ int m_indexOfTailOfLastWatchpoint;
};
} // namespace JSC
diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.cpp b/Source/JavaScriptCore/bytecode/CodeBlock.cpp
index 8ef716028..60596d1c2 100644
--- a/Source/JavaScriptCore/bytecode/CodeBlock.cpp
+++ b/Source/JavaScriptCore/bytecode/CodeBlock.cpp
@@ -228,6 +228,7 @@ void CodeBlock::printGetByIdOp(ExecState* exec, int location, Vector<Instruction
it += 5;
}
+#if ENABLE(JIT) || ENABLE(LLINT) // unused in some configurations
static void dumpStructure(const char* name, ExecState* exec, Structure* structure, Identifier& ident)
{
if (!structure)
@@ -239,7 +240,9 @@ static void dumpStructure(const char* name, ExecState* exec, Structure* structur
if (offset != notFound)
dataLog(" (offset = %lu)", static_cast<unsigned long>(offset));
}
+#endif
+#if ENABLE(JIT) // unused when not ENABLE(JIT), leading to silly warnings
static void dumpChain(ExecState* exec, StructureChain* chain, Identifier& ident)
{
dataLog("chain = %p: [", chain);
@@ -255,6 +258,7 @@ static void dumpChain(ExecState* exec, StructureChain* chain, Identifier& ident)
}
dataLog("]");
}
+#endif
void CodeBlock::printGetByIdCacheStatus(ExecState* exec, int location)
{
@@ -265,6 +269,8 @@ void CodeBlock::printGetByIdCacheStatus(ExecState* exec, int location)
Identifier& ident = identifier(instruction[3].u.operand);
+ UNUSED_PARAM(ident); // tell the compiler to shut up in certain platform configurations.
+
#if ENABLE(LLINT)
Structure* structure = instruction[4].u.structure.get();
dataLog(" llint(");
@@ -923,15 +929,31 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
}
case op_get_global_var: {
int r0 = (++it)->u.operand;
- int index = (++it)->u.operand;
- dataLog("[%4d] get_global_var\t %s, %d\n", location, registerName(exec, r0).data(), index);
+ WriteBarrier<Unknown>* registerPointer = (++it)->u.registerPointer;
+ dataLog("[%4d] get_global_var\t %s, g%d(%p)\n", location, registerName(exec, r0).data(), m_globalObject->findRegisterIndex(registerPointer), registerPointer);
+ it++;
+ break;
+ }
+ case op_get_global_var_watchable: {
+ int r0 = (++it)->u.operand;
+ WriteBarrier<Unknown>* registerPointer = (++it)->u.registerPointer;
+ dataLog("[%4d] get_global_var_watchable\t %s, g%d(%p)\n", location, registerName(exec, r0).data(), m_globalObject->findRegisterIndex(registerPointer), registerPointer);
+ it++;
it++;
break;
}
case op_put_global_var: {
- int index = (++it)->u.operand;
+ WriteBarrier<Unknown>* registerPointer = (++it)->u.registerPointer;
int r0 = (++it)->u.operand;
- dataLog("[%4d] put_global_var\t %d, %s\n", location, index, registerName(exec, r0).data());
+ dataLog("[%4d] put_global_var\t g%d(%p), %s\n", location, m_globalObject->findRegisterIndex(registerPointer), registerPointer, registerName(exec, r0).data());
+ break;
+ }
+ case op_put_global_var_check: {
+ WriteBarrier<Unknown>* registerPointer = (++it)->u.registerPointer;
+ int r0 = (++it)->u.operand;
+ dataLog("[%4d] put_global_var_check\t g%d(%p), %s\n", location, m_globalObject->findRegisterIndex(registerPointer), registerPointer, registerName(exec, r0).data());
+ it++;
+ it++;
break;
}
case op_resolve_base: {
@@ -1145,9 +1167,9 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
}
case op_jneq_ptr: {
int r0 = (++it)->u.operand;
- int r1 = (++it)->u.operand;
+ void* pointer = (++it)->u.pointer;
int offset = (++it)->u.operand;
- dataLog("[%4d] jneq_ptr\t\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset);
+ dataLog("[%4d] jneq_ptr\t\t %s, %p, %d(->%d)\n", location, registerName(exec, r0).data(), pointer, offset, location + offset);
break;
}
case op_jless: {
@@ -1306,7 +1328,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
}
case op_call_put_result: {
int r0 = (++it)->u.operand;
- dataLog("[%4d] op_call_put_result\t\t %s\n", location, registerName(exec, r0).data());
+ dataLog("[%4d] call_put_result\t\t %s\n", location, registerName(exec, r0).data());
it++;
break;
}
@@ -1578,6 +1600,7 @@ CodeBlock::CodeBlock(CopyParsedBlockTag, CodeBlock& other, SymbolTable* symTab)
, m_forcedOSRExitCounter(0)
, m_optimizationDelayCounter(0)
, m_reoptimizationRetryCounter(0)
+ , m_lineInfo(other.m_lineInfo)
#if ENABLE(JIT)
, m_canCompileWithDFGState(DFG::CapabilityLevelNotSet)
#endif
@@ -1585,7 +1608,7 @@ CodeBlock::CodeBlock(CopyParsedBlockTag, CodeBlock& other, SymbolTable* symTab)
setNumParameters(other.numParameters());
optimizeAfterWarmUp();
jitAfterWarmUp();
-
+
if (other.m_rareData) {
createRareDataIfNecessary();
@@ -1596,7 +1619,6 @@ CodeBlock::CodeBlock(CopyParsedBlockTag, CodeBlock& other, SymbolTable* symTab)
m_rareData->m_characterSwitchJumpTables = other.m_rareData->m_characterSwitchJumpTables;
m_rareData->m_stringSwitchJumpTables = other.m_rareData->m_stringSwitchJumpTables;
m_rareData->m_expressionInfo = other.m_rareData->m_expressionInfo;
- m_rareData->m_lineInfo = other.m_rareData->m_lineInfo;
}
}
@@ -2141,10 +2163,7 @@ int CodeBlock::lineNumberForBytecodeOffset(unsigned bytecodeOffset)
{
ASSERT(bytecodeOffset < instructions().size());
- if (!m_rareData)
- return m_ownerExecutable->source().firstLine();
-
- Vector<LineInfo>& lineInfo = m_rareData->m_lineInfo;
+ Vector<LineInfo>& lineInfo = m_lineInfo;
int low = 0;
int high = lineInfo.size();
@@ -2269,6 +2288,7 @@ void CodeBlock::shrinkToFit(ShrinkMode shrinkMode)
m_constantRegisters.shrinkToFit();
} // else don't shrink these, because we would have already pointed pointers into these tables.
+ m_lineInfo.shrinkToFit();
if (m_rareData) {
m_rareData->m_exceptionHandlers.shrinkToFit();
m_rareData->m_regexps.shrinkToFit();
@@ -2276,7 +2296,6 @@ void CodeBlock::shrinkToFit(ShrinkMode shrinkMode)
m_rareData->m_characterSwitchJumpTables.shrinkToFit();
m_rareData->m_stringSwitchJumpTables.shrinkToFit();
m_rareData->m_expressionInfo.shrinkToFit();
- m_rareData->m_lineInfo.shrinkToFit();
#if ENABLE(JIT)
m_rareData->m_callReturnIndexVector.shrinkToFit();
#endif
@@ -2560,7 +2579,7 @@ bool CodeBlock::shouldOptimizeNow()
profile->computeUpdatedPrediction();
continue;
}
- if (profile->numberOfSamples() || profile->m_prediction != PredictNone)
+ if (profile->numberOfSamples() || profile->m_prediction != SpecNone)
numberOfLiveNonArgumentValueProfiles++;
profile->computeUpdatedPrediction();
}
@@ -2614,7 +2633,7 @@ void CodeBlock::dumpValueProfiles()
dataLog(" arg = %u: ", i);
} else
dataLog(" bc = %d: ", profile->m_bytecodeOffset);
- if (!profile->numberOfSamples() && profile->m_prediction == PredictNone) {
+ if (!profile->numberOfSamples() && profile->m_prediction == SpecNone) {
dataLog("<empty>\n");
continue;
}
diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.h b/Source/JavaScriptCore/bytecode/CodeBlock.h
index cdc6a19e8..573d422d3 100644
--- a/Source/JavaScriptCore/bytecode/CodeBlock.h
+++ b/Source/JavaScriptCore/bytecode/CodeBlock.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved.
* Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
*
* Redistribution and use in source and binary forms, with or without
@@ -62,6 +62,7 @@
#include "UString.h"
#include "UnconditionalFinalizer.h"
#include "ValueProfile.h"
+#include "Watchpoint.h"
#include <wtf/RefCountedArray.h>
#include <wtf/FastAllocBase.h>
#include <wtf/PassOwnPtr.h>
@@ -273,10 +274,12 @@ namespace JSC {
return result;
}
- void appendOSRExit(const DFG::OSRExit& osrExit)
+ unsigned appendOSRExit(const DFG::OSRExit& osrExit)
{
createDFGDataIfNecessary();
+ unsigned result = m_dfgData->osrExit.size();
m_dfgData->osrExit.append(osrExit);
+ return result;
}
DFG::OSRExit& lastOSRExit()
@@ -284,10 +287,20 @@ namespace JSC {
return m_dfgData->osrExit.last();
}
- void appendSpeculationRecovery(const DFG::SpeculationRecovery& recovery)
+ unsigned appendSpeculationRecovery(const DFG::SpeculationRecovery& recovery)
{
createDFGDataIfNecessary();
+ unsigned result = m_dfgData->speculationRecovery.size();
m_dfgData->speculationRecovery.append(recovery);
+ return result;
+ }
+
+ unsigned appendWatchpoint(const Watchpoint& watchpoint)
+ {
+ createDFGDataIfNecessary();
+ unsigned result = m_dfgData->watchpoints.size();
+ m_dfgData->watchpoints.append(watchpoint);
+ return result;
}
unsigned numberOfOSRExits()
@@ -304,6 +317,13 @@ namespace JSC {
return m_dfgData->speculationRecovery.size();
}
+ unsigned numberOfWatchpoints()
+ {
+ if (!m_dfgData)
+ return 0;
+ return m_dfgData->watchpoints.size();
+ }
+
DFG::OSRExit& osrExit(unsigned index)
{
return m_dfgData->osrExit[index];
@@ -314,6 +334,11 @@ namespace JSC {
return m_dfgData->speculationRecovery[index];
}
+ Watchpoint& watchpoint(unsigned index)
+ {
+ return m_dfgData->watchpoints[index];
+ }
+
void appendWeakReference(JSCell* target)
{
createDFGDataIfNecessary();
@@ -576,7 +601,7 @@ namespace JSC {
bytecodeOffset].u.opcode)) - 1].u.profile == result);
return result;
}
- PredictedType valueProfilePredictionForBytecodeOffset(int bytecodeOffset)
+ SpeculatedType valueProfilePredictionForBytecodeOffset(int bytecodeOffset)
{
return valueProfileForBytecodeOffset(bytecodeOffset)->computeUpdatedPrediction();
}
@@ -686,8 +711,7 @@ namespace JSC {
void addLineInfo(unsigned bytecodeOffset, int lineNo)
{
- createRareDataIfNecessary();
- Vector<LineInfo>& lineInfo = m_rareData->m_lineInfo;
+ Vector<LineInfo>& lineInfo = m_lineInfo;
if (!lineInfo.size() || lineInfo.last().lineNumber != lineNo) {
LineInfo info = { bytecodeOffset, lineNo };
lineInfo.append(info);
@@ -695,14 +719,6 @@ namespace JSC {
}
bool hasExpressionInfo() { return m_rareData && m_rareData->m_expressionInfo.size(); }
- bool hasLineInfo() { return m_rareData && m_rareData->m_lineInfo.size(); }
- // We only generate exception handling info if the user is debugging
- // (and may want line number info), or if the function contains exception handler.
- bool needsCallReturnIndices()
- {
- return m_rareData &&
- (m_rareData->m_expressionInfo.size() || m_rareData->m_lineInfo.size() || m_rareData->m_exceptionHandlers.size());
- }
#if ENABLE(JIT)
Vector<CallReturnOffsetToBytecodeOffset>& callReturnIndexVector()
@@ -1238,6 +1254,7 @@ namespace JSC {
Vector<DFG::OSREntryData> osrEntry;
SegmentedVector<DFG::OSRExit, 8> osrExit;
Vector<DFG::SpeculationRecovery> speculationRecovery;
+ SegmentedVector<Watchpoint, 1, 0> watchpoints;
Vector<WeakReferenceTransition> transitions;
Vector<WriteBarrier<JSCell> > weakReferences;
bool mayBeExecuting;
@@ -1285,7 +1302,9 @@ namespace JSC {
uint32_t m_forcedOSRExitCounter;
uint16_t m_optimizationDelayCounter;
uint16_t m_reoptimizationRetryCounter;
-
+
+ Vector<LineInfo> m_lineInfo;
+
struct RareData {
WTF_MAKE_FAST_ALLOCATED;
public:
@@ -1307,7 +1326,6 @@ namespace JSC {
// Expression info - present if debugging.
Vector<ExpressionRangeInfo> m_expressionInfo;
// Line info - present if profiling or debugging.
- Vector<LineInfo> m_lineInfo;
#if ENABLE(JIT)
Vector<CallReturnOffsetToBytecodeOffset> m_callReturnIndexVector;
#endif
@@ -1499,6 +1517,11 @@ namespace JSC {
}
#endif
+ inline JSValue Structure::prototypeForLookup(CodeBlock* codeBlock) const
+ {
+ return prototypeForLookup(codeBlock->globalObject());
+ }
+
} // namespace JSC
#endif // CodeBlock_h
diff --git a/Source/JavaScriptCore/bytecode/DFGExitProfile.h b/Source/JavaScriptCore/bytecode/DFGExitProfile.h
index 09f9ee075..d751ce654 100644
--- a/Source/JavaScriptCore/bytecode/DFGExitProfile.h
+++ b/Source/JavaScriptCore/bytecode/DFGExitProfile.h
@@ -41,6 +41,7 @@ enum ExitKind {
InadequateCoverage, // We exited because we ended up in code that didn't have profiling coverage.
ArgumentsEscaped, // We exited because arguments escaped but we didn't expect them to.
Uncountable, // We exited for none of the above reasons, and we should not count it. Most uses of this should be viewed as a FIXME.
+ UncountableWatchpoint // We exited because of a watchpoint, which isn't counted because watchpoints do tracking themselves.
};
inline const char* exitKindToString(ExitKind kind)
@@ -58,6 +59,12 @@ inline const char* exitKindToString(ExitKind kind)
return "NegativeZero";
case InadequateCoverage:
return "InadequateCoverage";
+ case ArgumentsEscaped:
+ return "ArgumentsEscaped";
+ case Uncountable:
+ return "Uncountable";
+ case UncountableWatchpoint:
+ return "UncountableWatchpoint";
default:
return "Unknown";
}
@@ -70,6 +77,7 @@ inline bool exitKindIsCountable(ExitKind kind)
ASSERT_NOT_REACHED();
case BadType:
case Uncountable:
+ case UncountableWatchpoint:
return false;
default:
return true;
diff --git a/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp b/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp
index 11aead3df..a62a43f7f 100644
--- a/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp
+++ b/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp
@@ -44,15 +44,61 @@ GetByIdStatus GetByIdStatus::computeFromLLInt(CodeBlock* profiledBlock, unsigned
Structure* structure = instruction[4].u.structure.get();
if (!structure)
- return GetByIdStatus(NoInformation, StructureSet(), notFound, false);
+ return GetByIdStatus(NoInformation, false);
- size_t offset = structure->get(*profiledBlock->globalData(), ident);
+ unsigned attributesIgnored;
+ JSCell* specificValue;
+ size_t offset = structure->get(
+ *profiledBlock->globalData(), ident, attributesIgnored, specificValue);
if (offset == notFound)
- return GetByIdStatus(NoInformation, StructureSet(), notFound, false);
+ return GetByIdStatus(NoInformation, false);
- return GetByIdStatus(SimpleDirect, StructureSet(structure), offset, false);
+ return GetByIdStatus(Simple, false, StructureSet(structure), offset, specificValue);
#else
- return GetByIdStatus(NoInformation, StructureSet(), notFound, false);
+ return GetByIdStatus(NoInformation, false);
+#endif
+}
+
+void GetByIdStatus::computeForChain(GetByIdStatus& result, CodeBlock* profiledBlock, Identifier& ident, Structure* structure)
+{
+#if ENABLE(JIT) && ENABLE(VALUE_PROFILER)
+ // Validate the chain. If the chain is invalid, then currently the best thing
+ // we can do is to assume that TakesSlow is true. In the future, it might be
+ // worth exploring reifying the structure chain from the structure we've got
+ // instead of using the one from the cache, since that will do the right things
+ // if the structure chain has changed. But that may be harder, because we may
+ // then end up having a different type of access altogether. And it currently
+ // does not appear to be worth it to do so -- effectively, the heuristic we
+ // have now is that if the structure chain has changed between when it was
+ // cached on in the baseline JIT and when the DFG tried to inline the access,
+ // then we fall back on a polymorphic access.
+ Structure* currentStructure = structure;
+ JSObject* currentObject = 0;
+ for (unsigned i = 0; i < result.m_chain.size(); ++i) {
+ currentObject = asObject(currentStructure->prototypeForLookup(profiledBlock));
+ currentStructure = result.m_chain[i];
+ if (currentObject->structure() != currentStructure)
+ return;
+ }
+
+ ASSERT(currentObject);
+
+ unsigned attributesIgnored;
+ JSCell* specificValue;
+
+ result.m_offset = currentStructure->get(
+ *profiledBlock->globalData(), ident, attributesIgnored, specificValue);
+ if (result.m_offset == notFound)
+ return;
+
+ result.m_structureSet.add(structure);
+ result.m_specificValue = JSValue(specificValue);
+#else
+ UNUSED_PARAM(result);
+ UNUSED_PARAM(profiledBlock);
+ UNUSED_PARAM(ident);
+ UNUSED_PARAM(structure);
+ UNREACHABLE_FOR_PLATFORM();
#endif
}
@@ -89,12 +135,12 @@ GetByIdStatus GetByIdStatus::computeFor(CodeBlock* profiledBlock, unsigned bytec
}
for (int i = 0; i < listSize; ++i) {
if (!list->list[i].isDirect)
- return GetByIdStatus(MakesCalls, StructureSet(), notFound, true);
+ return GetByIdStatus(MakesCalls, true);
}
// 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, true);
+ return GetByIdStatus(TakesSlowPath, true);
// Finally figure out if we can derive an access strategy.
GetByIdStatus result;
@@ -105,10 +151,15 @@ GetByIdStatus GetByIdStatus::computeFor(CodeBlock* profiledBlock, unsigned bytec
case access_get_by_id_self: {
Structure* structure = stubInfo.u.getByIdSelf.baseObjectStructure.get();
- result.m_offset = structure->get(*profiledBlock->globalData(), ident);
+ unsigned attributesIgnored;
+ JSCell* specificValue;
+ result.m_offset = structure->get(
+ *profiledBlock->globalData(), ident, attributesIgnored, specificValue);
- if (result.m_offset != notFound)
+ if (result.m_offset != notFound) {
result.m_structureSet.add(structure);
+ result.m_specificValue = JSValue(specificValue);
+ }
if (result.m_offset != notFound)
ASSERT(result.m_structureSet.size());
@@ -116,29 +167,32 @@ GetByIdStatus GetByIdStatus::computeFor(CodeBlock* profiledBlock, unsigned bytec
}
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) {
+ for (int i = 0; i < listSize; ++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);
+ unsigned attributesIgnored;
+ JSCell* specificValue;
+ size_t myOffset = structure->get(
+ *profiledBlock->globalData(), ident, attributesIgnored, specificValue);
if (myOffset == notFound) {
result.m_offset = notFound;
break;
}
- if (!i)
+ if (!i) {
result.m_offset = myOffset;
- else if (result.m_offset != myOffset) {
+ result.m_specificValue = JSValue(specificValue);
+ } else if (result.m_offset != myOffset) {
result.m_offset = notFound;
break;
- }
-
+ } else if (result.m_specificValue != JSValue(specificValue))
+ result.m_specificValue = JSValue();
+
result.m_structureSet.add(structure);
}
@@ -147,6 +201,27 @@ GetByIdStatus GetByIdStatus::computeFor(CodeBlock* profiledBlock, unsigned bytec
break;
}
+ case access_get_by_id_proto: {
+ if (!stubInfo.u.getByIdProto.isDirect)
+ return GetByIdStatus(MakesCalls, true);
+ result.m_chain.append(stubInfo.u.getByIdProto.prototypeStructure.get());
+ computeForChain(
+ result, profiledBlock, ident,
+ stubInfo.u.getByIdProto.baseObjectStructure.get());
+ break;
+ }
+
+ case access_get_by_id_chain: {
+ if (!stubInfo.u.getByIdChain.isDirect)
+ return GetByIdStatus(MakesCalls, true);
+ for (unsigned i = 0; i < stubInfo.u.getByIdChain.count; ++i)
+ result.m_chain.append(stubInfo.u.getByIdChain.chain->head()[i].get());
+ computeForChain(
+ result, profiledBlock, ident,
+ stubInfo.u.getByIdChain.baseObjectStructure.get());
+ break;
+ }
+
default:
ASSERT(result.m_offset == notFound);
break;
@@ -155,12 +230,14 @@ GetByIdStatus GetByIdStatus::computeFor(CodeBlock* profiledBlock, unsigned bytec
if (result.m_offset == notFound) {
result.m_state = TakesSlowPath;
result.m_structureSet.clear();
+ result.m_chain.clear();
+ result.m_specificValue = JSValue();
} else
- result.m_state = SimpleDirect;
+ result.m_state = Simple;
return result;
#else // ENABLE(JIT)
- return GetByIdStatus(NoInformation, StructureSet(), notFound, false);
+ return GetByIdStatus(NoInformation, false);
#endif // ENABLE(JIT)
}
diff --git a/Source/JavaScriptCore/bytecode/GetByIdStatus.h b/Source/JavaScriptCore/bytecode/GetByIdStatus.h
index 39476c009..42eadfd68 100644
--- a/Source/JavaScriptCore/bytecode/GetByIdStatus.h
+++ b/Source/JavaScriptCore/bytecode/GetByIdStatus.h
@@ -38,7 +38,8 @@ 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.
+ Simple, // It's cached for a simple access to a known object property with
+ // a possible structure chain and a possible specific value.
TakesSlowPath, // It's known to often take slow path.
MakesCalls // It's known to take paths that make calls.
};
@@ -49,13 +50,17 @@ public:
{
}
- GetByIdStatus(State state, const StructureSet& structureSet, size_t offset, bool wasSeenInJIT)
+ GetByIdStatus(
+ State state, bool wasSeenInJIT, const StructureSet& structureSet = StructureSet(),
+ size_t offset = notFound, JSValue specificValue = JSValue(), Vector<Structure*> chain = Vector<Structure*>())
: m_state(state)
, m_structureSet(structureSet)
+ , m_chain(chain)
+ , m_specificValue(specificValue)
, m_offset(offset)
, m_wasSeenInJIT(wasSeenInJIT)
{
- ASSERT((state == SimpleDirect) == (offset != notFound));
+ ASSERT((state == Simple) == (offset != notFound));
}
static GetByIdStatus computeFor(CodeBlock*, unsigned bytecodeIndex, Identifier&);
@@ -64,20 +69,25 @@ public:
bool isSet() const { return m_state != NoInformation; }
bool operator!() const { return !isSet(); }
- bool isSimpleDirect() const { return m_state == SimpleDirect; }
+ bool isSimple() const { return m_state == Simple; }
bool takesSlowPath() const { return m_state == TakesSlowPath || m_state == MakesCalls; }
bool makesCalls() const { return m_state == MakesCalls; }
const StructureSet& structureSet() const { return m_structureSet; }
+ const Vector<Structure*>& chain() const { return m_chain; } // Returns empty vector if this is a direct access.
+ JSValue specificValue() const { return m_specificValue; } // Returns JSValue() if there is no specific value.
size_t offset() const { return m_offset; }
bool wasSeenInJIT() const { return m_wasSeenInJIT; }
private:
+ static void computeForChain(GetByIdStatus& result, CodeBlock*, Identifier&, Structure*);
static GetByIdStatus computeFromLLInt(CodeBlock*, unsigned bytecodeIndex, Identifier&);
State m_state;
StructureSet m_structureSet;
+ Vector<Structure*> m_chain;
+ JSValue m_specificValue;
size_t m_offset;
bool m_wasSeenInJIT;
};
diff --git a/Source/JavaScriptCore/bytecode/Instruction.h b/Source/JavaScriptCore/bytecode/Instruction.h
index c4989d2db..6e76512ff 100644
--- a/Source/JavaScriptCore/bytecode/Instruction.h
+++ b/Source/JavaScriptCore/bytecode/Instruction.h
@@ -191,6 +191,10 @@ namespace JSC {
Instruction(LLIntCallLinkInfo* callLinkInfo) { u.callLinkInfo = callLinkInfo; }
Instruction(ValueProfile* profile) { u.profile = profile; }
+
+ Instruction(WriteBarrier<Unknown>* registerPointer) { u.registerPointer = registerPointer; }
+
+ Instruction(bool* predicatePointer) { u.predicatePointer = predicatePointer; }
union {
Opcode opcode;
@@ -198,10 +202,12 @@ namespace JSC {
WriteBarrierBase<Structure> structure;
WriteBarrierBase<StructureChain> structureChain;
WriteBarrierBase<JSCell> jsCell;
+ WriteBarrier<Unknown>* registerPointer;
PropertySlot::GetValueFunc getterFunc;
LLIntCallLinkInfo* callLinkInfo;
ValueProfile* profile;
void* pointer;
+ bool* predicatePointer;
} u;
private:
diff --git a/Source/JavaScriptCore/bytecode/LazyOperandValueProfile.cpp b/Source/JavaScriptCore/bytecode/LazyOperandValueProfile.cpp
index 695e21219..59f0d0234 100644
--- a/Source/JavaScriptCore/bytecode/LazyOperandValueProfile.cpp
+++ b/Source/JavaScriptCore/bytecode/LazyOperandValueProfile.cpp
@@ -84,12 +84,12 @@ LazyOperandValueProfile* LazyOperandValueProfileParser::getIfPresent(
return iter->second;
}
-PredictedType LazyOperandValueProfileParser::prediction(
+SpeculatedType LazyOperandValueProfileParser::prediction(
const LazyOperandValueProfileKey& key) const
{
LazyOperandValueProfile* profile = getIfPresent(key);
if (!profile)
- return PredictNone;
+ return SpecNone;
return profile->computeUpdatedPrediction();
}
diff --git a/Source/JavaScriptCore/bytecode/LazyOperandValueProfile.h b/Source/JavaScriptCore/bytecode/LazyOperandValueProfile.h
index 91e5314aa..a117db64f 100644
--- a/Source/JavaScriptCore/bytecode/LazyOperandValueProfile.h
+++ b/Source/JavaScriptCore/bytecode/LazyOperandValueProfile.h
@@ -174,7 +174,7 @@ public:
LazyOperandValueProfile* getIfPresent(
const LazyOperandValueProfileKey& key) const;
- PredictedType prediction(const LazyOperandValueProfileKey& key) const;
+ SpeculatedType prediction(const LazyOperandValueProfileKey& key) const;
private:
CompressedLazyOperandValueProfileHolder& m_holder;
HashMap<LazyOperandValueProfileKey, LazyOperandValueProfile*> m_map;
diff --git a/Source/JavaScriptCore/bytecode/Opcode.h b/Source/JavaScriptCore/bytecode/Opcode.h
index aa83d9b97..e0cff165a 100644
--- a/Source/JavaScriptCore/bytecode/Opcode.h
+++ b/Source/JavaScriptCore/bytecode/Opcode.h
@@ -100,7 +100,9 @@ namespace JSC {
macro(op_get_scoped_var, 5) /* has value profiling */ \
macro(op_put_scoped_var, 4) \
macro(op_get_global_var, 4) /* has value profiling */ \
+ macro(op_get_global_var_watchable, 5) /* has value profiling */ \
macro(op_put_global_var, 3) \
+ macro(op_put_global_var_check, 5) \
macro(op_resolve_base, 5) /* has value profiling */ \
macro(op_ensure_property_exists, 3) \
macro(op_resolve_with_base, 5) /* has value profiling */ \
diff --git a/Source/JavaScriptCore/bytecode/PredictedType.h b/Source/JavaScriptCore/bytecode/PredictedType.h
deleted file mode 100644
index 9f0964a14..000000000
--- a/Source/JavaScriptCore/bytecode/PredictedType.h
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
- * 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
- * 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.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE 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 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 PredictedType_h
-#define PredictedType_h
-
-#include "JSValue.h"
-
-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 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 PredictMyArguments = 0x00002000; // It's definitely an Arguments object, and it's definitely the one for my current frame.
-static const PredictedType PredictForeignArguments = 0x00004000; // It's definitely an Arguments object, and it's definitely not mine.
-static const PredictedType PredictArguments = 0x00006000; // It's definitely an Arguments object.
-static const PredictedType PredictObjectOther = 0x00008000; // It's definitely an object but not JSFinalObject, JSArray, or JSFunction.
-static const PredictedType PredictObjectMask = 0x0000ffff; // Bitmask used for testing for any kind of object prediction.
-static const PredictedType PredictString = 0x00010000; // It's definitely a JSString.
-static const PredictedType PredictCellOther = 0x00020000; // It's definitely a JSCell but not a subclass of JSObject and definitely not a JSString.
-static const PredictedType PredictCell = 0x0003ffff; // It's definitely a JSCell.
-static const PredictedType PredictInt32 = 0x00800000; // It's definitely an Int32.
-static const PredictedType PredictDoubleReal = 0x01000000; // It's definitely a non-NaN double.
-static const PredictedType PredictDoubleNaN = 0x02000000; // It's definitely a NaN.
-static const PredictedType PredictDouble = 0x03000000; // It's either a non-NaN or a NaN double.
-static const PredictedType PredictNumber = 0x03800000; // It's either an Int32 or a Double.
-static const PredictedType PredictBoolean = 0x04000000; // It's definitely a Boolean.
-static const PredictedType PredictOther = 0x08000000; // It's definitely none of the above.
-static const PredictedType PredictTop = 0x0fffffff; // It can be any of the above.
-static const PredictedType PredictEmpty = 0x10000000; // It's definitely an empty value marker.
-static const PredictedType PredictEmptyOrTop = 0x1fffffff; // It can be any of the above.
-static const PredictedType FixedIndexedStorageMask = PredictInt8Array | PredictInt16Array | PredictInt32Array | PredictUint8Array | PredictUint8ClampedArray | PredictUint16Array | PredictUint32Array | PredictFloat32Array | PredictFloat64Array;
-
-typedef bool (*PredictionChecker)(PredictedType);
-
-// Dummy prediction checker, only useful if someone insists on requiring a prediction checker.
-inline bool isAnyPrediction(PredictedType)
-{
- return true;
-}
-
-inline bool isCellPrediction(PredictedType value)
-{
- return !!(value & PredictCell) && !(value & ~PredictCell);
-}
-
-inline bool isObjectPrediction(PredictedType value)
-{
- return !!(value & PredictObjectMask) && !(value & ~PredictObjectMask);
-}
-
-inline bool isFinalObjectPrediction(PredictedType value)
-{
- return value == PredictFinalObject;
-}
-
-inline bool isFinalObjectOrOtherPrediction(PredictedType value)
-{
- return !!(value & (PredictFinalObject | PredictOther)) && !(value & ~(PredictFinalObject | PredictOther));
-}
-
-inline bool isFixedIndexedStorageObjectPrediction(PredictedType value)
-{
- return !!value && (value & FixedIndexedStorageMask) == value;
-}
-
-inline bool isStringPrediction(PredictedType value)
-{
- return value == PredictString;
-}
-
-inline bool isArrayPrediction(PredictedType value)
-{
- return value == PredictArray;
-}
-
-inline bool isFunctionPrediction(PredictedType value)
-{
- return value == PredictFunction;
-}
-
-inline bool isInt8ArrayPrediction(PredictedType value)
-{
- return value == PredictInt8Array;
-}
-
-inline bool isInt16ArrayPrediction(PredictedType value)
-{
- return value == PredictInt16Array;
-}
-
-inline bool isInt32ArrayPrediction(PredictedType value)
-{
- return value == PredictInt32Array;
-}
-
-inline bool isUint8ArrayPrediction(PredictedType value)
-{
- return value == PredictUint8Array;
-}
-
-inline bool isUint8ClampedArrayPrediction(PredictedType value)
-{
- return value == PredictUint8ClampedArray;
-}
-
-inline bool isUint16ArrayPrediction(PredictedType value)
-{
- return value == PredictUint16Array;
-}
-
-inline bool isUint32ArrayPrediction(PredictedType value)
-{
- return value == PredictUint32Array;
-}
-
-inline bool isFloat32ArrayPrediction(PredictedType value)
-{
- return value == PredictFloat32Array;
-}
-
-inline bool isFloat64ArrayPrediction(PredictedType value)
-{
- return value == PredictFloat64Array;
-}
-
-inline bool isArgumentsPrediction(PredictedType value)
-{
- return !!value && (value & PredictArguments) == value;
-}
-
-inline bool isActionableIntMutableArrayPrediction(PredictedType value)
-{
- return isInt8ArrayPrediction(value)
- || isInt16ArrayPrediction(value)
- || isInt32ArrayPrediction(value)
- || isUint8ArrayPrediction(value)
- || isUint8ClampedArrayPrediction(value)
- || isUint16ArrayPrediction(value)
- || isUint32ArrayPrediction(value);
-}
-
-inline bool isActionableFloatMutableArrayPrediction(PredictedType value)
-{
- return isFloat32ArrayPrediction(value)
- || isFloat64ArrayPrediction(value);
-}
-
-inline bool isActionableTypedMutableArrayPrediction(PredictedType value)
-{
- return isActionableIntMutableArrayPrediction(value)
- || isActionableFloatMutableArrayPrediction(value);
-}
-
-inline bool isActionableMutableArrayPrediction(PredictedType value)
-{
- return isArrayPrediction(value)
- || isArgumentsPrediction(value)
- || isActionableTypedMutableArrayPrediction(value);
-}
-
-inline bool isActionableArrayPrediction(PredictedType value)
-{
- return isStringPrediction(value)
- || isActionableMutableArrayPrediction(value);
-}
-
-inline bool isArrayOrOtherPrediction(PredictedType value)
-{
- return !!(value & (PredictArray | PredictOther)) && !(value & ~(PredictArray | PredictOther));
-}
-
-inline bool isMyArgumentsPrediction(PredictedType value)
-{
- return value == PredictMyArguments;
-}
-
-inline bool isInt32Prediction(PredictedType value)
-{
- return value == PredictInt32;
-}
-
-inline bool isDoubleRealPrediction(PredictedType value)
-{
- return value == PredictDoubleReal;
-}
-
-inline bool isDoublePrediction(PredictedType value)
-{
- return !!value && (value & PredictDouble) == value;
-}
-
-inline bool isNumberPrediction(PredictedType value)
-{
- return !!(value & PredictNumber) && !(value & ~PredictNumber);
-}
-
-inline bool isBooleanPrediction(PredictedType value)
-{
- return value == PredictBoolean;
-}
-
-inline bool isOtherPrediction(PredictedType value)
-{
- return value == PredictOther;
-}
-
-inline bool isEmptyPrediction(PredictedType value)
-{
- return value == PredictEmpty;
-}
-
-const char* predictionToString(PredictedType value);
-const char* predictionToAbbreviatedString(PredictedType value);
-
-// Merge two predictions. Note that currently this just does left | right. It may
-// seem tempting to do so directly, but you would be doing so at your own peril,
-// since the merging protocol PredictedType may change at any time (and has already
-// changed several times in its history).
-inline PredictedType mergePredictions(PredictedType left, PredictedType right)
-{
- return left | right;
-}
-
-template<typename T>
-inline bool mergePrediction(T& left, PredictedType right)
-{
- PredictedType newPrediction = static_cast<T>(mergePredictions(static_cast<PredictedType>(left), right));
- bool result = newPrediction != static_cast<PredictedType>(left);
- left = newPrediction;
- return result;
-}
-
-PredictedType predictionFromClassInfo(const ClassInfo*);
-PredictedType predictionFromStructure(Structure*);
-PredictedType predictionFromCell(JSCell*);
-PredictedType predictionFromValue(JSValue);
-
-} // namespace JSC
-
-#endif // PredictedType_h
diff --git a/Source/JavaScriptCore/bytecode/PutByIdStatus.cpp b/Source/JavaScriptCore/bytecode/PutByIdStatus.cpp
index 209d4cd5e..3715606fe 100644
--- a/Source/JavaScriptCore/bytecode/PutByIdStatus.cpp
+++ b/Source/JavaScriptCore/bytecode/PutByIdStatus.cpp
@@ -53,6 +53,8 @@ PutByIdStatus PutByIdStatus::computeFromLLInt(CodeBlock* profiledBlock, unsigned
return PutByIdStatus(SimpleReplace, structure, 0, 0, offset);
}
+ ASSERT(structure->transitionWatchpointSetHasBeenInvalidated());
+
ASSERT(instruction[0].u.opcode == llint_op_put_by_id_transition_direct
|| instruction[0].u.opcode == llint_op_put_by_id_transition_normal);
@@ -106,6 +108,7 @@ PutByIdStatus PutByIdStatus::computeFor(CodeBlock* profiledBlock, unsigned bytec
case access_put_by_id_transition_normal:
case access_put_by_id_transition_direct: {
+ ASSERT(stubInfo.u.putByIdTransition.previousStructure->transitionWatchpointSetHasBeenInvalidated());
size_t offset = stubInfo.u.putByIdTransition.structure->get(
*profiledBlock->globalData(), ident);
if (offset != notFound) {
diff --git a/Source/JavaScriptCore/bytecode/PredictedType.cpp b/Source/JavaScriptCore/bytecode/SpeculatedType.cpp
index 5258f4079..02d0f7e77 100644
--- a/Source/JavaScriptCore/bytecode/PredictedType.cpp
+++ b/Source/JavaScriptCore/bytecode/SpeculatedType.cpp
@@ -27,7 +27,7 @@
*/
#include "config.h"
-#include "PredictedType.h"
+#include "SpeculatedType.h"
#include "Arguments.h"
#include "JSArray.h"
@@ -37,9 +37,9 @@
namespace JSC {
-const char* predictionToString(PredictedType value)
+const char* speculationToString(SpeculatedType value)
{
- if (value == PredictNone)
+ if (value == SpecNone)
return "None";
static const int size = 256;
@@ -48,112 +48,112 @@ const char* predictionToString(PredictedType value)
bool isTop = true;
- if (value & PredictCellOther)
+ if (value & SpecCellOther)
ptr.strcat("Othercell");
else
isTop = false;
- if (value & PredictObjectOther)
+ if (value & SpecObjectOther)
ptr.strcat("Otherobj");
else
isTop = false;
- if (value & PredictFinalObject)
+ if (value & SpecFinalObject)
ptr.strcat("Final");
else
isTop = false;
- if (value & PredictArray)
+ if (value & SpecArray)
ptr.strcat("Array");
else
isTop = false;
- if (value & PredictInt8Array)
+ if (value & SpecInt8Array)
ptr.strcat("Int8array");
else
isTop = false;
- if (value & PredictInt16Array)
+ if (value & SpecInt16Array)
ptr.strcat("Int16array");
else
isTop = false;
- if (value & PredictInt32Array)
+ if (value & SpecInt32Array)
ptr.strcat("Int32array");
else
isTop = false;
- if (value & PredictUint8Array)
+ if (value & SpecUint8Array)
ptr.strcat("Uint8array");
else
isTop = false;
- if (value & PredictUint8ClampedArray)
+ if (value & SpecUint8ClampedArray)
ptr.strcat("Uint8clampedarray");
else
isTop = false;
- if (value & PredictUint16Array)
+ if (value & SpecUint16Array)
ptr.strcat("Uint16array");
else
isTop = false;
- if (value & PredictUint32Array)
+ if (value & SpecUint32Array)
ptr.strcat("Uint32array");
else
isTop = false;
- if (value & PredictFloat32Array)
+ if (value & SpecFloat32Array)
ptr.strcat("Float32array");
else
isTop = false;
- if (value & PredictFloat64Array)
+ if (value & SpecFloat64Array)
ptr.strcat("Float64array");
else
isTop = false;
- if (value & PredictFunction)
+ if (value & SpecFunction)
ptr.strcat("Function");
else
isTop = false;
- if (value & PredictMyArguments)
+ if (value & SpecMyArguments)
ptr.strcat("Myarguments");
else
isTop = false;
- if (value & PredictForeignArguments)
+ if (value & SpecForeignArguments)
ptr.strcat("Foreignarguments");
else
isTop = false;
- if (value & PredictString)
+ if (value & SpecString)
ptr.strcat("String");
else
isTop = false;
- if (value & PredictInt32)
+ if (value & SpecInt32)
ptr.strcat("Int");
else
isTop = false;
- if (value & PredictDoubleReal)
+ if (value & SpecDoubleReal)
ptr.strcat("Doublereal");
else
isTop = false;
- if (value & PredictDoubleNaN)
+ if (value & SpecDoubleNaN)
ptr.strcat("Doublenan");
else
isTop = false;
- if (value & PredictBoolean)
+ if (value & SpecBoolean)
ptr.strcat("Bool");
else
isTop = false;
- if (value & PredictOther)
+ if (value & SpecOther)
ptr.strcat("Other");
else
isTop = false;
@@ -163,7 +163,7 @@ const char* predictionToString(PredictedType value)
ptr.strcat("Top");
}
- if (value & PredictEmpty)
+ if (value & SpecEmpty)
ptr.strcat("Empty");
*ptr++ = 0;
@@ -171,130 +171,130 @@ const char* predictionToString(PredictedType value)
return description;
}
-const char* predictionToAbbreviatedString(PredictedType prediction)
+const char* speculationToAbbreviatedString(SpeculatedType prediction)
{
- if (isFinalObjectPrediction(prediction))
+ if (isFinalObjectSpeculation(prediction))
return "<Final>";
- if (isArrayPrediction(prediction))
+ if (isArraySpeculation(prediction))
return "<Array>";
- if (isStringPrediction(prediction))
+ if (isStringSpeculation(prediction))
return "<String>";
- if (isFunctionPrediction(prediction))
+ if (isFunctionSpeculation(prediction))
return "<Function>";
- if (isInt8ArrayPrediction(prediction))
+ if (isInt8ArraySpeculation(prediction))
return "<Int8array>";
- if (isInt16ArrayPrediction(prediction))
+ if (isInt16ArraySpeculation(prediction))
return "<Int16array>";
- if (isInt32ArrayPrediction(prediction))
+ if (isInt32ArraySpeculation(prediction))
return "<Int32array>";
- if (isUint8ArrayPrediction(prediction))
+ if (isUint8ArraySpeculation(prediction))
return "<Uint8array>";
- if (isUint16ArrayPrediction(prediction))
+ if (isUint16ArraySpeculation(prediction))
return "<Uint16array>";
- if (isUint32ArrayPrediction(prediction))
+ if (isUint32ArraySpeculation(prediction))
return "<Uint32array>";
- if (isFloat32ArrayPrediction(prediction))
+ if (isFloat32ArraySpeculation(prediction))
return "<Float32array>";
- if (isFloat64ArrayPrediction(prediction))
+ if (isFloat64ArraySpeculation(prediction))
return "<Float64array>";
- if (isMyArgumentsPrediction(prediction))
+ if (isMyArgumentsSpeculation(prediction))
return "<Myarguments>";
- if (isArgumentsPrediction(prediction))
+ if (isArgumentsSpeculation(prediction))
return "<Arguments>";
- if (isObjectPrediction(prediction))
+ if (isObjectSpeculation(prediction))
return "<Object>";
- if (isCellPrediction(prediction))
+ if (isCellSpeculation(prediction))
return "<Cell>";
- if (isInt32Prediction(prediction))
+ if (isInt32Speculation(prediction))
return "<Int32>";
- if (isDoublePrediction(prediction))
+ if (isDoubleSpeculation(prediction))
return "<Double>";
- if (isNumberPrediction(prediction))
+ if (isNumberSpeculation(prediction))
return "<Number>";
- if (isBooleanPrediction(prediction))
+ if (isBooleanSpeculation(prediction))
return "<Boolean>";
- if (isOtherPrediction(prediction))
+ if (isOtherSpeculation(prediction))
return "<Other>";
return "";
}
-PredictedType predictionFromClassInfo(const ClassInfo* classInfo)
+SpeculatedType speculationFromClassInfo(const ClassInfo* classInfo)
{
if (classInfo == &JSFinalObject::s_info)
- return PredictFinalObject;
+ return SpecFinalObject;
if (classInfo == &JSArray::s_info)
- return PredictArray;
+ return SpecArray;
if (classInfo == &JSString::s_info)
- return PredictString;
+ return SpecString;
if (classInfo == &Arguments::s_info)
- return PredictArguments; // Cannot distinguish between MyArguments and ForeignArguments at this stage. That happens in the flow analysis.
+ return SpecArguments; // Cannot distinguish between MyArguments and ForeignArguments at this stage. That happens in the flow analysis.
if (classInfo->isSubClassOf(&JSFunction::s_info))
- return PredictFunction;
+ return SpecFunction;
if (classInfo->typedArrayStorageType != TypedArrayNone) {
switch (classInfo->typedArrayStorageType) {
case TypedArrayInt8:
- return PredictInt8Array;
+ return SpecInt8Array;
case TypedArrayInt16:
- return PredictInt16Array;
+ return SpecInt16Array;
case TypedArrayInt32:
- return PredictInt32Array;
+ return SpecInt32Array;
case TypedArrayUint8:
- return PredictUint8Array;
+ return SpecUint8Array;
case TypedArrayUint8Clamped:
- return PredictUint8ClampedArray;
+ return SpecUint8ClampedArray;
case TypedArrayUint16:
- return PredictUint16Array;
+ return SpecUint16Array;
case TypedArrayUint32:
- return PredictUint32Array;
+ return SpecUint32Array;
case TypedArrayFloat32:
- return PredictFloat32Array;
+ return SpecFloat32Array;
case TypedArrayFloat64:
- return PredictFloat64Array;
+ return SpecFloat64Array;
default:
break;
}
}
if (classInfo->isSubClassOf(&JSObject::s_info))
- return PredictObjectOther;
+ return SpecObjectOther;
- return PredictCellOther;
+ return SpecCellOther;
}
-PredictedType predictionFromStructure(Structure* structure)
+SpeculatedType speculationFromStructure(Structure* structure)
{
- return predictionFromClassInfo(structure->classInfo());
+ return speculationFromClassInfo(structure->classInfo());
}
-PredictedType predictionFromCell(JSCell* cell)
+SpeculatedType speculationFromCell(JSCell* cell)
{
- return predictionFromStructure(cell->structure());
+ return speculationFromStructure(cell->structure());
}
-PredictedType predictionFromValue(JSValue value)
+SpeculatedType speculationFromValue(JSValue value)
{
if (value.isEmpty())
- return PredictEmpty;
+ return SpecEmpty;
if (value.isInt32())
- return PredictInt32;
+ return SpecInt32;
if (value.isDouble()) {
double number = value.asNumber();
if (number == number)
- return PredictDoubleReal;
- return PredictDoubleNaN;
+ return SpecDoubleReal;
+ return SpecDoubleNaN;
}
if (value.isCell())
- return predictionFromCell(value.asCell());
+ return speculationFromCell(value.asCell());
if (value.isBoolean())
- return PredictBoolean;
+ return SpecBoolean;
ASSERT(value.isUndefinedOrNull());
- return PredictOther;
+ return SpecOther;
}
} // namespace JSC
diff --git a/Source/JavaScriptCore/bytecode/SpeculatedType.h b/Source/JavaScriptCore/bytecode/SpeculatedType.h
new file mode 100644
index 000000000..91fb4fe4d
--- /dev/null
+++ b/Source/JavaScriptCore/bytecode/SpeculatedType.h
@@ -0,0 +1,279 @@
+/*
+ * 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
+ * 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.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE 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 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 SpeculatedType_h
+#define SpeculatedType_h
+
+#include "JSValue.h"
+
+namespace JSC {
+
+class Structure;
+
+typedef uint32_t SpeculatedType;
+static const SpeculatedType SpecNone = 0x00000000; // We don't know anything yet.
+static const SpeculatedType SpecFinalObject = 0x00000001; // It's definitely a JSFinalObject.
+static const SpeculatedType SpecArray = 0x00000002; // It's definitely a JSArray.
+static const SpeculatedType SpecFunction = 0x00000008; // It's definitely a JSFunction or one of its subclasses.
+static const SpeculatedType SpecInt8Array = 0x00000010; // It's definitely an Int8Array or one of its subclasses.
+static const SpeculatedType SpecInt16Array = 0x00000020; // It's definitely an Int16Array or one of its subclasses.
+static const SpeculatedType SpecInt32Array = 0x00000040; // It's definitely an Int32Array or one of its subclasses.
+static const SpeculatedType SpecUint8Array = 0x00000080; // It's definitely an Uint8Array or one of its subclasses.
+static const SpeculatedType SpecUint8ClampedArray = 0x00000100; // It's definitely an Uint8ClampedArray or one of its subclasses.
+static const SpeculatedType SpecUint16Array = 0x00000200; // It's definitely an Uint16Array or one of its subclasses.
+static const SpeculatedType SpecUint32Array = 0x00000400; // It's definitely an Uint32Array or one of its subclasses.
+static const SpeculatedType SpecFloat32Array = 0x00000800; // It's definitely an Uint16Array or one of its subclasses.
+static const SpeculatedType SpecFloat64Array = 0x00001000; // It's definitely an Uint16Array or one of its subclasses.
+static const SpeculatedType SpecMyArguments = 0x00002000; // It's definitely an Arguments object, and it's definitely the one for my current frame.
+static const SpeculatedType SpecForeignArguments = 0x00004000; // It's definitely an Arguments object, and it's definitely not mine.
+static const SpeculatedType SpecArguments = 0x00006000; // It's definitely an Arguments object.
+static const SpeculatedType SpecObjectOther = 0x00008000; // It's definitely an object but not JSFinalObject, JSArray, or JSFunction.
+static const SpeculatedType SpecObjectMask = 0x0000ffff; // Bitmask used for testing for any kind of object prediction.
+static const SpeculatedType SpecString = 0x00010000; // It's definitely a JSString.
+static const SpeculatedType SpecCellOther = 0x00020000; // It's definitely a JSCell but not a subclass of JSObject and definitely not a JSString.
+static const SpeculatedType SpecCell = 0x0003ffff; // It's definitely a JSCell.
+static const SpeculatedType SpecInt32 = 0x00800000; // It's definitely an Int32.
+static const SpeculatedType SpecDoubleReal = 0x01000000; // It's definitely a non-NaN double.
+static const SpeculatedType SpecDoubleNaN = 0x02000000; // It's definitely a NaN.
+static const SpeculatedType SpecDouble = 0x03000000; // It's either a non-NaN or a NaN double.
+static const SpeculatedType SpecNumber = 0x03800000; // It's either an Int32 or a Double.
+static const SpeculatedType SpecBoolean = 0x04000000; // It's definitely a Boolean.
+static const SpeculatedType SpecOther = 0x08000000; // It's definitely none of the above.
+static const SpeculatedType SpecTop = 0x0fffffff; // It can be any of the above.
+static const SpeculatedType SpecEmpty = 0x10000000; // It's definitely an empty value marker.
+static const SpeculatedType SpecEmptyOrTop = 0x1fffffff; // It can be any of the above.
+static const SpeculatedType FixedIndexedStorageMask = SpecInt8Array | SpecInt16Array | SpecInt32Array | SpecUint8Array | SpecUint8ClampedArray | SpecUint16Array | SpecUint32Array | SpecFloat32Array | SpecFloat64Array;
+
+typedef bool (*SpeculatedTypeChecker)(SpeculatedType);
+
+// Dummy prediction checker, only useful if someone insists on requiring a prediction checker.
+inline bool isAnySpeculation(SpeculatedType)
+{
+ return true;
+}
+
+inline bool isCellSpeculation(SpeculatedType value)
+{
+ return !!(value & SpecCell) && !(value & ~SpecCell);
+}
+
+inline bool isObjectSpeculation(SpeculatedType value)
+{
+ return !!(value & SpecObjectMask) && !(value & ~SpecObjectMask);
+}
+
+inline bool isFinalObjectSpeculation(SpeculatedType value)
+{
+ return value == SpecFinalObject;
+}
+
+inline bool isFinalObjectOrOtherSpeculation(SpeculatedType value)
+{
+ return !!(value & (SpecFinalObject | SpecOther)) && !(value & ~(SpecFinalObject | SpecOther));
+}
+
+inline bool isFixedIndexedStorageObjectSpeculation(SpeculatedType value)
+{
+ return !!value && (value & FixedIndexedStorageMask) == value;
+}
+
+inline bool isStringSpeculation(SpeculatedType value)
+{
+ return value == SpecString;
+}
+
+inline bool isArraySpeculation(SpeculatedType value)
+{
+ return value == SpecArray;
+}
+
+inline bool isFunctionSpeculation(SpeculatedType value)
+{
+ return value == SpecFunction;
+}
+
+inline bool isInt8ArraySpeculation(SpeculatedType value)
+{
+ return value == SpecInt8Array;
+}
+
+inline bool isInt16ArraySpeculation(SpeculatedType value)
+{
+ return value == SpecInt16Array;
+}
+
+inline bool isInt32ArraySpeculation(SpeculatedType value)
+{
+ return value == SpecInt32Array;
+}
+
+inline bool isUint8ArraySpeculation(SpeculatedType value)
+{
+ return value == SpecUint8Array;
+}
+
+inline bool isUint8ClampedArraySpeculation(SpeculatedType value)
+{
+ return value == SpecUint8ClampedArray;
+}
+
+inline bool isUint16ArraySpeculation(SpeculatedType value)
+{
+ return value == SpecUint16Array;
+}
+
+inline bool isUint32ArraySpeculation(SpeculatedType value)
+{
+ return value == SpecUint32Array;
+}
+
+inline bool isFloat32ArraySpeculation(SpeculatedType value)
+{
+ return value == SpecFloat32Array;
+}
+
+inline bool isFloat64ArraySpeculation(SpeculatedType value)
+{
+ return value == SpecFloat64Array;
+}
+
+inline bool isArgumentsSpeculation(SpeculatedType value)
+{
+ return !!value && (value & SpecArguments) == value;
+}
+
+inline bool isActionableIntMutableArraySpeculation(SpeculatedType value)
+{
+ return isInt8ArraySpeculation(value)
+ || isInt16ArraySpeculation(value)
+ || isInt32ArraySpeculation(value)
+ || isUint8ArraySpeculation(value)
+ || isUint8ClampedArraySpeculation(value)
+ || isUint16ArraySpeculation(value)
+ || isUint32ArraySpeculation(value);
+}
+
+inline bool isActionableFloatMutableArraySpeculation(SpeculatedType value)
+{
+ return isFloat32ArraySpeculation(value)
+ || isFloat64ArraySpeculation(value);
+}
+
+inline bool isActionableTypedMutableArraySpeculation(SpeculatedType value)
+{
+ return isActionableIntMutableArraySpeculation(value)
+ || isActionableFloatMutableArraySpeculation(value);
+}
+
+inline bool isActionableMutableArraySpeculation(SpeculatedType value)
+{
+ return isArraySpeculation(value)
+ || isArgumentsSpeculation(value)
+ || isActionableTypedMutableArraySpeculation(value);
+}
+
+inline bool isActionableArraySpeculation(SpeculatedType value)
+{
+ return isStringSpeculation(value)
+ || isActionableMutableArraySpeculation(value);
+}
+
+inline bool isArrayOrOtherSpeculation(SpeculatedType value)
+{
+ return !!(value & (SpecArray | SpecOther)) && !(value & ~(SpecArray | SpecOther));
+}
+
+inline bool isMyArgumentsSpeculation(SpeculatedType value)
+{
+ return value == SpecMyArguments;
+}
+
+inline bool isInt32Speculation(SpeculatedType value)
+{
+ return value == SpecInt32;
+}
+
+inline bool isDoubleRealSpeculation(SpeculatedType value)
+{
+ return value == SpecDoubleReal;
+}
+
+inline bool isDoubleSpeculation(SpeculatedType value)
+{
+ return !!value && (value & SpecDouble) == value;
+}
+
+inline bool isNumberSpeculation(SpeculatedType value)
+{
+ return !!(value & SpecNumber) && !(value & ~SpecNumber);
+}
+
+inline bool isBooleanSpeculation(SpeculatedType value)
+{
+ return value == SpecBoolean;
+}
+
+inline bool isOtherSpeculation(SpeculatedType value)
+{
+ return value == SpecOther;
+}
+
+inline bool isEmptySpeculation(SpeculatedType value)
+{
+ return value == SpecEmpty;
+}
+
+const char* speculationToString(SpeculatedType value);
+const char* speculationToAbbreviatedString(SpeculatedType value);
+
+// Merge two predictions. Note that currently this just does left | right. It may
+// seem tempting to do so directly, but you would be doing so at your own peril,
+// since the merging protocol SpeculatedType may change at any time (and has already
+// changed several times in its history).
+inline SpeculatedType mergeSpeculations(SpeculatedType left, SpeculatedType right)
+{
+ return left | right;
+}
+
+template<typename T>
+inline bool mergeSpeculation(T& left, SpeculatedType right)
+{
+ SpeculatedType newSpeculation = static_cast<T>(mergeSpeculations(static_cast<SpeculatedType>(left), right));
+ bool result = newSpeculation != static_cast<SpeculatedType>(left);
+ left = newSpeculation;
+ return result;
+}
+
+SpeculatedType speculationFromClassInfo(const ClassInfo*);
+SpeculatedType speculationFromStructure(Structure*);
+SpeculatedType speculationFromCell(JSCell*);
+SpeculatedType speculationFromValue(JSValue);
+
+} // namespace JSC
+
+#endif // SpeculatedType_h
diff --git a/Source/JavaScriptCore/bytecode/StructureSet.h b/Source/JavaScriptCore/bytecode/StructureSet.h
index bfc30fc3c..2bbc50cad 100644
--- a/Source/JavaScriptCore/bytecode/StructureSet.h
+++ b/Source/JavaScriptCore/bytecode/StructureSet.h
@@ -26,7 +26,7 @@
#ifndef StructureSet_h
#define StructureSet_h
-#include "PredictedType.h"
+#include "SpeculatedType.h"
#include "Structure.h"
#include <stdio.h>
#include <wtf/Vector.h>
@@ -90,6 +90,13 @@ public:
return false;
}
+ bool containsOnly(Structure* structure) const
+ {
+ if (size() != 1)
+ return false;
+ return singletonStructure() == structure;
+ }
+
bool isSubsetOf(const StructureSet& other) const
{
for (size_t i = 0; i < m_structures.size(); ++i) {
@@ -115,18 +122,26 @@ public:
return true;
}
+ // Call this if you know that the structure set must consist of exactly
+ // one structure.
+ Structure* singletonStructure() const
+ {
+ ASSERT(m_structures.size() == 1);
+ return m_structures[0];
+ }
+
Structure* at(size_t i) const { return m_structures.at(i); }
Structure* operator[](size_t i) const { return at(i); }
Structure* last() const { return m_structures.last(); }
- PredictedType predictionFromStructures() const
+ SpeculatedType speculationFromStructures() const
{
- PredictedType result = PredictNone;
+ SpeculatedType result = SpecNone;
for (size_t i = 0; i < m_structures.size(); ++i)
- mergePrediction(result, predictionFromStructure(m_structures[i]));
+ mergeSpeculation(result, speculationFromStructure(m_structures[i]));
return result;
}
diff --git a/Source/JavaScriptCore/bytecode/StructureStubInfo.h b/Source/JavaScriptCore/bytecode/StructureStubInfo.h
index 9aa40532a..573f6e975 100644
--- a/Source/JavaScriptCore/bytecode/StructureStubInfo.h
+++ b/Source/JavaScriptCore/bytecode/StructureStubInfo.h
@@ -102,20 +102,23 @@ namespace JSC {
u.getByIdSelf.baseObjectStructure.set(globalData, owner, baseObjectStructure);
}
- void initGetByIdProto(JSGlobalData& globalData, JSCell* owner, Structure* baseObjectStructure, Structure* prototypeStructure)
+ void initGetByIdProto(JSGlobalData& globalData, JSCell* owner, Structure* baseObjectStructure, Structure* prototypeStructure, bool isDirect)
{
accessType = access_get_by_id_proto;
u.getByIdProto.baseObjectStructure.set(globalData, owner, baseObjectStructure);
u.getByIdProto.prototypeStructure.set(globalData, owner, prototypeStructure);
+ u.getByIdProto.isDirect = isDirect;
}
- void initGetByIdChain(JSGlobalData& globalData, JSCell* owner, Structure* baseObjectStructure, StructureChain* chain)
+ void initGetByIdChain(JSGlobalData& globalData, JSCell* owner, Structure* baseObjectStructure, StructureChain* chain, unsigned count, bool isDirect)
{
accessType = access_get_by_id_chain;
u.getByIdChain.baseObjectStructure.set(globalData, owner, baseObjectStructure);
u.getByIdChain.chain.set(globalData, owner, chain);
+ u.getByIdChain.count = count;
+ u.getByIdChain.isDirect = isDirect;
}
void initGetByIdSelfList(PolymorphicAccessStructureList* structureList, int listSize)
@@ -251,10 +254,13 @@ namespace JSC {
struct {
WriteBarrierBase<Structure> baseObjectStructure;
WriteBarrierBase<Structure> prototypeStructure;
+ bool isDirect;
} getByIdProto;
struct {
WriteBarrierBase<Structure> baseObjectStructure;
WriteBarrierBase<StructureChain> chain;
+ unsigned count : 31;
+ bool isDirect : 1;
} getByIdChain;
struct {
PolymorphicAccessStructureList* structureList;
diff --git a/Source/JavaScriptCore/bytecode/ValueProfile.h b/Source/JavaScriptCore/bytecode/ValueProfile.h
index 47fa8b72c..31e76842f 100644
--- a/Source/JavaScriptCore/bytecode/ValueProfile.h
+++ b/Source/JavaScriptCore/bytecode/ValueProfile.h
@@ -35,7 +35,7 @@
#include "Heap.h"
#include "JSArray.h"
-#include "PredictedType.h"
+#include "SpeculatedType.h"
#include "Structure.h"
#include "WriteBarrier.h"
@@ -50,7 +50,7 @@ struct ValueProfileBase {
ValueProfileBase()
: m_bytecodeOffset(-1)
- , m_prediction(PredictNone)
+ , m_prediction(SpecNone)
, m_numberOfSamplesInPrediction(0)
, m_singletonValueIsTop(false)
{
@@ -60,7 +60,7 @@ struct ValueProfileBase {
ValueProfileBase(int bytecodeOffset)
: m_bytecodeOffset(bytecodeOffset)
- , m_prediction(PredictNone)
+ , m_prediction(SpecNone)
, m_numberOfSamplesInPrediction(0)
, m_singletonValueIsTop(false)
{
@@ -114,7 +114,7 @@ struct ValueProfileBase {
fprintf(out,
"samples = %u, prediction = %s",
totalNumberOfSamples(),
- predictionToString(m_prediction));
+ speculationToString(m_prediction));
fprintf(out, ", value = ");
if (m_singletonValueIsTop)
fprintf(out, "TOP");
@@ -135,7 +135,7 @@ struct ValueProfileBase {
}
// Updates the prediction and returns the new one.
- PredictedType computeUpdatedPrediction(OperationInProgress operation = NoOperation)
+ SpeculatedType computeUpdatedPrediction(OperationInProgress operation = NoOperation)
{
for (unsigned i = 0; i < totalNumberOfBuckets; ++i) {
JSValue value = JSValue::decode(m_buckets[i]);
@@ -143,7 +143,7 @@ struct ValueProfileBase {
continue;
m_numberOfSamplesInPrediction++;
- mergePrediction(m_prediction, predictionFromValue(value));
+ mergeSpeculation(m_prediction, speculationFromValue(value));
if (!m_singletonValueIsTop && !!value) {
if (!m_singletonValue)
@@ -167,7 +167,7 @@ struct ValueProfileBase {
int m_bytecodeOffset; // -1 for prologue
- PredictedType m_prediction;
+ SpeculatedType m_prediction;
unsigned m_numberOfSamplesInPrediction;
bool m_singletonValueIsTop;
diff --git a/Source/JavaScriptCore/bytecode/Watchpoint.cpp b/Source/JavaScriptCore/bytecode/Watchpoint.cpp
new file mode 100644
index 000000000..1dd633f52
--- /dev/null
+++ b/Source/JavaScriptCore/bytecode/Watchpoint.cpp
@@ -0,0 +1,127 @@
+/*
+ * 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.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE 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 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 "Watchpoint.h"
+
+#include "LinkBuffer.h"
+
+namespace JSC {
+
+Watchpoint::~Watchpoint()
+{
+ if (isOnList())
+ remove();
+}
+
+#if ENABLE(JIT)
+void Watchpoint::correctLabels(LinkBuffer& linkBuffer)
+{
+ MacroAssembler::Label label;
+ label.m_label.m_offset = m_source;
+ m_source = bitwise_cast<uintptr_t>(linkBuffer.locationOf(label).dataLocation());
+ label.m_label.m_offset = m_destination;
+ m_destination = bitwise_cast<uintptr_t>(linkBuffer.locationOf(label).dataLocation());
+}
+#endif
+
+void Watchpoint::fire()
+{
+#if ENABLE(JIT)
+ MacroAssembler::replaceWithJump(
+ CodeLocationLabel(bitwise_cast<void*>(m_source)),
+ CodeLocationLabel(bitwise_cast<void*>(m_destination)));
+ if (isOnList())
+ remove();
+#else
+ UNREACHABLE_FOR_PLATFORM();
+#endif
+}
+
+WatchpointSet::WatchpointSet(InitialWatchpointSetMode mode)
+ : m_isWatched(mode == InitializedWatching)
+ , m_isInvalidated(false)
+{
+}
+
+WatchpointSet::~WatchpointSet()
+{
+ // Fire all watchpoints. This is necessary because it is possible, say with
+ // structure watchpoints, for the watchpoint set owner to die while the
+ // watchpoint owners are still live.
+ fireAllWatchpoints();
+}
+
+void WatchpointSet::add(Watchpoint* watchpoint)
+{
+ if (!watchpoint)
+ return;
+ m_set.push(watchpoint);
+ m_isWatched = true;
+}
+
+void WatchpointSet::notifyWriteSlow()
+{
+ ASSERT(m_isWatched);
+
+ fireAllWatchpoints();
+ m_isWatched = false;
+ m_isInvalidated = true;
+}
+
+void WatchpointSet::fireAllWatchpoints()
+{
+ while (!m_set.isEmpty())
+ m_set.begin()->fire();
+}
+
+void InlineWatchpointSet::add(Watchpoint* watchpoint)
+{
+ inflate()->add(watchpoint);
+}
+
+WatchpointSet* InlineWatchpointSet::inflateSlow()
+{
+ ASSERT(isThin());
+ WatchpointSet* fat = adoptRef(new WatchpointSet(InitializedBlind)).leakRef();
+ if (m_data & IsInvalidatedFlag)
+ fat->m_isInvalidated = true;
+ if (m_data & IsWatchedFlag)
+ fat->m_isWatched = true;
+ m_data = bitwise_cast<uintptr_t>(fat);
+ return fat;
+}
+
+void InlineWatchpointSet::freeFat()
+{
+ ASSERT(isFat());
+ fat()->deref();
+}
+
+} // namespace JSC
+
diff --git a/Source/JavaScriptCore/bytecode/Watchpoint.h b/Source/JavaScriptCore/bytecode/Watchpoint.h
new file mode 100644
index 000000000..0055bf607
--- /dev/null
+++ b/Source/JavaScriptCore/bytecode/Watchpoint.h
@@ -0,0 +1,220 @@
+/*
+ * 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.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE 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 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 Watchpoint_h
+#define Watchpoint_h
+
+#include "CodeLocation.h"
+#include "MacroAssembler.h"
+#include <wtf/RefCounted.h>
+#include <wtf/SentinelLinkedList.h>
+
+namespace JSC {
+
+class Watchpoint : public BasicRawSentinelNode<Watchpoint> {
+public:
+ Watchpoint()
+ : m_source(std::numeric_limits<uintptr_t>::max())
+ , m_destination(std::numeric_limits<uintptr_t>::max())
+ {
+ }
+
+#if ENABLE(JIT)
+ Watchpoint(MacroAssembler::Label source)
+ : m_source(source.m_label.m_offset)
+ , m_destination(std::numeric_limits<uintptr_t>::max())
+ {
+ }
+
+ void setDestination(MacroAssembler::Label destination)
+ {
+ m_destination = destination.m_label.m_offset;
+ }
+
+ void correctLabels(LinkBuffer&);
+#endif
+
+ ~Watchpoint();
+
+ void fire();
+
+private:
+ uintptr_t m_source;
+ uintptr_t m_destination;
+};
+
+enum InitialWatchpointSetMode { InitializedWatching, InitializedBlind };
+
+class InlineWatchpointSet;
+
+class WatchpointSet : public RefCounted<WatchpointSet> {
+public:
+ WatchpointSet(InitialWatchpointSetMode);
+ ~WatchpointSet();
+
+ bool isStillValid() const { return !m_isInvalidated; }
+ bool hasBeenInvalidated() const { return m_isInvalidated; }
+
+ // As a convenience, this will ignore 0. That's because code paths in the DFG
+ // that create speculation watchpoints may choose to bail out if speculation
+ // had already been terminated.
+ void add(Watchpoint*);
+
+ // Force the watchpoint set to behave as if it was being watched even if no
+ // watchpoints have been installed. This will result in invalidation if the
+ // watchpoint would have fired. That's a pretty good indication that you
+ // probably don't want to set watchpoints, since we typically don't want to
+ // set watchpoints that we believe will actually be fired.
+ void startWatching() { m_isWatched = true; }
+
+ void notifyWrite()
+ {
+ if (!m_isWatched)
+ return;
+ notifyWriteSlow();
+ }
+
+ bool* addressOfIsWatched() { return &m_isWatched; }
+
+ void notifyWriteSlow(); // Call only if you've checked isWatched.
+
+private:
+ void fireAllWatchpoints();
+
+ friend class InlineWatchpointSet;
+
+ SentinelLinkedList<Watchpoint, BasicRawSentinelNode<Watchpoint> > m_set;
+ bool m_isWatched;
+ bool m_isInvalidated;
+};
+
+// InlineWatchpointSet is a low-overhead, non-copyable watchpoint set in which
+// it is not possible to quickly query whether it is being watched in a single
+// branch. There is a fairly simple tradeoff between WatchpointSet and
+// InlineWatchpointSet:
+//
+// Do you have to emit JIT code that rapidly tests whether the watchpoint set
+// is being watched? If so, use WatchpointSet.
+//
+// Do you need multiple parties to have pointers to the same WatchpointSet?
+// If so, use WatchpointSet.
+//
+// Do you have to allocate a lot of watchpoint sets? If so, use
+// InlineWatchpointSet unless you answered "yes" to the previous questions.
+//
+// InlineWatchpointSet will use just one pointer-width word of memory unless
+// you actually add watchpoints to it, in which case it internally inflates
+// to a pointer to a WatchpointSet, and transfers its state to the
+// WatchpointSet.
+
+class InlineWatchpointSet {
+ WTF_MAKE_NONCOPYABLE(InlineWatchpointSet);
+public:
+ InlineWatchpointSet(InitialWatchpointSetMode mode)
+ : m_data((mode == InitializedWatching ? IsWatchedFlag : 0) | IsThinFlag)
+ {
+ }
+
+ ~InlineWatchpointSet()
+ {
+ if (isThin())
+ return;
+ freeFat();
+ }
+
+ bool hasBeenInvalidated() const
+ {
+ if (isFat())
+ return fat()->hasBeenInvalidated();
+ return m_data & IsInvalidatedFlag;
+ }
+
+ bool isStillValid() const
+ {
+ return !hasBeenInvalidated();
+ }
+
+ void add(Watchpoint*);
+
+ void startWatching()
+ {
+ if (isFat()) {
+ fat()->startWatching();
+ return;
+ }
+ m_data |= IsWatchedFlag;
+ }
+
+ void notifyWrite()
+ {
+ if (isFat()) {
+ fat()->notifyWrite();
+ return;
+ }
+ if (!(m_data & IsWatchedFlag))
+ return;
+ m_data |= IsInvalidatedFlag;
+ }
+
+private:
+ static const uintptr_t IsThinFlag = 1;
+ static const uintptr_t IsInvalidatedFlag = 2;
+ static const uintptr_t IsWatchedFlag = 4;
+
+ bool isThin() const { return m_data & IsThinFlag; }
+ bool isFat() const { return !isThin(); };
+
+ WatchpointSet* fat()
+ {
+ ASSERT(isFat());
+ return bitwise_cast<WatchpointSet*>(m_data);
+ }
+
+ const WatchpointSet* fat() const
+ {
+ ASSERT(isFat());
+ return bitwise_cast<WatchpointSet*>(m_data);
+ }
+
+ WatchpointSet* inflate()
+ {
+ if (LIKELY(isFat()))
+ return fat();
+ return inflateSlow();
+ }
+
+ JS_EXPORT_PRIVATE WatchpointSet* inflateSlow();
+ JS_EXPORT_PRIVATE void freeFat();
+
+ uintptr_t m_data;
+};
+
+} // namespace JSC
+
+#endif // Watchpoint_h
+
diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
index fb05e48ff..8969a7f25 100644
--- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
+++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
@@ -148,6 +148,7 @@ void ResolveResult::checkValidity()
return;
case IndexedGlobal:
case ReadOnlyIndexedGlobal:
+ case WatchedIndexedGlobal:
case DynamicIndexedGlobal:
case DynamicReadOnlyIndexedGlobal:
ASSERT(m_index != missingSymbolMarker());
@@ -161,6 +162,11 @@ void ResolveResult::checkValidity()
}
#endif
+WriteBarrier<Unknown>* ResolveResult::registerPointer() const
+{
+ return &jsCast<JSGlobalObject*>(globalObject())->registerAt(index());
+}
+
static bool s_dumpsGeneratedCode = false;
void BytecodeGenerator::setDumpsGeneratedCode(bool dumpsGeneratedCode)
@@ -211,13 +217,19 @@ bool BytecodeGenerator::addVar(const Identifier& ident, bool isConstant, Registe
return true;
}
-int BytecodeGenerator::addGlobalVar(const Identifier& ident, bool isConstant)
+int BytecodeGenerator::addGlobalVar(
+ const Identifier& ident, ConstantMode constantMode, FunctionMode functionMode)
{
+ UNUSED_PARAM(functionMode);
int index = symbolTable().size();
- SymbolTableEntry newEntry(index, isConstant ? ReadOnly : 0);
+ SymbolTableEntry newEntry(index, (constantMode == IsConstant) ? ReadOnly : 0);
+ if (functionMode == IsFunctionToSpecialize)
+ newEntry.attemptToWatch();
SymbolTable::AddResult result = symbolTable().add(ident.impl(), newEntry);
- if (!result.isNewEntry)
+ if (!result.isNewEntry) {
+ result.iterator->second.notifyWrite();
index = result.iterator->second.getIndex();
+ }
return index;
}
@@ -280,21 +292,27 @@ BytecodeGenerator::BytecodeGenerator(ProgramNode* programNode, ScopeChainNode* s
size_t newGlobals = varStack.size() + functionStack.size();
if (!newGlobals)
return;
- globalObject->resizeRegisters(symbolTable->size() + newGlobals);
+ globalObject->addRegisters(newGlobals);
for (size_t i = 0; i < functionStack.size(); ++i) {
FunctionBodyNode* function = functionStack[i];
- globalObject->removeDirect(*m_globalData, function->ident()); // Newly declared functions overwrite existing properties.
-
+ bool propertyDidExist =
+ globalObject->removeDirect(*m_globalData, function->ident()); // Newly declared functions overwrite existing properties.
+
JSValue value = JSFunction::create(exec, makeFunction(exec, function), scopeChain);
- int index = addGlobalVar(function->ident(), false);
+ int index = addGlobalVar(
+ function->ident(), IsVariable,
+ !propertyDidExist ? IsFunctionToSpecialize : NotFunctionOrNotSpecializable);
globalObject->registerAt(index).set(*m_globalData, globalObject, value);
}
for (size_t i = 0; i < varStack.size(); ++i) {
if (globalObject->hasProperty(exec, *varStack[i].first))
continue;
- addGlobalVar(*varStack[i].first, varStack[i].second & DeclarationStacks::IsConstant);
+ addGlobalVar(
+ *varStack[i].first,
+ (varStack[i].second & DeclarationStacks::IsConstant) ? IsConstant : IsVariable,
+ NotFunctionOrNotSpecializable);
}
}
@@ -679,6 +697,14 @@ void BytecodeGenerator::retrieveLastUnaryOp(int& dstIndex, int& srcIndex)
srcIndex = instructions().at(size - 1).u.operand;
}
+void BytecodeGenerator::retrieveLastUnaryOp(WriteBarrier<Unknown>*& dstPointer, int& srcIndex)
+{
+ ASSERT(instructions().size() >= 3);
+ size_t size = instructions().size();
+ dstPointer = instructions().at(size - 2).u.registerPointer;
+ srcIndex = instructions().at(size - 1).u.operand;
+}
+
void ALWAYS_INLINE BytecodeGenerator::rewindBinaryOp()
{
ASSERT(instructions().size() >= 4);
@@ -1170,6 +1196,7 @@ ResolveResult BytecodeGenerator::resolve(const Identifier& property)
ScopeChainIterator iter = m_scopeChain->begin();
ScopeChainIterator end = m_scopeChain->end();
size_t depth = 0;
+ size_t depthOfFirstScopeWithDynamicChecks = 0;
unsigned flags = 0;
for (; iter != end; ++iter, ++depth) {
JSObject* currentScope = iter->get();
@@ -1177,7 +1204,7 @@ ResolveResult BytecodeGenerator::resolve(const Identifier& property)
flags |= ResolveResult::DynamicFlag;
break;
}
- JSVariableObject* currentVariableObject = jsCast<JSVariableObject*>(currentScope);
+ JSSymbolTableObject* currentVariableObject = jsCast<JSSymbolTableObject*>(currentScope);
SymbolTableEntry entry = currentVariableObject->symbolTable().get(property.impl());
// Found the property
@@ -1188,7 +1215,9 @@ ResolveResult BytecodeGenerator::resolve(const Identifier& property)
if (++iter == end) {
if (flags & ResolveResult::DynamicFlag)
return ResolveResult::dynamicIndexedGlobalResolve(entry.getIndex(), depth, currentScope, flags);
- return ResolveResult::indexedGlobalResolve(entry.getIndex(), currentScope, flags);
+ return ResolveResult::indexedGlobalResolve(
+ entry.getIndex(), currentScope,
+ flags | (entry.couldBeWatched() ? ResolveResult::WatchedFlag : 0));
}
#if !ASSERT_DISABLED
if (JSActivation* activation = jsDynamicCast<JSActivation*>(currentVariableObject))
@@ -1199,19 +1228,27 @@ ResolveResult BytecodeGenerator::resolve(const Identifier& property)
bool scopeRequiresDynamicChecks = false;
if (currentVariableObject->isDynamicScope(scopeRequiresDynamicChecks))
break;
- if (scopeRequiresDynamicChecks)
- flags |= ResolveResult::DynamicFlag;
+ if (!(flags & ResolveResult::DynamicFlag)) {
+ if (scopeRequiresDynamicChecks)
+ flags |= ResolveResult::DynamicFlag;
+ else
+ ++depthOfFirstScopeWithDynamicChecks;
+ }
}
// Can't locate the property but we're able to avoid a few lookups.
JSObject* scope = iter->get();
+ // Step over the function's activation, if it needs one. At this point we
+ // know there is no dynamic scope in the function itself, so this is safe to
+ // do.
depth += m_codeBlock->needsFullScopeChain();
+ depthOfFirstScopeWithDynamicChecks += m_codeBlock->needsFullScopeChain();
if (++iter == end) {
if ((flags & ResolveResult::DynamicFlag) && depth)
return ResolveResult::dynamicGlobalResolve(depth, scope);
return ResolveResult::globalResolve(scope);
}
- return ResolveResult::dynamicResolve(depth);
+ return ResolveResult::dynamicResolve(depthOfFirstScopeWithDynamicChecks);
}
ResolveResult BytecodeGenerator::resolveConstDecl(const Identifier& property)
@@ -1234,7 +1271,7 @@ ResolveResult BytecodeGenerator::resolveConstDecl(const Identifier& property)
JSObject* currentScope = iter->get();
if (!currentScope->isVariableObject())
continue;
- JSVariableObject* currentVariableObject = jsCast<JSVariableObject*>(currentScope);
+ JSSymbolTableObject* currentVariableObject = jsCast<JSSymbolTableObject*>(currentScope);
SymbolTableEntry entry = currentVariableObject->symbolTable().get(property.impl());
if (entry.isNull())
continue;
@@ -1274,7 +1311,7 @@ bool BytecodeGenerator::shouldAvoidResolveGlobal()
RegisterID* BytecodeGenerator::emitResolve(RegisterID* dst, const ResolveResult& resolveResult, const Identifier& property)
{
if (resolveResult.isStatic())
- return emitGetStaticVar(dst, resolveResult);
+ return emitGetStaticVar(dst, resolveResult, property);
if (resolveResult.isGlobal() && !shouldAvoidResolveGlobal()) {
#if ENABLE(JIT)
@@ -1357,7 +1394,7 @@ RegisterID* BytecodeGenerator::emitResolveWithBase(RegisterID* baseDst, Register
if (resolveResult.isStatic()) {
// Directly index the property lookup across multiple scopes.
- emitGetStaticVar(propDst, resolveResult);
+ emitGetStaticVar(propDst, resolveResult, property);
return baseDst;
}
@@ -1396,7 +1433,7 @@ RegisterID* BytecodeGenerator::emitResolveWithThis(RegisterID* baseDst, Register
{
if (resolveResult.isStatic()) {
emitLoad(baseDst, jsUndefined());
- emitGetStaticVar(propDst, resolveResult);
+ emitGetStaticVar(propDst, resolveResult, property);
return baseDst;
}
@@ -1414,7 +1451,7 @@ RegisterID* BytecodeGenerator::emitResolveWithThis(RegisterID* baseDst, Register
return emitResolve(propDst, resolveResult, property);
}
-RegisterID* BytecodeGenerator::emitGetStaticVar(RegisterID* dst, const ResolveResult& resolveResult)
+RegisterID* BytecodeGenerator::emitGetStaticVar(RegisterID* dst, const ResolveResult& resolveResult, const Identifier& identifier)
{
ValueProfile* profile = 0;
@@ -1437,16 +1474,27 @@ RegisterID* BytecodeGenerator::emitGetStaticVar(RegisterID* dst, const ResolveRe
case ResolveResult::IndexedGlobal:
case ResolveResult::ReadOnlyIndexedGlobal:
if (m_lastOpcodeID == op_put_global_var) {
- int dstIndex;
+ WriteBarrier<Unknown>* dstPointer;
int srcIndex;
- retrieveLastUnaryOp(dstIndex, srcIndex);
- if (dstIndex == resolveResult.index() && srcIndex == dst->index())
+ retrieveLastUnaryOp(dstPointer, srcIndex);
+ if (dstPointer == resolveResult.registerPointer() && srcIndex == dst->index())
return dst;
}
profile = emitProfiledOpcode(op_get_global_var);
instructions().append(dst->index());
- instructions().append(resolveResult.index());
+ instructions().append(resolveResult.registerPointer());
+ instructions().append(profile);
+ return dst;
+
+ case ResolveResult::WatchedIndexedGlobal:
+ // Skip the peephole for now. It's not clear that it's profitable given
+ // the DFG's capabilities, and the fact that if it's watchable then we
+ // don't expect to see any put_global_var's anyway.
+ profile = emitProfiledOpcode(op_get_global_var_watchable);
+ instructions().append(dst->index());
+ instructions().append(resolveResult.registerPointer());
+ instructions().append(addConstant(identifier)); // For the benefit of the DFG.
instructions().append(profile);
return dst;
@@ -1456,7 +1504,7 @@ RegisterID* BytecodeGenerator::emitGetStaticVar(RegisterID* dst, const ResolveRe
}
}
-RegisterID* BytecodeGenerator::emitPutStaticVar(const ResolveResult& resolveResult, RegisterID* value)
+RegisterID* BytecodeGenerator::emitPutStaticVar(const ResolveResult& resolveResult, const Identifier& identifier, RegisterID* value)
{
switch (resolveResult.type()) {
case ResolveResult::Register:
@@ -1474,8 +1522,16 @@ RegisterID* BytecodeGenerator::emitPutStaticVar(const ResolveResult& resolveResu
case ResolveResult::IndexedGlobal:
case ResolveResult::ReadOnlyIndexedGlobal:
emitOpcode(op_put_global_var);
- instructions().append(resolveResult.index());
+ instructions().append(resolveResult.registerPointer());
+ instructions().append(value->index());
+ return value;
+
+ case ResolveResult::WatchedIndexedGlobal:
+ emitOpcode(op_put_global_var_check);
+ instructions().append(resolveResult.registerPointer());
instructions().append(value->index());
+ instructions().append(jsCast<JSGlobalObject*>(resolveResult.globalObject())->symbolTable().get(identifier.impl()).addressOfIsWatched());
+ instructions().append(addConstant(identifier));
return value;
default:
diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
index a71bbb785..8b1d1d744 100644
--- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
+++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
@@ -111,7 +111,9 @@ namespace JSC {
// The resolved binding is immutable.
ReadOnlyFlag = 0x20,
// The base object is the global object.
- GlobalFlag = 0x40
+ GlobalFlag = 0x40,
+ // The property is being watched, so writes should be special.
+ WatchedFlag = 0x80
};
enum Type {
// The property is local, and stored in a register.
@@ -131,6 +133,8 @@ namespace JSC {
// 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 being watched.
+ WatchedIndexedGlobal = IndexedFlag | GlobalFlag | StaticFlag | WatchedFlag,
// Like IndexedGlobal, but the property is also read-only, like NaN,
// Infinity, or undefined.
ReadOnlyIndexedGlobal = IndexedFlag | ReadOnlyFlag | GlobalFlag | StaticFlag,
@@ -197,6 +201,7 @@ namespace JSC {
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; }
+ WriteBarrier<Unknown>* registerPointer() const;
bool isRegister() const { return m_type & RegisterFlag; }
bool isDynamic() const { return m_type & DynamicFlag; }
@@ -440,8 +445,8 @@ 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* emitGetStaticVar(RegisterID* dst, const ResolveResult&);
- RegisterID* emitPutStaticVar(const ResolveResult&, RegisterID* value);
+ RegisterID* emitGetStaticVar(RegisterID* dst, const ResolveResult&, const Identifier&);
+ RegisterID* emitPutStaticVar(const ResolveResult&, const Identifier&, RegisterID* value);
RegisterID* emitResolve(RegisterID* dst, const ResolveResult&, const Identifier& property);
RegisterID* emitResolveBase(RegisterID* dst, const ResolveResult&, const Identifier& property);
@@ -541,6 +546,7 @@ namespace JSC {
ValueProfile* emitProfiledOpcode(OpcodeID);
void retrieveLastBinaryOp(int& dstIndex, int& src1Index, int& src2Index);
void retrieveLastUnaryOp(int& dstIndex, int& srcIndex);
+ void retrieveLastUnaryOp(WriteBarrier<Unknown>*& dstPointer, int& srcIndex);
ALWAYS_INLINE void rewindBinaryOp();
ALWAYS_INLINE void rewindUnaryOp();
@@ -572,7 +578,9 @@ namespace JSC {
}
// Returns the index of the added var.
- int addGlobalVar(const Identifier&, bool isConstant);
+ enum ConstantMode { IsConstant, IsVariable };
+ enum FunctionMode { IsFunctionToSpecialize, NotFunctionOrNotSpecializable };
+ int addGlobalVar(const Identifier&, ConstantMode, FunctionMode);
void addParameter(const Identifier&, int parameterIndex);
@@ -608,10 +616,7 @@ namespace JSC {
void addLineInfo(unsigned lineNo)
{
-#if !ENABLE(OPCODE_SAMPLING)
- if (m_shouldEmitRichSourceInfo)
-#endif
- m_codeBlock->addLineInfo(instructions().size(), lineNo);
+ m_codeBlock->addLineInfo(instructions().size(), lineNo);
}
RegisterID* emitInitLazyRegister(RegisterID*);
diff --git a/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp b/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
index 4f113f776..d243e8ce0 100644
--- a/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
+++ b/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
@@ -430,7 +430,7 @@ RegisterID* FunctionCallResolveNode::emitBytecode(BytecodeGenerator& generator,
if (resolveResult.isStatic()) {
RefPtr<RegisterID> func = generator.newTemporary();
CallArguments callArguments(generator, m_args);
- generator.emitGetStaticVar(func.get(), resolveResult);
+ generator.emitGetStaticVar(func.get(), resolveResult, m_ident);
generator.emitLoad(callArguments.thisRegister(), jsUndefined());
return generator.emitCall(generator.finalDestinationOrIgnored(dst, func.get()), func.get(), callArguments, divot(), startOffset(), endOffset());
}
@@ -618,7 +618,7 @@ RegisterID* PostfixResolveNode::emitBytecode(BytecodeGenerator& generator, Regis
}
if (resolveResult.isStatic() && !resolveResult.isReadOnly()) {
- RefPtr<RegisterID> value = generator.emitGetStaticVar(generator.newTemporary(), resolveResult);
+ RefPtr<RegisterID> value = generator.emitGetStaticVar(generator.newTemporary(), resolveResult, m_ident);
RegisterID* oldValue;
if (dst == generator.ignoredResult()) {
oldValue = 0;
@@ -626,7 +626,7 @@ RegisterID* PostfixResolveNode::emitBytecode(BytecodeGenerator& generator, Regis
} else {
oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator);
}
- generator.emitPutStaticVar(resolveResult, value.get());
+ generator.emitPutStaticVar(resolveResult, m_ident, value.get());
return oldValue;
}
@@ -803,9 +803,9 @@ RegisterID* PrefixResolveNode::emitBytecode(BytecodeGenerator& generator, Regist
}
if (resolveResult.isStatic() && !resolveResult.isReadOnly()) {
- RefPtr<RegisterID> propDst = generator.emitGetStaticVar(generator.tempDestination(dst), resolveResult);
+ RefPtr<RegisterID> propDst = generator.emitGetStaticVar(generator.tempDestination(dst), resolveResult, m_ident);
emitPreIncOrDec(generator, propDst.get(), m_operator);
- generator.emitPutStaticVar(resolveResult, propDst.get());
+ generator.emitPutStaticVar(resolveResult, m_ident, propDst.get());
return generator.moveToDestinationIfNeeded(dst, propDst.get());
}
@@ -1226,9 +1226,9 @@ RegisterID* ReadModifyResolveNode::emitBytecode(BytecodeGenerator& generator, Re
}
if (resolveResult.isStatic() && !resolveResult.isReadOnly()) {
- RefPtr<RegisterID> src1 = generator.emitGetStaticVar(generator.tempDestination(dst), resolveResult);
+ RefPtr<RegisterID> src1 = generator.emitGetStaticVar(generator.tempDestination(dst), resolveResult, m_ident);
RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
- generator.emitPutStaticVar(resolveResult, result);
+ generator.emitPutStaticVar(resolveResult, m_ident, result);
return result;
}
@@ -1256,7 +1256,7 @@ RegisterID* AssignResolveNode::emitBytecode(BytecodeGenerator& generator, Regist
if (dst == generator.ignoredResult())
dst = 0;
RegisterID* value = generator.emitNode(dst, m_right);
- generator.emitPutStaticVar(resolveResult, value);
+ generator.emitPutStaticVar(resolveResult, m_ident, value);
return value;
}
@@ -1361,7 +1361,7 @@ RegisterID* ConstDeclNode::emitCodeSingle(BytecodeGenerator& generator)
RefPtr<RegisterID> value = m_init ? generator.emitNode(m_init) : generator.emitLoad(0, jsUndefined());
if (resolveResult.isStatic())
- return generator.emitPutStaticVar(resolveResult, value.get());
+ return generator.emitPutStaticVar(resolveResult, m_ident, value.get());
if (generator.codeType() != EvalCode)
return value.get();
diff --git a/Source/JavaScriptCore/debugger/Debugger.cpp b/Source/JavaScriptCore/debugger/Debugger.cpp
index ede8a9ba2..0a66d6f34 100644
--- a/Source/JavaScriptCore/debugger/Debugger.cpp
+++ b/Source/JavaScriptCore/debugger/Debugger.cpp
@@ -79,7 +79,7 @@ inline void Recompiler::operator()(JSCell* cell)
return;
ExecState* exec = function->scope()->globalObject->JSGlobalObject::globalExec();
- executable->discardCode();
+ executable->clearCodeIfNotCompiling();
if (m_debugger == function->scope()->globalObject->debugger())
m_sourceProviders.add(executable->source().provider(), exec);
}
diff --git a/Source/JavaScriptCore/dfg/DFGAbstractState.cpp b/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
index a0849acea..94e96853d 100644
--- a/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
+++ b/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
@@ -99,31 +99,31 @@ void AbstractState::initialize(Graph& graph)
continue;
}
- PredictedType prediction = node.variableAccessData()->prediction();
- if (isInt32Prediction(prediction))
- root->valuesAtHead.argument(i).set(PredictInt32);
- else if (isArrayPrediction(prediction))
- root->valuesAtHead.argument(i).set(PredictArray);
- else if (isBooleanPrediction(prediction))
- root->valuesAtHead.argument(i).set(PredictBoolean);
- else if (isInt8ArrayPrediction(prediction))
- root->valuesAtHead.argument(i).set(PredictInt8Array);
- else if (isInt16ArrayPrediction(prediction))
- root->valuesAtHead.argument(i).set(PredictInt16Array);
- else if (isInt32ArrayPrediction(prediction))
- 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))
- root->valuesAtHead.argument(i).set(PredictUint32Array);
- else if (isFloat32ArrayPrediction(prediction))
- root->valuesAtHead.argument(i).set(PredictFloat32Array);
- else if (isFloat64ArrayPrediction(prediction))
- root->valuesAtHead.argument(i).set(PredictFloat64Array);
+ SpeculatedType prediction = node.variableAccessData()->prediction();
+ if (isInt32Speculation(prediction))
+ root->valuesAtHead.argument(i).set(SpecInt32);
+ else if (isArraySpeculation(prediction))
+ root->valuesAtHead.argument(i).set(SpecArray);
+ else if (isBooleanSpeculation(prediction))
+ root->valuesAtHead.argument(i).set(SpecBoolean);
+ else if (isInt8ArraySpeculation(prediction))
+ root->valuesAtHead.argument(i).set(SpecInt8Array);
+ else if (isInt16ArraySpeculation(prediction))
+ root->valuesAtHead.argument(i).set(SpecInt16Array);
+ else if (isInt32ArraySpeculation(prediction))
+ root->valuesAtHead.argument(i).set(SpecInt32Array);
+ else if (isUint8ArraySpeculation(prediction))
+ root->valuesAtHead.argument(i).set(SpecUint8Array);
+ else if (isUint8ClampedArraySpeculation(prediction))
+ root->valuesAtHead.argument(i).set(SpecUint8ClampedArray);
+ else if (isUint16ArraySpeculation(prediction))
+ root->valuesAtHead.argument(i).set(SpecUint16Array);
+ else if (isUint32ArraySpeculation(prediction))
+ root->valuesAtHead.argument(i).set(SpecUint32Array);
+ else if (isFloat32ArraySpeculation(prediction))
+ root->valuesAtHead.argument(i).set(SpecFloat32Array);
+ else if (isFloat64ArraySpeculation(prediction))
+ root->valuesAtHead.argument(i).set(SpecFloat64Array);
else
root->valuesAtHead.argument(i).makeTop();
@@ -219,7 +219,9 @@ bool AbstractState::execute(unsigned indexInBlock)
{
ASSERT(m_block);
ASSERT(m_isValid);
-
+
+ m_didClobber = false;
+
NodeIndex nodeIndex = m_block->at(indexInBlock);
Node& node = m_graph[nodeIndex];
@@ -237,24 +239,29 @@ bool AbstractState::execute(unsigned indexInBlock)
case GetLocal: {
VariableAccessData* variableAccessData = node.variableAccessData();
+ if (variableAccessData->prediction() == SpecNone) {
+ m_isValid = false;
+ node.setCanExit(true);
+ break;
+ }
bool canExit = false;
- canExit |= variableAccessData->prediction() == PredictNone;
- if (variableAccessData->isCaptured())
- forNode(nodeIndex) = m_variables.operand(variableAccessData->local());
- else {
- AbstractValue value = m_variables.operand(variableAccessData->local());
+ AbstractValue value = m_variables.operand(variableAccessData->local());
+ if (!variableAccessData->isCaptured()) {
if (value.isClear())
canExit |= true;
- if (value.value())
- m_foundConstants = true;
- forNode(nodeIndex) = value;
}
+ if (value.value())
+ m_foundConstants = true;
+ forNode(nodeIndex) = value;
node.setCanExit(canExit);
break;
}
case GetLocalUnlinked: {
- forNode(nodeIndex) = m_variables.operand(node.unlinkedLocal());
+ AbstractValue value = m_variables.operand(node.unlinkedLocal());
+ if (value.value())
+ m_foundConstants = true;
+ forNode(nodeIndex) = value;
node.setCanExit(false);
break;
}
@@ -268,17 +275,17 @@ bool AbstractState::execute(unsigned indexInBlock)
if (node.variableAccessData()->shouldUseDoubleFormat()) {
speculateNumberUnary(node);
- m_variables.operand(node.local()).set(PredictDouble);
+ m_variables.operand(node.local()).set(SpecDouble);
break;
}
- PredictedType predictedType = node.variableAccessData()->argumentAwarePrediction();
- if (isInt32Prediction(predictedType))
+ SpeculatedType predictedType = node.variableAccessData()->argumentAwarePrediction();
+ if (isInt32Speculation(predictedType))
speculateInt32Unary(node);
- else if (isArrayPrediction(predictedType)) {
- node.setCanExit(!isArrayPrediction(forNode(node.child1()).m_type));
- forNode(node.child1()).filter(PredictArray);
- } else if (isBooleanPrediction(predictedType))
+ else if (isArraySpeculation(predictedType)) {
+ node.setCanExit(!isArraySpeculation(forNode(node.child1()).m_type));
+ forNode(node.child1()).filter(SpecArray);
+ } else if (isBooleanSpeculation(predictedType))
speculateBooleanUnary(node);
else
node.setCanExit(false);
@@ -331,7 +338,7 @@ bool AbstractState::execute(unsigned indexInBlock)
break;
}
speculateInt32Binary(node);
- forNode(nodeIndex).set(PredictInt32);
+ forNode(nodeIndex).set(SpecInt32);
break;
}
@@ -345,10 +352,10 @@ bool AbstractState::execute(unsigned indexInBlock)
break;
}
if (!node.canSpeculateInteger()) {
- forNode(nodeIndex).set(PredictDouble);
+ forNode(nodeIndex).set(SpecDouble);
node.setCanExit(false);
} else {
- forNode(nodeIndex).set(PredictInt32);
+ forNode(nodeIndex).set(SpecInt32);
node.setCanExit(true);
}
break;
@@ -367,8 +374,8 @@ bool AbstractState::execute(unsigned indexInBlock)
}
}
node.setCanExit(true);
- forNode(node.child1()).filter(PredictNumber);
- forNode(nodeIndex).set(PredictInt32);
+ forNode(node.child1()).filter(SpecNumber);
+ forNode(nodeIndex).set(SpecInt32);
break;
}
@@ -392,7 +399,7 @@ bool AbstractState::execute(unsigned indexInBlock)
else
node.setCanExit(false);
- forNode(nodeIndex).set(PredictInt32);
+ forNode(nodeIndex).set(SpecInt32);
break;
}
@@ -405,12 +412,12 @@ bool AbstractState::execute(unsigned indexInBlock)
break;
}
speculateNumberUnary(node);
- forNode(nodeIndex).set(PredictDouble);
+ forNode(nodeIndex).set(SpecDouble);
break;
}
case CheckNumber:
- forNode(node.child1()).filter(PredictNumber);
+ forNode(node.child1()).filter(SpecNumber);
break;
case ValueAdd:
@@ -426,17 +433,17 @@ bool AbstractState::execute(unsigned indexInBlock)
if (m_graph.addShouldSpeculateInteger(node)) {
speculateInt32Binary(
node, !nodeCanTruncateInteger(node.arithNodeFlags()));
- forNode(nodeIndex).set(PredictInt32);
+ forNode(nodeIndex).set(SpecInt32);
break;
}
if (Node::shouldSpeculateNumber(m_graph[node.child1()], m_graph[node.child2()])) {
speculateNumberBinary(node);
- forNode(nodeIndex).set(PredictDouble);
+ forNode(nodeIndex).set(SpecDouble);
break;
}
if (node.op() == ValueAdd) {
clobberWorld(node.codeOrigin, indexInBlock);
- forNode(nodeIndex).set(PredictString | PredictInt32 | PredictNumber);
+ forNode(nodeIndex).set(SpecString | SpecInt32 | SpecNumber);
node.setCanExit(false);
break;
}
@@ -458,11 +465,11 @@ bool AbstractState::execute(unsigned indexInBlock)
if (m_graph.addShouldSpeculateInteger(node)) {
speculateInt32Binary(
node, !nodeCanTruncateInteger(node.arithNodeFlags()));
- forNode(nodeIndex).set(PredictInt32);
+ forNode(nodeIndex).set(SpecInt32);
break;
}
speculateNumberBinary(node);
- forNode(nodeIndex).set(PredictDouble);
+ forNode(nodeIndex).set(SpecDouble);
break;
}
@@ -477,11 +484,11 @@ bool AbstractState::execute(unsigned indexInBlock)
if (m_graph.negateShouldSpeculateInteger(node)) {
speculateInt32Unary(
node, !nodeCanTruncateInteger(node.arithNodeFlags()));
- forNode(nodeIndex).set(PredictInt32);
+ forNode(nodeIndex).set(SpecInt32);
break;
}
speculateNumberUnary(node);
- forNode(nodeIndex).set(PredictDouble);
+ forNode(nodeIndex).set(SpecDouble);
break;
}
@@ -499,11 +506,11 @@ bool AbstractState::execute(unsigned indexInBlock)
node,
!nodeCanTruncateInteger(node.arithNodeFlags())
|| !nodeCanIgnoreNegativeZero(node.arithNodeFlags()));
- forNode(nodeIndex).set(PredictInt32);
+ forNode(nodeIndex).set(SpecInt32);
break;
}
speculateNumberBinary(node);
- forNode(nodeIndex).set(PredictDouble);
+ forNode(nodeIndex).set(SpecDouble);
break;
}
@@ -541,11 +548,11 @@ bool AbstractState::execute(unsigned indexInBlock)
m_graph[node.child1()], m_graph[node.child2()])
&& node.canSpeculateInteger()) {
speculateInt32Binary(node, true); // forcing can-exit, which is a bit on the conservative side.
- forNode(nodeIndex).set(PredictInt32);
+ forNode(nodeIndex).set(SpecInt32);
break;
}
speculateNumberBinary(node);
- forNode(nodeIndex).set(PredictDouble);
+ forNode(nodeIndex).set(SpecDouble);
break;
}
@@ -560,11 +567,11 @@ bool AbstractState::execute(unsigned indexInBlock)
if (m_graph[node.child1()].shouldSpeculateInteger()
&& node.canSpeculateInteger()) {
speculateInt32Unary(node, true);
- forNode(nodeIndex).set(PredictInt32);
+ forNode(nodeIndex).set(SpecInt32);
break;
}
speculateNumberUnary(node);
- forNode(nodeIndex).set(PredictDouble);
+ forNode(nodeIndex).set(SpecDouble);
break;
}
@@ -577,7 +584,7 @@ bool AbstractState::execute(unsigned indexInBlock)
break;
}
speculateNumberUnary(node);
- forNode(nodeIndex).set(PredictDouble);
+ forNode(nodeIndex).set(SpecDouble);
break;
}
@@ -585,27 +592,28 @@ bool AbstractState::execute(unsigned indexInBlock)
JSValue childConst = forNode(node.child1()).value();
if (childConst) {
forNode(nodeIndex).set(jsBoolean(!childConst.toBoolean()));
+ m_foundConstants = true;
node.setCanExit(false);
break;
}
Node& child = m_graph[node.child1()];
- if (isBooleanPrediction(child.prediction()))
+ if (isBooleanSpeculation(child.prediction()))
speculateBooleanUnary(node);
else if (child.shouldSpeculateFinalObjectOrOther()) {
node.setCanExit(
- !isFinalObjectOrOtherPrediction(forNode(node.child1()).m_type));
- forNode(node.child1()).filter(PredictFinalObject | PredictOther);
+ !isFinalObjectOrOtherSpeculation(forNode(node.child1()).m_type));
+ forNode(node.child1()).filter(SpecFinalObject | SpecOther);
} else if (child.shouldSpeculateArrayOrOther()) {
node.setCanExit(
- !isArrayOrOtherPrediction(forNode(node.child1()).m_type));
- forNode(node.child1()).filter(PredictArray | PredictOther);
+ !isArrayOrOtherSpeculation(forNode(node.child1()).m_type));
+ forNode(node.child1()).filter(SpecArray | SpecOther);
} else if (child.shouldSpeculateInteger())
speculateInt32Unary(node);
else if (child.shouldSpeculateNumber())
speculateNumberUnary(node);
else
node.setCanExit(false);
- forNode(nodeIndex).set(PredictBoolean);
+ forNode(nodeIndex).set(SpecBoolean);
break;
}
@@ -643,7 +651,7 @@ bool AbstractState::execute(unsigned indexInBlock)
break;
}
}
- forNode(nodeIndex).set(PredictBoolean);
+ forNode(nodeIndex).set(SpecBoolean);
break;
}
@@ -682,18 +690,18 @@ bool AbstractState::execute(unsigned indexInBlock)
break;
}
- forNode(nodeIndex).set(PredictBoolean);
+ forNode(nodeIndex).set(SpecBoolean);
Node& left = m_graph[node.child1()];
Node& right = m_graph[node.child2()];
- PredictedType filter;
- PredictionChecker checker;
+ SpeculatedType filter;
+ SpeculatedTypeChecker checker;
if (Node::shouldSpeculateInteger(left, right)) {
- filter = PredictInt32;
- checker = isInt32Prediction;
+ filter = SpecInt32;
+ checker = isInt32Speculation;
} else if (Node::shouldSpeculateNumber(left, right)) {
- filter = PredictNumber;
- checker = isNumberPrediction;
+ filter = SpecNumber;
+ checker = isNumberSpeculation;
} else if (node.op() == CompareEq) {
if ((m_graph.isConstant(node.child1().index())
&& m_graph.valueOfJSConstant(node.child1().index()).isNull())
@@ -705,47 +713,47 @@ bool AbstractState::execute(unsigned indexInBlock)
}
if (Node::shouldSpeculateFinalObject(left, right)) {
- filter = PredictFinalObject;
- checker = isFinalObjectPrediction;
+ filter = SpecFinalObject;
+ checker = isFinalObjectSpeculation;
} else if (Node::shouldSpeculateArray(left, right)) {
- filter = PredictArray;
- checker = isArrayPrediction;
+ filter = SpecArray;
+ checker = isArraySpeculation;
} else if (left.shouldSpeculateFinalObject() && right.shouldSpeculateFinalObjectOrOther()) {
node.setCanExit(
- !isFinalObjectPrediction(forNode(node.child1()).m_type)
- || !isFinalObjectOrOtherPrediction(forNode(node.child2()).m_type));
- forNode(node.child1()).filter(PredictFinalObject);
- forNode(node.child2()).filter(PredictFinalObject | PredictOther);
+ !isFinalObjectSpeculation(forNode(node.child1()).m_type)
+ || !isFinalObjectOrOtherSpeculation(forNode(node.child2()).m_type));
+ forNode(node.child1()).filter(SpecFinalObject);
+ forNode(node.child2()).filter(SpecFinalObject | SpecOther);
break;
} else if (right.shouldSpeculateFinalObject() && left.shouldSpeculateFinalObjectOrOther()) {
node.setCanExit(
- !isFinalObjectOrOtherPrediction(forNode(node.child1()).m_type)
- || !isFinalObjectPrediction(forNode(node.child2()).m_type));
- forNode(node.child1()).filter(PredictFinalObject | PredictOther);
- forNode(node.child2()).filter(PredictFinalObject);
+ !isFinalObjectOrOtherSpeculation(forNode(node.child1()).m_type)
+ || !isFinalObjectSpeculation(forNode(node.child2()).m_type));
+ forNode(node.child1()).filter(SpecFinalObject | SpecOther);
+ forNode(node.child2()).filter(SpecFinalObject);
break;
} else if (left.shouldSpeculateArray() && right.shouldSpeculateArrayOrOther()) {
node.setCanExit(
- !isArrayPrediction(forNode(node.child1()).m_type)
- || !isArrayOrOtherPrediction(forNode(node.child2()).m_type));
- forNode(node.child1()).filter(PredictArray);
- forNode(node.child2()).filter(PredictArray | PredictOther);
+ !isArraySpeculation(forNode(node.child1()).m_type)
+ || !isArrayOrOtherSpeculation(forNode(node.child2()).m_type));
+ forNode(node.child1()).filter(SpecArray);
+ forNode(node.child2()).filter(SpecArray | SpecOther);
break;
} else if (right.shouldSpeculateArray() && left.shouldSpeculateArrayOrOther()) {
node.setCanExit(
- !isArrayOrOtherPrediction(forNode(node.child1()).m_type)
- || !isArrayPrediction(forNode(node.child2()).m_type));
- forNode(node.child1()).filter(PredictArray | PredictOther);
- forNode(node.child2()).filter(PredictArray);
+ !isArrayOrOtherSpeculation(forNode(node.child1()).m_type)
+ || !isArraySpeculation(forNode(node.child2()).m_type));
+ forNode(node.child1()).filter(SpecArray | SpecOther);
+ forNode(node.child2()).filter(SpecArray);
break;
} else {
- filter = PredictTop;
- checker = isAnyPrediction;
+ filter = SpecTop;
+ checker = isAnySpeculation;
clobberWorld(node.codeOrigin, indexInBlock);
}
} else {
- filter = PredictTop;
- checker = isAnyPrediction;
+ filter = SpecTop;
+ checker = isAnySpeculation;
clobberWorld(node.codeOrigin, indexInBlock);
}
node.setCanExit(
@@ -765,7 +773,7 @@ bool AbstractState::execute(unsigned indexInBlock)
node.setCanExit(false);
break;
}
- forNode(nodeIndex).set(PredictBoolean);
+ forNode(nodeIndex).set(SpecBoolean);
if (m_graph.isJSConstant(node.child1().index())) {
JSValue value = m_graph.valueOfJSConstant(node.child1().index());
if (!value.isNumber() && !value.isString()) {
@@ -793,19 +801,19 @@ bool AbstractState::execute(unsigned indexInBlock)
if (Node::shouldSpeculateFinalObject(
m_graph[node.child1()], m_graph[node.child2()])) {
node.setCanExit(
- !isFinalObjectPrediction(forNode(node.child1()).m_type)
- || !isFinalObjectPrediction(forNode(node.child2()).m_type));
- forNode(node.child1()).filter(PredictFinalObject);
- forNode(node.child2()).filter(PredictFinalObject);
+ !isFinalObjectSpeculation(forNode(node.child1()).m_type)
+ || !isFinalObjectSpeculation(forNode(node.child2()).m_type));
+ forNode(node.child1()).filter(SpecFinalObject);
+ forNode(node.child2()).filter(SpecFinalObject);
break;
}
if (Node::shouldSpeculateArray(
m_graph[node.child1()], m_graph[node.child2()])) {
node.setCanExit(
- !isArrayPrediction(forNode(node.child1()).m_type)
- || !isArrayPrediction(forNode(node.child2()).m_type));
- forNode(node.child1()).filter(PredictArray);
- forNode(node.child2()).filter(PredictArray);
+ !isArraySpeculation(forNode(node.child1()).m_type)
+ || !isArraySpeculation(forNode(node.child2()).m_type));
+ forNode(node.child1()).filter(SpecArray);
+ forNode(node.child2()).filter(SpecArray);
break;
}
node.setCanExit(false);
@@ -814,16 +822,16 @@ bool AbstractState::execute(unsigned indexInBlock)
case StringCharCodeAt:
node.setCanExit(true);
- forNode(node.child1()).filter(PredictString);
- forNode(node.child2()).filter(PredictInt32);
- forNode(nodeIndex).set(PredictInt32);
+ forNode(node.child1()).filter(SpecString);
+ forNode(node.child2()).filter(SpecInt32);
+ forNode(nodeIndex).set(SpecInt32);
break;
case StringCharAt:
node.setCanExit(true);
- forNode(node.child1()).filter(PredictString);
- forNode(node.child2()).filter(PredictInt32);
- forNode(nodeIndex).set(PredictString);
+ forNode(node.child1()).filter(SpecString);
+ forNode(node.child2()).filter(SpecInt32);
+ forNode(nodeIndex).set(SpecString);
break;
case GetByVal: {
@@ -832,84 +840,84 @@ bool AbstractState::execute(unsigned indexInBlock)
m_isValid = false;
break;
}
- if (!isActionableArrayPrediction(m_graph[node.child1()].prediction()) || !m_graph[node.child2()].shouldSpeculateInteger()) {
+ if (!isActionableArraySpeculation(m_graph[node.child1()].prediction()) || !m_graph[node.child2()].shouldSpeculateInteger()) {
clobberWorld(node.codeOrigin, indexInBlock);
forNode(nodeIndex).makeTop();
break;
}
if (m_graph[node.child1()].shouldSpeculateArguments()) {
- forNode(node.child1()).filter(PredictArguments);
- forNode(node.child2()).filter(PredictInt32);
+ forNode(node.child1()).filter(SpecArguments);
+ forNode(node.child2()).filter(SpecInt32);
forNode(nodeIndex).makeTop();
break;
}
- if (m_graph[node.child1()].prediction() == PredictString) {
- forNode(node.child1()).filter(PredictString);
- forNode(node.child2()).filter(PredictInt32);
- forNode(nodeIndex).set(PredictString);
+ if (m_graph[node.child1()].prediction() == SpecString) {
+ forNode(node.child1()).filter(SpecString);
+ forNode(node.child2()).filter(SpecInt32);
+ forNode(nodeIndex).set(SpecString);
break;
}
if (m_graph[node.child1()].shouldSpeculateInt8Array()) {
- forNode(node.child1()).filter(PredictInt8Array);
- forNode(node.child2()).filter(PredictInt32);
- forNode(nodeIndex).set(PredictInt32);
+ forNode(node.child1()).filter(SpecInt8Array);
+ forNode(node.child2()).filter(SpecInt32);
+ forNode(nodeIndex).set(SpecInt32);
break;
}
if (m_graph[node.child1()].shouldSpeculateInt16Array()) {
- forNode(node.child1()).filter(PredictInt16Array);
- forNode(node.child2()).filter(PredictInt32);
- forNode(nodeIndex).set(PredictInt32);
+ forNode(node.child1()).filter(SpecInt16Array);
+ forNode(node.child2()).filter(SpecInt32);
+ forNode(nodeIndex).set(SpecInt32);
break;
}
if (m_graph[node.child1()].shouldSpeculateInt32Array()) {
- forNode(node.child1()).filter(PredictInt32Array);
- forNode(node.child2()).filter(PredictInt32);
- forNode(nodeIndex).set(PredictInt32);
+ forNode(node.child1()).filter(SpecInt32Array);
+ forNode(node.child2()).filter(SpecInt32);
+ forNode(nodeIndex).set(SpecInt32);
break;
}
if (m_graph[node.child1()].shouldSpeculateUint8Array()) {
- forNode(node.child1()).filter(PredictUint8Array);
- forNode(node.child2()).filter(PredictInt32);
- forNode(nodeIndex).set(PredictInt32);
+ forNode(node.child1()).filter(SpecUint8Array);
+ forNode(node.child2()).filter(SpecInt32);
+ forNode(nodeIndex).set(SpecInt32);
break;
}
if (m_graph[node.child1()].shouldSpeculateUint8ClampedArray()) {
- forNode(node.child1()).filter(PredictUint8ClampedArray);
- forNode(node.child2()).filter(PredictInt32);
- forNode(nodeIndex).set(PredictInt32);
+ forNode(node.child1()).filter(SpecUint8ClampedArray);
+ forNode(node.child2()).filter(SpecInt32);
+ forNode(nodeIndex).set(SpecInt32);
break;
}
if (m_graph[node.child1()].shouldSpeculateUint16Array()) {
- forNode(node.child1()).filter(PredictUint16Array);
- forNode(node.child2()).filter(PredictInt32);
- forNode(nodeIndex).set(PredictInt32);
+ forNode(node.child1()).filter(SpecUint16Array);
+ forNode(node.child2()).filter(SpecInt32);
+ forNode(nodeIndex).set(SpecInt32);
break;
}
if (m_graph[node.child1()].shouldSpeculateUint32Array()) {
- forNode(node.child1()).filter(PredictUint32Array);
- forNode(node.child2()).filter(PredictInt32);
+ forNode(node.child1()).filter(SpecUint32Array);
+ forNode(node.child2()).filter(SpecInt32);
if (node.shouldSpeculateInteger())
- forNode(nodeIndex).set(PredictInt32);
+ forNode(nodeIndex).set(SpecInt32);
else
- forNode(nodeIndex).set(PredictDouble);
+ forNode(nodeIndex).set(SpecDouble);
break;
}
if (m_graph[node.child1()].shouldSpeculateFloat32Array()) {
- forNode(node.child1()).filter(PredictFloat32Array);
- forNode(node.child2()).filter(PredictInt32);
- forNode(nodeIndex).set(PredictDouble);
+ forNode(node.child1()).filter(SpecFloat32Array);
+ forNode(node.child2()).filter(SpecInt32);
+ forNode(nodeIndex).set(SpecDouble);
break;
}
if (m_graph[node.child1()].shouldSpeculateFloat64Array()) {
- forNode(node.child1()).filter(PredictFloat64Array);
- forNode(node.child2()).filter(PredictInt32);
- forNode(nodeIndex).set(PredictDouble);
+ forNode(node.child1()).filter(SpecFloat64Array);
+ forNode(node.child2()).filter(SpecInt32);
+ forNode(nodeIndex).set(SpecDouble);
break;
}
ASSERT(m_graph[node.child1()].shouldSpeculateArray());
- forNode(node.child1()).filter(PredictArray);
- forNode(node.child2()).filter(PredictInt32);
+ forNode(node.child1()).filter(SpecArray);
+ forNode(node.child2()).filter(SpecInt32);
forNode(nodeIndex).makeTop();
break;
}
@@ -921,7 +929,7 @@ bool AbstractState::execute(unsigned indexInBlock)
m_isValid = false;
break;
}
- if (!m_graph[node.child2()].shouldSpeculateInteger() || !isActionableMutableArrayPrediction(m_graph[node.child1()].prediction())
+ if (!m_graph[node.child2()].shouldSpeculateInteger() || !isActionableMutableArraySpeculation(m_graph[node.child1()].prediction())
#if USE(JSVALUE32_64)
|| m_graph[node.child1()].shouldSpeculateArguments()
#endif
@@ -933,110 +941,112 @@ bool AbstractState::execute(unsigned indexInBlock)
}
if (m_graph[node.child1()].shouldSpeculateArguments()) {
- forNode(node.child1()).filter(PredictArguments);
- forNode(node.child2()).filter(PredictInt32);
+ forNode(node.child1()).filter(SpecArguments);
+ forNode(node.child2()).filter(SpecInt32);
break;
}
if (m_graph[node.child1()].shouldSpeculateInt8Array()) {
- forNode(node.child1()).filter(PredictInt8Array);
- forNode(node.child2()).filter(PredictInt32);
+ forNode(node.child1()).filter(SpecInt8Array);
+ forNode(node.child2()).filter(SpecInt32);
if (m_graph[node.child3()].shouldSpeculateInteger())
- forNode(node.child3()).filter(PredictInt32);
+ forNode(node.child3()).filter(SpecInt32);
else
- forNode(node.child3()).filter(PredictNumber);
+ forNode(node.child3()).filter(SpecNumber);
break;
}
if (m_graph[node.child1()].shouldSpeculateInt16Array()) {
- forNode(node.child1()).filter(PredictInt16Array);
- forNode(node.child2()).filter(PredictInt32);
+ forNode(node.child1()).filter(SpecInt16Array);
+ forNode(node.child2()).filter(SpecInt32);
if (m_graph[node.child3()].shouldSpeculateInteger())
- forNode(node.child3()).filter(PredictInt32);
+ forNode(node.child3()).filter(SpecInt32);
else
- forNode(node.child3()).filter(PredictNumber);
+ forNode(node.child3()).filter(SpecNumber);
break;
}
if (m_graph[node.child1()].shouldSpeculateInt32Array()) {
- forNode(node.child1()).filter(PredictInt32Array);
- forNode(node.child2()).filter(PredictInt32);
+ forNode(node.child1()).filter(SpecInt32Array);
+ forNode(node.child2()).filter(SpecInt32);
if (m_graph[node.child3()].shouldSpeculateInteger())
- forNode(node.child3()).filter(PredictInt32);
+ forNode(node.child3()).filter(SpecInt32);
else
- forNode(node.child3()).filter(PredictNumber);
+ forNode(node.child3()).filter(SpecNumber);
break;
}
if (m_graph[node.child1()].shouldSpeculateUint8Array()) {
- forNode(node.child1()).filter(PredictUint8Array);
- forNode(node.child2()).filter(PredictInt32);
+ forNode(node.child1()).filter(SpecUint8Array);
+ forNode(node.child2()).filter(SpecInt32);
if (m_graph[node.child3()].shouldSpeculateInteger())
- forNode(node.child3()).filter(PredictInt32);
+ forNode(node.child3()).filter(SpecInt32);
else
- forNode(node.child3()).filter(PredictNumber);
+ forNode(node.child3()).filter(SpecNumber);
break;
}
if (m_graph[node.child1()].shouldSpeculateUint8ClampedArray()) {
- forNode(node.child1()).filter(PredictUint8ClampedArray);
- forNode(node.child2()).filter(PredictInt32);
+ forNode(node.child1()).filter(SpecUint8ClampedArray);
+ forNode(node.child2()).filter(SpecInt32);
if (m_graph[node.child3()].shouldSpeculateInteger())
- forNode(node.child3()).filter(PredictInt32);
+ forNode(node.child3()).filter(SpecInt32);
else
- forNode(node.child3()).filter(PredictNumber);
+ forNode(node.child3()).filter(SpecNumber);
break;
}
if (m_graph[node.child1()].shouldSpeculateUint16Array()) {
- forNode(node.child1()).filter(PredictUint16Array);
- forNode(node.child2()).filter(PredictInt32);
+ forNode(node.child1()).filter(SpecUint16Array);
+ forNode(node.child2()).filter(SpecInt32);
if (m_graph[node.child3()].shouldSpeculateInteger())
- forNode(node.child3()).filter(PredictInt32);
+ forNode(node.child3()).filter(SpecInt32);
else
- forNode(node.child3()).filter(PredictNumber);
+ forNode(node.child3()).filter(SpecNumber);
break;
}
if (m_graph[node.child1()].shouldSpeculateUint32Array()) {
- forNode(node.child1()).filter(PredictUint32Array);
- forNode(node.child2()).filter(PredictInt32);
+ forNode(node.child1()).filter(SpecUint32Array);
+ forNode(node.child2()).filter(SpecInt32);
if (m_graph[node.child3()].shouldSpeculateInteger())
- forNode(node.child3()).filter(PredictInt32);
+ forNode(node.child3()).filter(SpecInt32);
else
- forNode(node.child3()).filter(PredictNumber);
+ forNode(node.child3()).filter(SpecNumber);
break;
}
if (m_graph[node.child1()].shouldSpeculateFloat32Array()) {
- forNode(node.child1()).filter(PredictFloat32Array);
- forNode(node.child2()).filter(PredictInt32);
- forNode(node.child3()).filter(PredictNumber);
+ forNode(node.child1()).filter(SpecFloat32Array);
+ forNode(node.child2()).filter(SpecInt32);
+ forNode(node.child3()).filter(SpecNumber);
break;
}
if (m_graph[node.child1()].shouldSpeculateFloat64Array()) {
- forNode(node.child1()).filter(PredictFloat64Array);
- forNode(node.child2()).filter(PredictInt32);
- forNode(node.child3()).filter(PredictNumber);
+ forNode(node.child1()).filter(SpecFloat64Array);
+ forNode(node.child2()).filter(SpecInt32);
+ forNode(node.child3()).filter(SpecNumber);
break;
}
ASSERT(m_graph[node.child1()].shouldSpeculateArray());
- forNode(node.child1()).filter(PredictArray);
- forNode(node.child2()).filter(PredictInt32);
+ forNode(node.child1()).filter(SpecArray);
+ forNode(node.child2()).filter(SpecInt32);
+ if (node.op() == PutByVal)
+ clobberWorld(node.codeOrigin, indexInBlock);
break;
}
case ArrayPush:
node.setCanExit(true);
- forNode(node.child1()).filter(PredictArray);
- forNode(nodeIndex).set(PredictNumber);
+ forNode(node.child1()).filter(SpecArray);
+ forNode(nodeIndex).set(SpecNumber);
break;
case ArrayPop:
node.setCanExit(true);
- forNode(node.child1()).filter(PredictArray);
+ forNode(node.child1()).filter(SpecArray);
forNode(nodeIndex).makeTop();
break;
case RegExpExec:
case RegExpTest:
node.setCanExit(
- !isCellPrediction(forNode(node.child1()).m_type)
- || !isCellPrediction(forNode(node.child2()).m_type));
- forNode(node.child1()).filter(PredictCell);
- forNode(node.child2()).filter(PredictCell);
+ !isCellSpeculation(forNode(node.child1()).m_type)
+ || !isCellSpeculation(forNode(node.child2()).m_type));
+ forNode(node.child1()).filter(SpecCell);
+ forNode(node.child2()).filter(SpecCell);
forNode(nodeIndex).makeTop();
break;
@@ -1067,12 +1077,12 @@ bool AbstractState::execute(unsigned indexInBlock)
speculateBooleanUnary(node);
else if (child.shouldSpeculateFinalObjectOrOther()) {
node.setCanExit(
- !isFinalObjectOrOtherPrediction(forNode(node.child1()).m_type));
- forNode(node.child1()).filter(PredictFinalObject | PredictOther);
+ !isFinalObjectOrOtherSpeculation(forNode(node.child1()).m_type));
+ forNode(node.child1()).filter(SpecFinalObject | SpecOther);
} else if (child.shouldSpeculateArrayOrOther()) {
node.setCanExit(
- !isArrayOrOtherPrediction(forNode(node.child1()).m_type));
- forNode(node.child1()).filter(PredictArray | PredictOther);
+ !isArrayOrOtherSpeculation(forNode(node.child1()).m_type));
+ forNode(node.child1()).filter(SpecArray | SpecOther);
} else if (child.shouldSpeculateInteger())
speculateInt32Unary(node);
else if (child.shouldSpeculateNumber())
@@ -1106,17 +1116,17 @@ bool AbstractState::execute(unsigned indexInBlock)
Node& child = m_graph[node.child1()];
if (child.shouldSpeculateInteger()) {
speculateInt32Unary(node);
- forNode(nodeIndex).set(PredictInt32);
+ forNode(nodeIndex).set(SpecInt32);
break;
}
AbstractValue& source = forNode(node.child1());
AbstractValue& destination = forNode(nodeIndex);
- PredictedType type = source.m_type;
- if (type & ~(PredictNumber | PredictString | PredictBoolean)) {
- type &= (PredictNumber | PredictString | PredictBoolean);
- type |= PredictString;
+ SpeculatedType type = source.m_type;
+ if (type & ~(SpecNumber | SpecString | SpecBoolean)) {
+ type &= (SpecNumber | SpecString | SpecBoolean);
+ type |= SpecString;
}
destination.set(type);
node.setCanExit(false);
@@ -1125,7 +1135,7 @@ bool AbstractState::execute(unsigned indexInBlock)
case StrCat:
node.setCanExit(false);
- forNode(nodeIndex).set(PredictString);
+ forNode(nodeIndex).set(SpecString);
break;
case NewArray:
@@ -1146,7 +1156,7 @@ bool AbstractState::execute(unsigned indexInBlock)
AbstractValue& source = forNode(node.child1());
AbstractValue& destination = forNode(nodeIndex);
- if (isObjectPrediction(source.m_type)) {
+ if (isObjectSpeculation(source.m_type)) {
// This is the simple case. We already know that the source is an
// object, so there's nothing to do. I don't think this case will
// be hit, but then again, you never know.
@@ -1157,20 +1167,20 @@ bool AbstractState::execute(unsigned indexInBlock)
node.setCanExit(true);
- if (isOtherPrediction(child.prediction())) {
- source.filter(PredictOther);
- destination.set(PredictObjectOther);
+ if (isOtherSpeculation(child.prediction())) {
+ source.filter(SpecOther);
+ destination.set(SpecObjectOther);
break;
}
- if (isObjectPrediction(child.prediction())) {
- source.filter(PredictObjectMask);
+ if (isObjectSpeculation(child.prediction())) {
+ source.filter(SpecObjectMask);
destination = source;
break;
}
destination = source;
- destination.merge(PredictObjectOther);
+ destination.merge(SpecObjectOther);
break;
}
@@ -1178,10 +1188,10 @@ bool AbstractState::execute(unsigned indexInBlock)
AbstractValue& source = forNode(node.child1());
AbstractValue& destination = forNode(nodeIndex);
- node.setCanExit(!isCellPrediction(source.m_type));
+ node.setCanExit(!isCellSpeculation(source.m_type));
- source.filter(PredictFunction);
- destination.set(PredictFinalObject);
+ source.filter(SpecFunction);
+ destination.set(SpecFinalObject);
break;
}
@@ -1210,10 +1220,13 @@ bool AbstractState::execute(unsigned indexInBlock)
break;
case CheckArgumentsNotCreated:
- node.setCanExit(
- !isEmptyPrediction(
+ if (isEmptySpeculation(
m_variables.operand(
- m_graph.argumentsRegisterFor(node.codeOrigin)).m_type));
+ m_graph.argumentsRegisterFor(node.codeOrigin)).m_type)) {
+ node.setCanExit(false);
+ m_foundConstants = true;
+ } else
+ node.setCanExit(true);
break;
case GetMyArgumentsLength:
@@ -1224,9 +1237,9 @@ bool AbstractState::execute(unsigned indexInBlock)
if (node.codeOrigin.inlineCallFrame)
forNode(nodeIndex).set(jsNumber(node.codeOrigin.inlineCallFrame->arguments.size() - 1));
else
- forNode(nodeIndex).set(PredictInt32);
+ forNode(nodeIndex).set(SpecInt32);
node.setCanExit(
- !isEmptyPrediction(
+ !isEmptySpeculation(
m_variables.operand(
m_graph.argumentsRegisterFor(node.codeOrigin)).m_type));
break;
@@ -1246,7 +1259,7 @@ bool AbstractState::execute(unsigned indexInBlock)
// We know that this executable does not escape its arguments, so we can optimize
// the arguments a bit. Note that this ends up being further optimized by the
// ArgumentsSimplificationPhase.
- forNode(node.child1()).filter(PredictInt32);
+ forNode(node.child1()).filter(SpecInt32);
forNode(nodeIndex).makeTop();
break;
@@ -1256,7 +1269,7 @@ bool AbstractState::execute(unsigned indexInBlock)
// a getter. We don't speculate against this.
clobberWorld(node.codeOrigin, indexInBlock);
// But we do speculate that the index is an integer.
- forNode(node.child1()).filter(PredictInt32);
+ forNode(node.child1()).filter(SpecInt32);
// And the result is unknown.
forNode(nodeIndex).makeTop();
break;
@@ -1270,12 +1283,12 @@ bool AbstractState::execute(unsigned indexInBlock)
case GetCallee:
node.setCanExit(false);
- forNode(nodeIndex).set(PredictFunction);
+ forNode(nodeIndex).set(SpecFunction);
break;
case GetScopeChain:
node.setCanExit(false);
- forNode(nodeIndex).set(PredictCellOther);
+ forNode(nodeIndex).set(SpecCellOther);
break;
case GetScopedVar:
@@ -1295,74 +1308,74 @@ bool AbstractState::execute(unsigned indexInBlock)
m_isValid = false;
break;
}
- if (isCellPrediction(m_graph[node.child1()].prediction()))
- forNode(node.child1()).filter(PredictCell);
+ if (isCellSpeculation(m_graph[node.child1()].prediction()))
+ forNode(node.child1()).filter(SpecCell);
clobberWorld(node.codeOrigin, indexInBlock);
forNode(nodeIndex).makeTop();
break;
case GetArrayLength:
node.setCanExit(true);
- forNode(node.child1()).filter(PredictArray);
- forNode(nodeIndex).set(PredictInt32);
+ forNode(node.child1()).filter(SpecArray);
+ forNode(nodeIndex).set(SpecInt32);
break;
case GetArgumentsLength:
node.setCanExit(true);
- forNode(node.child1()).filter(PredictArguments);
- forNode(nodeIndex).set(PredictInt32);
+ forNode(node.child1()).filter(SpecArguments);
+ forNode(nodeIndex).set(SpecInt32);
break;
case GetStringLength:
- node.setCanExit(!isStringPrediction(forNode(node.child1()).m_type));
- forNode(node.child1()).filter(PredictString);
- forNode(nodeIndex).set(PredictInt32);
+ node.setCanExit(!isStringSpeculation(forNode(node.child1()).m_type));
+ forNode(node.child1()).filter(SpecString);
+ forNode(nodeIndex).set(SpecInt32);
break;
case GetInt8ArrayLength:
- node.setCanExit(!isInt8ArrayPrediction(forNode(node.child1()).m_type));
- forNode(node.child1()).filter(PredictInt8Array);
- forNode(nodeIndex).set(PredictInt32);
+ node.setCanExit(!isInt8ArraySpeculation(forNode(node.child1()).m_type));
+ forNode(node.child1()).filter(SpecInt8Array);
+ forNode(nodeIndex).set(SpecInt32);
break;
case GetInt16ArrayLength:
- node.setCanExit(!isInt16ArrayPrediction(forNode(node.child1()).m_type));
- forNode(node.child1()).filter(PredictInt16Array);
- forNode(nodeIndex).set(PredictInt32);
+ node.setCanExit(!isInt16ArraySpeculation(forNode(node.child1()).m_type));
+ forNode(node.child1()).filter(SpecInt16Array);
+ forNode(nodeIndex).set(SpecInt32);
break;
case GetInt32ArrayLength:
- node.setCanExit(!isInt32ArrayPrediction(forNode(node.child1()).m_type));
- forNode(node.child1()).filter(PredictInt32Array);
- forNode(nodeIndex).set(PredictInt32);
+ node.setCanExit(!isInt32ArraySpeculation(forNode(node.child1()).m_type));
+ forNode(node.child1()).filter(SpecInt32Array);
+ forNode(nodeIndex).set(SpecInt32);
break;
case GetUint8ArrayLength:
- node.setCanExit(!isUint8ArrayPrediction(forNode(node.child1()).m_type));
- forNode(node.child1()).filter(PredictUint8Array);
- forNode(nodeIndex).set(PredictInt32);
+ node.setCanExit(!isUint8ArraySpeculation(forNode(node.child1()).m_type));
+ forNode(node.child1()).filter(SpecUint8Array);
+ forNode(nodeIndex).set(SpecInt32);
break;
case GetUint8ClampedArrayLength:
- node.setCanExit(!isUint8ClampedArrayPrediction(forNode(node.child1()).m_type));
- forNode(node.child1()).filter(PredictUint8ClampedArray);
- forNode(nodeIndex).set(PredictInt32);
+ node.setCanExit(!isUint8ClampedArraySpeculation(forNode(node.child1()).m_type));
+ forNode(node.child1()).filter(SpecUint8ClampedArray);
+ forNode(nodeIndex).set(SpecInt32);
break;
case GetUint16ArrayLength:
- node.setCanExit(!isUint16ArrayPrediction(forNode(node.child1()).m_type));
- forNode(node.child1()).filter(PredictUint16Array);
- forNode(nodeIndex).set(PredictInt32);
+ node.setCanExit(!isUint16ArraySpeculation(forNode(node.child1()).m_type));
+ forNode(node.child1()).filter(SpecUint16Array);
+ forNode(nodeIndex).set(SpecInt32);
break;
case GetUint32ArrayLength:
- node.setCanExit(!isUint32ArrayPrediction(forNode(node.child1()).m_type));
- forNode(node.child1()).filter(PredictUint32Array);
- forNode(nodeIndex).set(PredictInt32);
+ node.setCanExit(!isUint32ArraySpeculation(forNode(node.child1()).m_type));
+ forNode(node.child1()).filter(SpecUint32Array);
+ forNode(nodeIndex).set(SpecInt32);
break;
case GetFloat32ArrayLength:
- node.setCanExit(!isFloat32ArrayPrediction(forNode(node.child1()).m_type));
- forNode(node.child1()).filter(PredictFloat32Array);
- forNode(nodeIndex).set(PredictInt32);
+ node.setCanExit(!isFloat32ArraySpeculation(forNode(node.child1()).m_type));
+ forNode(node.child1()).filter(SpecFloat32Array);
+ forNode(nodeIndex).set(SpecInt32);
break;
case GetFloat64ArrayLength:
- node.setCanExit(!isFloat64ArrayPrediction(forNode(node.child1()).m_type));
- forNode(node.child1()).filter(PredictFloat64Array);
- forNode(nodeIndex).set(PredictInt32);
+ node.setCanExit(!isFloat64ArraySpeculation(forNode(node.child1()).m_type));
+ forNode(node.child1()).filter(SpecFloat64Array);
+ forNode(nodeIndex).set(SpecInt32);
break;
case CheckStructure: {
@@ -1370,11 +1383,20 @@ bool AbstractState::execute(unsigned indexInBlock)
AbstractValue& value = forNode(node.child1());
node.setCanExit(
!value.m_structure.isSubsetOf(node.structureSet())
- || !isCellPrediction(value.m_type));
+ || !isCellSpeculation(value.m_type));
value.filter(node.structureSet());
m_haveStructures = true;
break;
}
+
+ case StructureTransitionWatchpoint: {
+ // FIXME: Turn CheckStructure into StructureTransitionWatchpoint when possible!
+ AbstractValue& value = forNode(node.child1());
+ ASSERT(isCellSpeculation(value.m_type));
+ value.filter(node.structure());
+ node.setCanExit(true);
+ break;
+ }
case PutStructure:
case PhantomPutStructure:
@@ -1385,13 +1407,13 @@ bool AbstractState::execute(unsigned indexInBlock)
break;
case GetPropertyStorage:
node.setCanExit(false);
- forNode(node.child1()).filter(PredictCell);
+ forNode(node.child1()).filter(SpecCell);
forNode(nodeIndex).clear(); // The result is not a JS value.
break;
case GetIndexedPropertyStorage: {
node.setCanExit(true); // Lies, but this is (almost) always followed by GetByVal, which does exit. So no point in trying to be more precise.
- PredictedType basePrediction = m_graph[node.child2()].prediction();
- if (!(basePrediction & PredictInt32) && basePrediction) {
+ SpeculatedType basePrediction = m_graph[node.child2()].prediction();
+ if (!(basePrediction & SpecInt32) && basePrediction) {
forNode(nodeIndex).clear();
break;
}
@@ -1399,82 +1421,82 @@ bool AbstractState::execute(unsigned indexInBlock)
ASSERT_NOT_REACHED();
break;
}
- if (m_graph[node.child1()].prediction() == PredictString) {
- forNode(node.child1()).filter(PredictString);
+ if (m_graph[node.child1()].prediction() == SpecString) {
+ forNode(node.child1()).filter(SpecString);
forNode(nodeIndex).clear();
break;
}
if (m_graph[node.child1()].shouldSpeculateInt8Array()) {
- forNode(node.child1()).filter(PredictInt8Array);
+ forNode(node.child1()).filter(SpecInt8Array);
forNode(nodeIndex).clear();
break;
}
if (m_graph[node.child1()].shouldSpeculateInt16Array()) {
- forNode(node.child1()).filter(PredictInt16Array);
+ forNode(node.child1()).filter(SpecInt16Array);
forNode(nodeIndex).clear();
break;
}
if (m_graph[node.child1()].shouldSpeculateInt32Array()) {
- forNode(node.child1()).filter(PredictInt32Array);
+ forNode(node.child1()).filter(SpecInt32Array);
forNode(nodeIndex).clear();
break;
}
if (m_graph[node.child1()].shouldSpeculateUint8Array()) {
- forNode(node.child1()).filter(PredictUint8Array);
+ forNode(node.child1()).filter(SpecUint8Array);
forNode(nodeIndex).clear();
break;
}
if (m_graph[node.child1()].shouldSpeculateUint8ClampedArray()) {
- forNode(node.child1()).filter(PredictUint8ClampedArray);
+ forNode(node.child1()).filter(SpecUint8ClampedArray);
forNode(nodeIndex).clear();
break;
}
if (m_graph[node.child1()].shouldSpeculateUint16Array()) {
- forNode(node.child1()).filter(PredictUint16Array);
- forNode(nodeIndex).set(PredictOther);
+ forNode(node.child1()).filter(SpecUint16Array);
+ forNode(nodeIndex).set(SpecOther);
break;
}
if (m_graph[node.child1()].shouldSpeculateUint32Array()) {
- forNode(node.child1()).filter(PredictUint32Array);
+ forNode(node.child1()).filter(SpecUint32Array);
forNode(nodeIndex).clear();
break;
}
if (m_graph[node.child1()].shouldSpeculateFloat32Array()) {
- forNode(node.child1()).filter(PredictFloat32Array);
+ forNode(node.child1()).filter(SpecFloat32Array);
forNode(nodeIndex).clear();
break;
}
if (m_graph[node.child1()].shouldSpeculateFloat64Array()) {
- forNode(node.child1()).filter(PredictFloat64Array);
+ forNode(node.child1()).filter(SpecFloat64Array);
forNode(nodeIndex).clear();
break;
}
- forNode(node.child1()).filter(PredictArray);
+ forNode(node.child1()).filter(SpecArray);
forNode(nodeIndex).clear();
break;
}
case GetByOffset:
node.setCanExit(false);
- forNode(node.child1()).filter(PredictCell);
+ forNode(node.child1()).filter(SpecCell);
forNode(nodeIndex).makeTop();
break;
case PutByOffset:
node.setCanExit(false);
- forNode(node.child1()).filter(PredictCell);
+ forNode(node.child1()).filter(SpecCell);
break;
case CheckFunction:
node.setCanExit(true); // Lies! We can do better.
- forNode(node.child1()).filter(PredictFunction);
+ forNode(node.child1()).filter(SpecFunction);
// FIXME: Should be able to propagate the fact that we know what the function is.
break;
-
+
case PutById:
case PutByIdDirect:
node.setCanExit(true);
- forNode(node.child1()).filter(PredictCell);
+ forNode(node.child1()).filter(SpecCell);
clobberWorld(node.codeOrigin, indexInBlock);
break;
@@ -1482,24 +1504,29 @@ bool AbstractState::execute(unsigned indexInBlock)
node.setCanExit(false);
forNode(nodeIndex).makeTop();
break;
+
+ case GlobalVarWatchpoint:
+ node.setCanExit(true);
+ break;
case PutGlobalVar:
+ case PutGlobalVarCheck:
node.setCanExit(false);
break;
case CheckHasInstance:
node.setCanExit(true);
- forNode(node.child1()).filter(PredictCell);
+ forNode(node.child1()).filter(SpecCell);
// Sadly, we don't propagate the fact that we've done CheckHasInstance
break;
case InstanceOf:
node.setCanExit(true);
// Again, sadly, we don't propagate the fact that we've done InstanceOf
- if (!(m_graph[node.child1()].prediction() & ~PredictCell) && !(forNode(node.child1()).m_type & ~PredictCell))
- forNode(node.child1()).filter(PredictCell);
- forNode(node.child3()).filter(PredictCell);
- forNode(nodeIndex).set(PredictBoolean);
+ if (!(m_graph[node.child1()].prediction() & ~SpecCell) && !(forNode(node.child1()).m_type & ~SpecCell))
+ forNode(node.child1()).filter(SpecCell);
+ forNode(node.child3()).filter(SpecCell);
+ forNode(nodeIndex).set(SpecBoolean);
break;
case Phi:
@@ -1572,6 +1599,7 @@ inline void AbstractState::clobberStructures(unsigned indexInBlock)
for (size_t i = m_variables.numberOfLocals(); i--;)
m_variables.local(i).clobberStructures();
m_haveStructures = false;
+ m_didClobber = true;
}
inline bool AbstractState::mergeStateAtTail(AbstractValue& destination, AbstractValue& inVariable, NodeIndex nodeIndex)
@@ -1625,7 +1653,7 @@ inline bool AbstractState::mergeStateAtTail(AbstractValue& destination, Abstract
// before and after setting it.
if (node.variableAccessData()->shouldUseDoubleFormat()) {
// FIXME: This unnecessarily loses precision.
- source.set(PredictDouble);
+ source.set(SpecDouble);
} else
source = forNode(node.child1());
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
diff --git a/Source/JavaScriptCore/dfg/DFGAbstractState.h b/Source/JavaScriptCore/dfg/DFGAbstractState.h
index 4b0a248f3..9bb74cd86 100644
--- a/Source/JavaScriptCore/dfg/DFGAbstractState.h
+++ b/Source/JavaScriptCore/dfg/DFGAbstractState.h
@@ -193,6 +193,9 @@ public:
// of Throw.
bool execute(unsigned);
+ // Did the last executed node clobber the world?
+ bool didClobber() const { return m_didClobber; }
+
// Is the execution state still valid? This will be false if execute() has
// returned false previously.
bool isValid() const { return m_isValid; }
@@ -223,22 +226,22 @@ private:
void speculateInt32Unary(Node& node, bool forceCanExit = false)
{
AbstractValue& childValue = forNode(node.child1());
- node.setCanExit(forceCanExit || !isInt32Prediction(childValue.m_type));
- childValue.filter(PredictInt32);
+ node.setCanExit(forceCanExit || !isInt32Speculation(childValue.m_type));
+ childValue.filter(SpecInt32);
}
void speculateNumberUnary(Node& node)
{
AbstractValue& childValue = forNode(node.child1());
- node.setCanExit(!isNumberPrediction(childValue.m_type));
- childValue.filter(PredictNumber);
+ node.setCanExit(!isNumberSpeculation(childValue.m_type));
+ childValue.filter(SpecNumber);
}
void speculateBooleanUnary(Node& node)
{
AbstractValue& childValue = forNode(node.child1());
- node.setCanExit(!isBooleanPrediction(childValue.m_type));
- childValue.filter(PredictBoolean);
+ node.setCanExit(!isBooleanSpeculation(childValue.m_type));
+ childValue.filter(SpecBoolean);
}
void speculateInt32Binary(Node& node, bool forceCanExit = false)
@@ -247,10 +250,10 @@ private:
AbstractValue& childValue2 = forNode(node.child2());
node.setCanExit(
forceCanExit
- || !isInt32Prediction(childValue1.m_type)
- || !isInt32Prediction(childValue2.m_type));
- childValue1.filter(PredictInt32);
- childValue2.filter(PredictInt32);
+ || !isInt32Speculation(childValue1.m_type)
+ || !isInt32Speculation(childValue2.m_type));
+ childValue1.filter(SpecInt32);
+ childValue2.filter(SpecInt32);
}
void speculateNumberBinary(Node& node)
@@ -258,10 +261,10 @@ private:
AbstractValue& childValue1 = forNode(node.child1());
AbstractValue& childValue2 = forNode(node.child2());
node.setCanExit(
- !isNumberPrediction(childValue1.m_type)
- || !isNumberPrediction(childValue2.m_type));
- childValue1.filter(PredictNumber);
- childValue2.filter(PredictNumber);
+ !isNumberSpeculation(childValue1.m_type)
+ || !isNumberSpeculation(childValue2.m_type));
+ childValue1.filter(SpecNumber);
+ childValue2.filter(SpecNumber);
}
CodeBlock* m_codeBlock;
@@ -274,6 +277,7 @@ private:
bool m_foundConstants;
bool m_isValid;
+ bool m_didClobber;
BranchDirection m_branchDirection; // This is only set for blocks that end in Branch and that execute to completion (i.e. m_isValid == true).
};
diff --git a/Source/JavaScriptCore/dfg/DFGAbstractValue.h b/Source/JavaScriptCore/dfg/DFGAbstractValue.h
index c61a383eb..f81af4ecf 100644
--- a/Source/JavaScriptCore/dfg/DFGAbstractValue.h
+++ b/Source/JavaScriptCore/dfg/DFGAbstractValue.h
@@ -31,7 +31,7 @@
#if ENABLE(DFG_JIT)
#include "JSCell.h"
-#include "PredictedType.h"
+#include "SpeculatedType.h"
#include "StructureSet.h"
namespace JSC { namespace DFG {
@@ -225,9 +225,9 @@ public:
m_structure = 0;
}
- void filter(PredictedType other)
+ void filter(SpeculatedType other)
{
- if (!(other & PredictCell)) {
+ if (!(other & SpecCell)) {
clear();
return;
}
@@ -235,7 +235,7 @@ public:
if (isClearOrTop())
return;
- if (!(predictionFromStructure(m_structure) & other))
+ if (!(speculationFromStructure(m_structure) & other))
m_structure = 0;
}
@@ -273,13 +273,13 @@ public:
return at(0);
}
- PredictedType predictionFromStructures() const
+ SpeculatedType speculationFromStructures() const
{
if (isTop())
- return PredictCell;
+ return SpecCell;
if (isClear())
- return PredictNone;
- return predictionFromStructure(m_structure);
+ return SpecNone;
+ return speculationFromStructure(m_structure);
}
bool operator==(const StructureAbstractValue& other) const
@@ -309,13 +309,13 @@ private:
struct AbstractValue {
AbstractValue()
- : m_type(PredictNone)
+ : m_type(SpecNone)
{
}
void clear()
{
- m_type = PredictNone;
+ m_type = SpecNone;
m_structure.clear();
m_value = JSValue();
checkConsistency();
@@ -323,7 +323,7 @@ struct AbstractValue {
bool isClear() const
{
- bool result = m_type == PredictNone && m_structure.isClear();
+ bool result = m_type == SpecNone && m_structure.isClear();
if (result)
ASSERT(!m_value);
return result;
@@ -331,7 +331,7 @@ struct AbstractValue {
void makeTop()
{
- m_type = PredictTop;
+ m_type = SpecTop;
m_structure.makeTop();
m_value = JSValue();
checkConsistency();
@@ -339,7 +339,7 @@ struct AbstractValue {
void clobberStructures()
{
- if (m_type & PredictCell)
+ if (m_type & SpecCell)
m_structure.makeTop();
else
ASSERT(m_structure.isClear());
@@ -353,7 +353,7 @@ struct AbstractValue {
bool isTop() const
{
- return m_type == PredictTop && m_structure.isTop();
+ return m_type == SpecTop && m_structure.isTop();
}
bool valueIsTop() const
@@ -386,7 +386,7 @@ struct AbstractValue {
} else
m_structure.clear();
- m_type = predictionFromValue(value);
+ m_type = speculationFromValue(value);
m_value = value;
checkConsistency();
@@ -397,15 +397,15 @@ struct AbstractValue {
m_structure.clear();
m_structure.add(structure);
- m_type = predictionFromStructure(structure);
+ m_type = speculationFromStructure(structure);
m_value = JSValue();
checkConsistency();
}
- void set(PredictedType type)
+ void set(SpeculatedType type)
{
- if (type & PredictCell)
+ if (type & SpecCell)
m_structure.makeTop();
else
m_structure.clear();
@@ -435,7 +435,7 @@ struct AbstractValue {
*this = other;
result = !other.isClear();
} else {
- result |= mergePrediction(m_type, other.m_type);
+ result |= mergeSpeculation(m_type, other.m_type);
result |= m_structure.addAll(other.m_structure);
if (m_value != other.m_value) {
result |= !!m_value;
@@ -447,11 +447,11 @@ struct AbstractValue {
return result;
}
- void merge(PredictedType type)
+ void merge(SpeculatedType type)
{
- mergePrediction(m_type, type);
+ mergeSpeculation(m_type, type);
- if (type & PredictCell)
+ if (type & SpecCell)
m_structure.makeTop();
m_value = JSValue();
@@ -460,13 +460,13 @@ struct AbstractValue {
void filter(const StructureSet& other)
{
- m_type &= other.predictionFromStructures();
+ m_type &= other.speculationFromStructures();
m_structure.filter(other);
// It's possible that prior to the above two statements we had (Foo, TOP), where
- // Foo is a PredictedType that is disjoint with the passed StructureSet. In that
+ // Foo is a SpeculatedType that is disjoint with the passed StructureSet. In that
// case, we will now have (None, [someStructure]). In general, we need to make
- // sure that new information gleaned from the PredictedType needs to be fed back
+ // sure that new information gleaned from the SpeculatedType needs to be fed back
// into the information gleaned from the StructureSet.
m_structure.filter(m_type);
@@ -476,9 +476,9 @@ struct AbstractValue {
checkConsistency();
}
- void filter(PredictedType type)
+ void filter(SpeculatedType type)
{
- if (type == PredictTop)
+ if (type == SpecTop)
return;
m_type &= type;
@@ -499,11 +499,11 @@ struct AbstractValue {
if (isTop())
return true;
- if (mergePredictions(m_type, predictionFromValue(value)) != m_type)
+ if (mergeSpeculations(m_type, speculationFromValue(value)) != m_type)
return false;
if (value.isEmpty()) {
- ASSERT(m_type & PredictEmpty);
+ ASSERT(m_type & SpecEmpty);
return true;
}
@@ -511,7 +511,7 @@ struct AbstractValue {
return true;
if (!!value && value.isCell()) {
- ASSERT(m_type & PredictCell);
+ ASSERT(m_type & SpecCell);
return m_structure.contains(value.asCell()->structure());
}
@@ -526,11 +526,11 @@ struct AbstractValue {
if (!!m_value)
return m_value == value;
- if (mergePredictions(m_type, predictionFromValue(value)) != m_type)
+ if (mergeSpeculations(m_type, speculationFromValue(value)) != m_type)
return false;
if (value.isEmpty()) {
- ASSERT(m_type & PredictEmpty);
+ ASSERT(m_type & SpecEmpty);
return true;
}
@@ -538,7 +538,7 @@ struct AbstractValue {
return true;
if (!!value && value.isCell()) {
- ASSERT(m_type & PredictCell);
+ ASSERT(m_type & SpecCell);
return m_structure.contains(value.asCell()->structure());
}
@@ -547,14 +547,14 @@ struct AbstractValue {
void checkConsistency() const
{
- if (!(m_type & PredictCell))
+ if (!(m_type & SpecCell))
ASSERT(m_structure.isClear());
if (isClear())
ASSERT(!m_value);
if (!!m_value)
- ASSERT(mergePredictions(m_type, predictionFromValue(m_value)) == m_type);
+ ASSERT(mergeSpeculations(m_type, speculationFromValue(m_value)) == m_type);
// Note that it's possible for a prediction like (Final, []). This really means that
// the value is bottom and that any code that uses the value is unreachable. But
@@ -564,7 +564,7 @@ struct AbstractValue {
void dump(FILE* out) const
{
- fprintf(out, "(%s, ", predictionToString(m_type));
+ fprintf(out, "(%s, ", speculationToString(m_type));
m_structure.dump(out);
if (!!m_value)
fprintf(out, ", %s", m_value.description());
@@ -572,7 +572,7 @@ struct AbstractValue {
}
StructureAbstractValue m_structure;
- PredictedType m_type;
+ SpeculatedType m_type;
JSValue m_value;
};
diff --git a/Source/JavaScriptCore/dfg/DFGArgumentPosition.h b/Source/JavaScriptCore/dfg/DFGArgumentPosition.h
index ed447ff91..05d1cb048 100644
--- a/Source/JavaScriptCore/dfg/DFGArgumentPosition.h
+++ b/Source/JavaScriptCore/dfg/DFGArgumentPosition.h
@@ -28,14 +28,14 @@
#include "DFGDoubleFormatState.h"
#include "DFGVariableAccessData.h"
-#include "PredictedType.h"
+#include "SpeculatedType.h"
namespace JSC { namespace DFG {
class ArgumentPosition {
public:
ArgumentPosition()
- : m_prediction(PredictNone)
+ : m_prediction(SpecNone)
, m_doubleFormatState(EmptyDoubleFormatState)
{
}
@@ -49,7 +49,7 @@ public:
{
bool changed = false;
for (unsigned i = 0; i < m_variables.size(); ++i) {
- changed |= mergePrediction(m_prediction, m_variables[i]->argumentAwarePrediction());
+ changed |= mergeSpeculation(m_prediction, m_variables[i]->argumentAwarePrediction());
changed |= mergeDoubleFormatState(m_doubleFormatState, m_variables[i]->doubleFormatState());
}
if (!changed)
@@ -62,8 +62,15 @@ public:
return changed;
}
+ SpeculatedType prediction() const { return m_prediction; }
+ DoubleFormatState doubleFormatState() const { return m_doubleFormatState; }
+ bool shouldUseDoubleFormat() const
+ {
+ return doubleFormatState() == UsingDoubleFormat;
+ }
+
private:
- PredictedType m_prediction;
+ SpeculatedType m_prediction;
DoubleFormatState m_doubleFormatState;
Vector<VariableAccessData*, 2> m_variables;
diff --git a/Source/JavaScriptCore/dfg/DFGArgumentsSimplificationPhase.cpp b/Source/JavaScriptCore/dfg/DFGArgumentsSimplificationPhase.cpp
index 48163a91b..28e686aef 100644
--- a/Source/JavaScriptCore/dfg/DFGArgumentsSimplificationPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGArgumentsSimplificationPhase.cpp
@@ -170,9 +170,17 @@ public:
break;
}
+ case TearOffArguments: {
+ // Ignore arguments tear off, because it's only relevant if we actually
+ // need to create the arguments.
+ break;
+ }
+
case SetLocal: {
Node& source = m_graph[node.child1()];
VariableAccessData* variableAccessData = node.variableAccessData();
+ int argumentsRegister =
+ m_graph.uncheckedArgumentsRegisterFor(node.codeOrigin);
if (source.op() != CreateArguments) {
// Make sure that the source of the SetLocal knows that if it's
// a variable that we think is aliased to the arguments, then it
@@ -180,8 +188,28 @@ public:
// aliasing. But not yet.
observeBadArgumentsUse(node.child1());
- if (variableAccessData->isCaptured())
+ if (variableAccessData->isCaptured()) {
+ // If this is an assignment to the arguments register, then
+ // pretend as if the arguments were created. We don't want to
+ // optimize code that explicitly assigns to the arguments,
+ // because that seems too ugly.
+
+ // But, before getting rid of CreateArguments, we will have
+ // an assignment to the arguments registers with JSValue().
+ // That's because CSE will refuse to get rid of the
+ // init_lazy_reg since it treats CreateArguments as reading
+ // local variables. That could be fixed, but it's easier to
+ // work around this here.
+ if (source.op() == JSConstant
+ && !source.valueOfJSConstant(codeBlock()))
+ break;
+
+ if (argumentsRegister != InvalidVirtualRegister
+ && (variableAccessData->local() == argumentsRegister
+ || variableAccessData->local() == unmodifiedArgumentsRegister(argumentsRegister)))
+ m_createsArguments.add(node.codeOrigin.inlineCallFrame);
break;
+ }
// Make sure that if it's a variable that we think is aliased to
// the arguments, that we know that it might actually not be.
@@ -191,11 +219,9 @@ public:
data.mergeCallContext(node.codeOrigin.inlineCallFrame);
break;
}
- int argumentsRegister =
- m_graph.uncheckedArgumentsRegisterFor(node.codeOrigin);
- if (variableAccessData->local() == argumentsRegister
- || variableAccessData->local() ==
- unmodifiedArgumentsRegister(argumentsRegister)) {
+ if (argumentsRegister != InvalidVirtualRegister
+ && (variableAccessData->local() == argumentsRegister
+ || variableAccessData->local() == unmodifiedArgumentsRegister(argumentsRegister))) {
if (node.codeOrigin.inlineCallFrame == source.codeOrigin.inlineCallFrame)
break;
m_createsArguments.add(source.codeOrigin.inlineCallFrame);
@@ -258,7 +284,7 @@ public:
break;
}
- if (!isActionableArrayPrediction(m_graph[node.child1()].prediction())
+ if (!isActionableArraySpeculation(m_graph[node.child1()].prediction())
|| !m_graph[node.child2()].shouldSpeculateInteger()) {
observeBadArgumentsUses(node);
break;
@@ -398,10 +424,25 @@ public:
if (source.op() != CreateArguments)
break;
+ if (m_createsArguments.contains(source.codeOrigin.inlineCallFrame))
+ break;
+
VariableAccessData* variableAccessData = node.variableAccessData();
- if (variableAccessData->isCaptured())
+ if (variableAccessData->isCaptured()) {
+ ASSERT(m_graph.argumentsRegisterFor(node.codeOrigin) == variableAccessData->local()
+ || unmodifiedArgumentsRegister(m_graph.argumentsRegisterFor(node.codeOrigin)) == variableAccessData->local());
+ // The child of this store should really be the empty value.
+ Node emptyJSValue(JSConstant, node.codeOrigin, OpInfo(codeBlock()->addOrFindConstant(JSValue())));
+ emptyJSValue.ref();
+ NodeIndex emptyJSValueIndex = m_graph.size();
+ m_graph.deref(node.child1());
+ node.children.child1() = Edge(emptyJSValueIndex);
+ m_graph.append(emptyJSValue);
+ insertionSet.append(indexInBlock, emptyJSValueIndex);
+ changed = true;
break;
+ }
// If this is a store into a VariableAccessData* that is marked as
// arguments aliasing for an InlineCallFrame* that does not create
@@ -410,11 +451,8 @@ public:
// things. Note also that the SetLocal should become dead as soon as
// we replace all uses of this variable with GetMyArgumentsLength and
// GetMyArgumentByVal.
- if (m_argumentsAliasing.find(variableAccessData)->second.isValid()
- && !m_createsArguments.contains(source.codeOrigin.inlineCallFrame)) {
- changed |= variableAccessData->mergeIsArgumentsAlias(true);
- break;
- }
+ ASSERT(m_argumentsAliasing.find(variableAccessData)->second.isValid());
+ changed |= variableAccessData->mergeIsArgumentsAlias(true);
break;
}
@@ -439,7 +477,7 @@ public:
|| !m_graph[node.child2()].prediction())
break;
- if (!isActionableArrayPrediction(m_graph[node.child1()].prediction())
+ if (!isActionableArraySpeculation(m_graph[node.child1()].prediction())
|| !m_graph[node.child2()].shouldSpeculateInteger())
break;
@@ -487,19 +525,21 @@ public:
node.setOp(GetMyArgumentsLength);
changed = true;
}
- if (!node.codeOrigin.inlineCallFrame)
+
+ CodeOrigin codeOrigin = node.codeOrigin;
+ if (!codeOrigin.inlineCallFrame)
break;
// We know exactly what this will return. But only after we have checked
// that nobody has escaped our arguments.
- Node check(CheckArgumentsNotCreated, node.codeOrigin);
+ Node check(CheckArgumentsNotCreated, codeOrigin);
check.ref();
NodeIndex checkIndex = m_graph.size();
m_graph.append(check);
insertionSet.append(indexInBlock, checkIndex);
m_graph.convertToConstant(
- nodeIndex, jsNumber(node.codeOrigin.inlineCallFrame->arguments.size() - 1));
+ nodeIndex, jsNumber(codeOrigin.inlineCallFrame->arguments.size() - 1));
changed = true;
break;
}
@@ -559,6 +599,16 @@ public:
break;
}
+ case TearOffArguments: {
+ if (m_createsArguments.contains(node.codeOrigin.inlineCallFrame))
+ continue;
+
+ node.setOpAndDefaultFlags(Nop);
+ m_graph.clearAndDerefChild1(node);
+ node.setRefCount(0);
+ break;
+ }
+
default:
break;
}
@@ -573,8 +623,6 @@ public:
for (unsigned indexInBlock = 0; indexInBlock < block->size(); ++indexInBlock) {
NodeIndex nodeIndex = block->at(indexInBlock);
Node& node = m_graph[nodeIndex];
- if (!node.shouldGenerate())
- continue;
if (node.op() != CreateArguments)
continue;
// If this is a CreateArguments for an InlineCallFrame* that does
@@ -583,14 +631,16 @@ public:
// empty value) in DFG and arguments creation for OSR exit.
if (m_createsArguments.contains(node.codeOrigin.inlineCallFrame))
continue;
- Node phantom(Phantom, node.codeOrigin);
- phantom.children = node.children;
- phantom.ref();
+ if (node.shouldGenerate()) {
+ Node phantom(Phantom, node.codeOrigin);
+ phantom.children = node.children;
+ phantom.ref();
+ NodeIndex phantomNodeIndex = m_graph.size();
+ m_graph.append(phantom);
+ insertionSet.append(indexInBlock, phantomNodeIndex);
+ }
node.setOpAndDefaultFlags(PhantomArguments);
node.children.reset();
- NodeIndex phantomNodeIndex = m_graph.size();
- m_graph.append(phantom);
- insertionSet.append(indexInBlock, phantomNodeIndex);
}
insertionSet.execute(*block);
}
@@ -622,7 +672,10 @@ private:
}
case GetLocal: {
- if (child.local() == m_graph.uncheckedArgumentsRegisterFor(child.codeOrigin)) {
+ int argumentsRegister = m_graph.uncheckedArgumentsRegisterFor(child.codeOrigin);
+ if (argumentsRegister != InvalidVirtualRegister
+ && (child.local() == argumentsRegister
+ || child.local() == unmodifiedArgumentsRegister(argumentsRegister))) {
m_createsArguments.add(child.codeOrigin.inlineCallFrame);
break;
}
@@ -684,25 +737,31 @@ private:
bool isOKToOptimize(Node& source)
{
+ if (m_createsArguments.contains(source.codeOrigin.inlineCallFrame))
+ return false;
+
switch (source.op()) {
case GetLocal: {
VariableAccessData* variableAccessData = source.variableAccessData();
- if (variableAccessData->isCaptured())
+ if (variableAccessData->isCaptured()) {
+ int argumentsRegister = m_graph.uncheckedArgumentsRegisterFor(source.codeOrigin);
+ if (argumentsRegister == InvalidVirtualRegister)
+ break;
+ if (argumentsRegister == variableAccessData->local())
+ return true;
+ if (unmodifiedArgumentsRegister(argumentsRegister) == variableAccessData->local())
+ return true;
break;
+ }
ArgumentsAliasingData& data =
m_argumentsAliasing.find(variableAccessData)->second;
if (!data.isValid())
break;
- if (m_createsArguments.contains(source.codeOrigin.inlineCallFrame))
- break;
return true;
}
case CreateArguments: {
- if (m_createsArguments.contains(source.codeOrigin.inlineCallFrame))
- break;
-
return true;
}
diff --git a/Source/JavaScriptCore/dfg/DFGAssemblyHelpers.h b/Source/JavaScriptCore/dfg/DFGAssemblyHelpers.h
index 9087eec57..f86c15e65 100644
--- a/Source/JavaScriptCore/dfg/DFGAssemblyHelpers.h
+++ b/Source/JavaScriptCore/dfg/DFGAssemblyHelpers.h
@@ -115,21 +115,6 @@ public:
#endif
}
- static Address addressForGlobalVar(GPRReg global, int32_t varNumber)
- {
- return Address(global, varNumber * sizeof(Register));
- }
-
- static Address tagForGlobalVar(GPRReg global, int32_t varNumber)
- {
- return Address(global, varNumber * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag));
- }
-
- static Address payloadForGlobalVar(GPRReg global, int32_t varNumber)
- {
- return Address(global, varNumber * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
- }
-
static Address addressFor(VirtualRegister virtualRegister)
{
return Address(GPRInfo::callFrameRegister, virtualRegister * sizeof(Register));
diff --git a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
index 358171029..317a08504 100644
--- a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
+++ b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
@@ -93,7 +93,10 @@ private:
// Handle setting the result of an intrinsic.
void setIntrinsicResult(bool usesResult, int resultOperand, NodeIndex);
// Handle intrinsic functions. Return true if it succeeded, false if we need to plant a call.
- bool handleIntrinsic(bool usesResult, int resultOperand, Intrinsic, int registerOffset, int argumentCountIncludingThis, PredictedType prediction);
+ bool handleIntrinsic(bool usesResult, int resultOperand, Intrinsic, int registerOffset, int argumentCountIncludingThis, SpeculatedType prediction);
+ void handleGetById(
+ int destinationOperand, SpeculatedType, NodeIndex base, unsigned identifierNumber,
+ const GetByIdStatus&);
// Prepare to parse a block.
void prepareToParseBlock();
// Parse a single basic block of bytecode instructions.
@@ -109,7 +112,7 @@ private:
template<PhiStackType stackType>
void processPhiStack();
- void fixVariableAccessPredictions();
+ void fixVariableAccessSpeculations();
// Add spill locations to nodes.
void allocateVirtualRegisters();
@@ -159,17 +162,17 @@ private:
setDirect(m_inlineStackTop->remapOperand(operand), value, setMode);
}
- NodeIndex injectLazyOperandPrediction(NodeIndex nodeIndex)
+ NodeIndex injectLazyOperandSpeculation(NodeIndex nodeIndex)
{
Node& node = m_graph[nodeIndex];
ASSERT(node.op() == GetLocal);
ASSERT(node.codeOrigin.bytecodeIndex == m_currentIndex);
- PredictedType prediction =
+ SpeculatedType prediction =
m_inlineStackTop->m_lazyOperands.prediction(
LazyOperandValueProfileKey(m_currentIndex, node.local()));
#if DFG_ENABLE(DEBUG_VERBOSE)
dataLog("Lazy operand [@%u, bc#%u, r%d] prediction: %s\n",
- nodeIndex, m_currentIndex, node.local(), predictionToString(prediction));
+ nodeIndex, m_currentIndex, node.local(), speculationToString(prediction));
#endif
node.variableAccessData()->predict(prediction);
return nodeIndex;
@@ -192,7 +195,7 @@ private:
if (flushChild.op() == Phi) {
VariableAccessData* variableAccessData = flushChild.variableAccessData();
variableAccessData->mergeIsCaptured(isCaptured);
- nodeIndex = injectLazyOperandPrediction(addToGraph(GetLocal, OpInfo(variableAccessData), nodeIndex));
+ nodeIndex = injectLazyOperandSpeculation(addToGraph(GetLocal, OpInfo(variableAccessData), nodeIndex));
m_currentBlock->variablesAtTail.local(operand) = nodeIndex;
return nodeIndex;
}
@@ -213,7 +216,7 @@ private:
if (nodePtr->op() == GetLocal)
nodeIndex = nodePtr->child1().index();
- return injectLazyOperandPrediction(addToGraph(GetLocal, OpInfo(nodePtr->variableAccessData()), nodeIndex));
+ return injectLazyOperandSpeculation(addToGraph(GetLocal, OpInfo(nodePtr->variableAccessData()), nodeIndex));
}
if (nodePtr->op() == GetLocal)
@@ -230,7 +233,7 @@ private:
NodeIndex phi = addToGraph(Phi, OpInfo(variableAccessData));
m_localPhiStack.append(PhiStackEntry(m_currentBlock, phi, operand));
- nodeIndex = injectLazyOperandPrediction(addToGraph(GetLocal, OpInfo(variableAccessData), phi));
+ nodeIndex = injectLazyOperandSpeculation(addToGraph(GetLocal, OpInfo(variableAccessData), phi));
m_currentBlock->variablesAtTail.local(operand) = nodeIndex;
m_currentBlock->variablesAtHead.setLocalFirstTime(operand, nodeIndex);
@@ -274,7 +277,7 @@ private:
if (flushChild.op() == Phi) {
VariableAccessData* variableAccessData = flushChild.variableAccessData();
variableAccessData->mergeIsCaptured(isCaptured);
- nodeIndex = injectLazyOperandPrediction(addToGraph(GetLocal, OpInfo(variableAccessData), nodeIndex));
+ nodeIndex = injectLazyOperandSpeculation(addToGraph(GetLocal, OpInfo(variableAccessData), nodeIndex));
m_currentBlock->variablesAtTail.argument(argument) = nodeIndex;
return nodeIndex;
}
@@ -290,7 +293,7 @@ private:
// We're getting an argument in the first basic block; link
// the GetLocal to the SetArgument.
ASSERT(nodePtr->local() == static_cast<VirtualRegister>(operand));
- nodeIndex = injectLazyOperandPrediction(addToGraph(GetLocal, OpInfo(nodePtr->variableAccessData()), nodeIndex));
+ nodeIndex = injectLazyOperandSpeculation(addToGraph(GetLocal, OpInfo(nodePtr->variableAccessData()), nodeIndex));
m_currentBlock->variablesAtTail.argument(argument) = nodeIndex;
return nodeIndex;
}
@@ -298,7 +301,7 @@ private:
if (isCaptured) {
if (nodePtr->op() == GetLocal)
nodeIndex = nodePtr->child1().index();
- return injectLazyOperandPrediction(addToGraph(GetLocal, OpInfo(nodePtr->variableAccessData()), nodeIndex));
+ return injectLazyOperandSpeculation(addToGraph(GetLocal, OpInfo(nodePtr->variableAccessData()), nodeIndex));
}
if (nodePtr->op() == GetLocal)
@@ -312,7 +315,7 @@ private:
NodeIndex phi = addToGraph(Phi, OpInfo(variableAccessData));
m_argumentPhiStack.append(PhiStackEntry(m_currentBlock, phi, argument));
- nodeIndex = injectLazyOperandPrediction(addToGraph(GetLocal, OpInfo(variableAccessData), phi));
+ nodeIndex = injectLazyOperandSpeculation(addToGraph(GetLocal, OpInfo(variableAccessData), phi));
m_currentBlock->variablesAtTail.argument(argument) = nodeIndex;
m_currentBlock->variablesAtHead.setArgumentFirstTime(argument, nodeIndex);
@@ -725,7 +728,7 @@ private:
{
Instruction* putInstruction = currentInstruction + OPCODE_LENGTH(op_call);
- PredictedType prediction = PredictNone;
+ SpeculatedType prediction = SpecNone;
if (interpreter->getOpcodeID(putInstruction->u.opcode) == op_call_put_result) {
m_currentProfilingIndex = m_currentIndex + OPCODE_LENGTH(op_call);
prediction = getPrediction();
@@ -747,23 +750,44 @@ private:
return call;
}
- PredictedType getPredictionWithoutOSRExit(NodeIndex nodeIndex, unsigned bytecodeIndex)
+ NodeIndex addStructureTransitionCheck(JSCell* object, Structure* structure)
+ {
+ // Add a weak JS constant for the object regardless, since the code should
+ // be jettisoned if the object ever dies.
+ NodeIndex objectIndex = cellConstant(object);
+
+ if (object->structure() == structure && structure->transitionWatchpointSetIsStillValid()) {
+ addToGraph(StructureTransitionWatchpoint, OpInfo(structure), objectIndex);
+ return objectIndex;
+ }
+
+ addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(structure)), objectIndex);
+
+ return objectIndex;
+ }
+
+ NodeIndex addStructureTransitionCheck(JSCell* object)
+ {
+ return addStructureTransitionCheck(object, object->structure());
+ }
+
+ SpeculatedType getPredictionWithoutOSRExit(NodeIndex nodeIndex, unsigned bytecodeIndex)
{
UNUSED_PARAM(nodeIndex);
- PredictedType prediction = m_inlineStackTop->m_profiledBlock->valueProfilePredictionForBytecodeOffset(bytecodeIndex);
+ SpeculatedType prediction = m_inlineStackTop->m_profiledBlock->valueProfilePredictionForBytecodeOffset(bytecodeIndex);
#if DFG_ENABLE(DEBUG_VERBOSE)
- dataLog("Dynamic [@%u, bc#%u] prediction: %s\n", nodeIndex, bytecodeIndex, predictionToString(prediction));
+ dataLog("Dynamic [@%u, bc#%u] prediction: %s\n", nodeIndex, bytecodeIndex, speculationToString(prediction));
#endif
return prediction;
}
- PredictedType getPrediction(NodeIndex nodeIndex, unsigned bytecodeIndex)
+ SpeculatedType getPrediction(NodeIndex nodeIndex, unsigned bytecodeIndex)
{
- PredictedType prediction = getPredictionWithoutOSRExit(nodeIndex, bytecodeIndex);
+ SpeculatedType prediction = getPredictionWithoutOSRExit(nodeIndex, bytecodeIndex);
- if (prediction == PredictNone) {
+ if (prediction == SpecNone) {
// We have no information about what values this node generates. Give up
// on executing this code, since we're likely to do more damage than good.
addToGraph(ForceOSRExit);
@@ -772,12 +796,12 @@ private:
return prediction;
}
- PredictedType getPredictionWithoutOSRExit()
+ SpeculatedType getPredictionWithoutOSRExit()
{
return getPredictionWithoutOSRExit(m_graph.size(), m_currentProfilingIndex);
}
- PredictedType getPrediction()
+ SpeculatedType getPrediction()
{
return getPrediction(m_graph.size(), m_currentProfilingIndex);
}
@@ -1020,7 +1044,7 @@ private:
VirtualRegister m_returnValue;
- // Predictions about variable types collected from the profiled code block,
+ // Speculations about variable types collected from the profiled code block,
// which are based on OSR exit profiles that past DFG compilatins of this
// code block had gathered.
LazyOperandValueProfileParser m_lazyOperands;
@@ -1147,7 +1171,7 @@ void ByteCodeParser::handleCall(Interpreter* interpreter, Instruction* currentIn
int resultOperand = 0; // make compiler happy
unsigned nextOffset = m_currentIndex + OPCODE_LENGTH(op_call);
Instruction* putInstruction = currentInstruction + OPCODE_LENGTH(op_call);
- PredictedType prediction = PredictNone;
+ SpeculatedType prediction = SpecNone;
if (interpreter->getOpcodeID(putInstruction->u.opcode) == op_call_put_result) {
resultOperand = putInstruction[1].u.operand;
usesResult = true;
@@ -1231,6 +1255,9 @@ bool ByteCodeParser::handleInlining(bool usesResult, int callTarget, NodeIndex c
// Does the code block's size match the heuristics/requirements for being
// an inline candidate?
CodeBlock* profiledBlock = executable->profiledCodeBlockFor(kind);
+ if (!profiledBlock)
+ return false;
+
if (!mightInlineFunctionFor(profiledBlock, kind))
return false;
@@ -1270,6 +1297,8 @@ bool ByteCodeParser::handleInlining(bool usesResult, int callTarget, NodeIndex c
for (size_t i = 0; i < m_graph.m_blocks.size(); ++i)
m_graph.m_blocks[i]->ensureLocals(newNumLocals);
}
+
+ size_t argumentPositionStart = m_graph.m_argumentPositions.size();
InlineStackEntry inlineStackEntry(
this, codeBlock, profiledBlock, m_graph.m_blocks.size() - 1,
@@ -1284,7 +1313,7 @@ bool ByteCodeParser::handleInlining(bool usesResult, int callTarget, NodeIndex c
m_currentIndex = 0;
m_currentProfilingIndex = 0;
- addToGraph(InlineStart);
+ addToGraph(InlineStart, OpInfo(argumentPositionStart));
parseCodeBlock();
@@ -1418,7 +1447,7 @@ bool ByteCodeParser::handleMinMax(bool usesResult, int resultOperand, NodeType o
// FIXME: We dead-code-eliminate unused Math intrinsics, but that's invalid because
// they need to perform the ToNumber conversion, which can have side-effects.
-bool ByteCodeParser::handleIntrinsic(bool usesResult, int resultOperand, Intrinsic intrinsic, int registerOffset, int argumentCountIncludingThis, PredictedType prediction)
+bool ByteCodeParser::handleIntrinsic(bool usesResult, int resultOperand, Intrinsic intrinsic, int registerOffset, int argumentCountIncludingThis, SpeculatedType prediction)
{
switch (intrinsic) {
case AbsIntrinsic: {
@@ -1482,7 +1511,7 @@ bool ByteCodeParser::handleIntrinsic(bool usesResult, int resultOperand, Intrins
return false;
int thisOperand = registerOffset + argumentToOperand(0);
- if (!(m_graph[get(thisOperand)].prediction() & PredictString))
+ if (!(m_graph[get(thisOperand)].prediction() & SpecString))
return false;
int indexOperand = registerOffset + argumentToOperand(1);
@@ -1499,7 +1528,7 @@ bool ByteCodeParser::handleIntrinsic(bool usesResult, int resultOperand, Intrins
return false;
int thisOperand = registerOffset + argumentToOperand(0);
- if (!(m_graph[get(thisOperand)].prediction() & PredictString))
+ if (!(m_graph[get(thisOperand)].prediction() & SpecString))
return false;
int indexOperand = registerOffset + argumentToOperand(1);
@@ -1538,6 +1567,80 @@ bool ByteCodeParser::handleIntrinsic(bool usesResult, int resultOperand, Intrins
}
}
+void ByteCodeParser::handleGetById(
+ int destinationOperand, SpeculatedType prediction, NodeIndex base, unsigned identifierNumber,
+ const GetByIdStatus& getByIdStatus)
+{
+ if (!getByIdStatus.isSimple()
+ || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache)) {
+ set(destinationOperand,
+ addToGraph(
+ getByIdStatus.makesCalls() ? GetByIdFlush : GetById,
+ OpInfo(identifierNumber), OpInfo(prediction), base));
+ return;
+ }
+
+ 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 == SpecNone)
+ addToGraph(ForceOSRExit);
+
+ NodeIndex originalBaseForBaselineJIT = base;
+
+ addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(getByIdStatus.structureSet())), base);
+
+ bool useInlineStorage;
+ if (!getByIdStatus.chain().isEmpty()) {
+ Structure* currentStructure = getByIdStatus.structureSet().singletonStructure();
+ JSObject* currentObject = 0;
+ for (unsigned i = 0; i < getByIdStatus.chain().size(); ++i) {
+ currentObject = asObject(currentStructure->prototypeForLookup(m_inlineStackTop->m_codeBlock));
+ currentStructure = getByIdStatus.chain()[i];
+ base = addStructureTransitionCheck(currentObject, currentStructure);
+ }
+ useInlineStorage = currentStructure->isUsingInlineStorage();
+ } else
+ useInlineStorage = getByIdStatus.structureSet().allAreUsingInlinePropertyStorage();
+
+ // Unless we want bugs like https://bugs.webkit.org/show_bug.cgi?id=88783, we need to
+ // ensure that the base of the original get_by_id is kept alive until we're done with
+ // all of the speculations. We only insert the Phantom if there had been a CheckStructure
+ // on something other than the base following the CheckStructure on base, or if the
+ // access was compiled to a WeakJSConstant specific value, in which case we might not
+ // have any explicit use of the base at all.
+ if (getByIdStatus.specificValue() || originalBaseForBaselineJIT != base)
+ addToGraph(Phantom, originalBaseForBaselineJIT);
+
+ if (getByIdStatus.specificValue()) {
+ ASSERT(getByIdStatus.specificValue().isCell());
+
+ set(destinationOperand, cellConstant(getByIdStatus.specificValue().asCell()));
+ return;
+ }
+
+ NodeIndex propertyStorage;
+ size_t offsetOffset;
+ if (useInlineStorage) {
+ propertyStorage = base;
+ ASSERT(!(sizeof(JSObject) % sizeof(EncodedJSValue)));
+ offsetOffset = sizeof(JSObject) / sizeof(EncodedJSValue);
+ } else {
+ propertyStorage = addToGraph(GetPropertyStorage, base);
+ offsetOffset = 0;
+ }
+ set(destinationOperand,
+ addToGraph(
+ GetByOffset, OpInfo(m_graph.m_storageAccessData.size()), OpInfo(prediction),
+ propertyStorage));
+
+ StorageAccessData storageAccessData;
+ storageAccessData.offset = getByIdStatus.offset() + offsetOffset;
+ storageAccessData.identifierNumber = identifierNumber;
+ m_graph.m_storageAccessData.append(storageAccessData);
+}
+
void ByteCodeParser::prepareToParseBlock()
{
for (unsigned i = 0; i < m_constants.size(); ++i)
@@ -1972,7 +2075,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
// === Property access operations ===
case op_get_by_val: {
- PredictedType prediction = getPrediction();
+ SpeculatedType prediction = getPrediction();
NodeIndex base = get(currentInstruction[2].u.operand);
NodeIndex property = get(currentInstruction[3].u.operand);
@@ -1997,7 +2100,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
m_currentProfilingIndex += OPCODE_LENGTH(op_method_check);
Instruction* getInstruction = currentInstruction + OPCODE_LENGTH(op_method_check);
- PredictedType prediction = getPrediction();
+ SpeculatedType prediction = getPrediction();
ASSERT(interpreter->getOpcodeID(getInstruction->u.opcode) == op_get_by_id);
@@ -2020,18 +2123,22 @@ bool ByteCodeParser::parseBlock(unsigned limit)
// but the slow path (i.e. the normal get_by_id) never fired.
addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(methodCallStatus.structure())), base);
- if (methodCallStatus.needsPrototypeCheck())
- addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(methodCallStatus.prototypeStructure())), cellConstant(methodCallStatus.prototype()));
-
+ if (methodCallStatus.needsPrototypeCheck()) {
+ addStructureTransitionCheck(
+ methodCallStatus.prototype(), methodCallStatus.prototypeStructure());
+ addToGraph(Phantom, base);
+ }
set(getInstruction[1].u.operand, cellConstant(methodCallStatus.function()));
- } else
- set(getInstruction[1].u.operand, addToGraph(getByIdStatus.makesCalls() ? GetByIdFlush : GetById, OpInfo(identifier), OpInfo(prediction), base));
+ } else {
+ handleGetById(
+ getInstruction[1].u.operand, prediction, base, identifier, getByIdStatus);
+ }
m_currentIndex += OPCODE_LENGTH(op_method_check) + OPCODE_LENGTH(op_get_by_id);
continue;
}
case op_get_scoped_var: {
- PredictedType prediction = getPrediction();
+ SpeculatedType prediction = getPrediction();
int dst = currentInstruction[1].u.operand;
int slot = currentInstruction[2].u.operand;
int depth = currentInstruction[3].u.operand;
@@ -2049,7 +2156,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
NEXT_OPCODE(op_put_scoped_var);
}
case op_get_by_id: {
- PredictedType prediction = getPredictionWithoutOSRExit();
+ SpeculatedType prediction = getPredictionWithoutOSRExit();
NodeIndex base = get(currentInstruction[2].u.operand);
unsigned identifierNumber = m_inlineStackTop->m_identifierRemap[currentInstruction[3].u.operand];
@@ -2058,34 +2165,8 @@ bool ByteCodeParser::parseBlock(unsigned limit)
GetByIdStatus getByIdStatus = GetByIdStatus::computeFor(
m_inlineStackTop->m_profiledBlock, m_currentIndex, identifier);
- if (getByIdStatus.isSimpleDirect()
- && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache)) {
- 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(getByIdStatus.structureSet())), base);
- NodeIndex propertyStorage;
- size_t offsetOffset;
- if (getByIdStatus.structureSet().allAreUsingInlinePropertyStorage()) {
- propertyStorage = base;
- ASSERT(!(sizeof(JSObject) % sizeof(EncodedJSValue)));
- offsetOffset = sizeof(JSObject) / sizeof(EncodedJSValue);
- } else {
- propertyStorage = addToGraph(GetPropertyStorage, base);
- offsetOffset = 0;
- }
- set(currentInstruction[1].u.operand, addToGraph(GetByOffset, OpInfo(m_graph.m_storageAccessData.size()), OpInfo(prediction), propertyStorage));
-
- StorageAccessData storageAccessData;
- storageAccessData.offset = getByIdStatus.offset() + offsetOffset;
- storageAccessData.identifierNumber = identifierNumber;
- m_graph.m_storageAccessData.append(storageAccessData);
- } else
- set(currentInstruction[1].u.operand, addToGraph(getByIdStatus.makesCalls() ? GetByIdFlush : GetById, OpInfo(identifierNumber), OpInfo(prediction), base));
+ handleGetById(
+ currentInstruction[1].u.operand, prediction, base, identifierNumber, getByIdStatus);
NEXT_OPCODE(op_get_by_id);
}
@@ -2134,23 +2215,20 @@ bool ByteCodeParser::parseBlock(unsigned limit)
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 (!putByIdStatus.oldStructure()->storedPrototype().isNull()) {
+ addStructureTransitionCheck(
+ putByIdStatus.oldStructure()->storedPrototype().asCell());
+ }
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()));
+ addStructureTransitionCheck(prototype.asCell());
}
}
+ ASSERT(putByIdStatus.oldStructure()->transitionWatchpointSetHasBeenInvalidated());
addToGraph(
PutStructure,
OpInfo(
@@ -2192,19 +2270,94 @@ bool ByteCodeParser::parseBlock(unsigned limit)
}
case op_get_global_var: {
- PredictedType prediction = getPrediction();
+ SpeculatedType prediction = getPrediction();
- NodeIndex getGlobalVar = addToGraph(GetGlobalVar, OpInfo(currentInstruction[2].u.operand), OpInfo(prediction));
+ JSGlobalObject* globalObject = m_inlineStackTop->m_codeBlock->globalObject();
+
+ NodeIndex getGlobalVar = addToGraph(
+ GetGlobalVar,
+ OpInfo(globalObject->assertRegisterIsInThisObject(currentInstruction[2].u.registerPointer)),
+ OpInfo(prediction));
set(currentInstruction[1].u.operand, getGlobalVar);
NEXT_OPCODE(op_get_global_var);
}
+
+ case op_get_global_var_watchable: {
+ SpeculatedType prediction = getPrediction();
+
+ JSGlobalObject* globalObject = m_inlineStackTop->m_codeBlock->globalObject();
+
+ unsigned identifierNumber = m_inlineStackTop->m_identifierRemap[currentInstruction[3].u.operand];
+ Identifier identifier = m_codeBlock->identifier(identifierNumber);
+ SymbolTableEntry entry = globalObject->symbolTable().get(identifier.impl());
+ if (!entry.couldBeWatched()) {
+ NodeIndex getGlobalVar = addToGraph(
+ GetGlobalVar,
+ OpInfo(globalObject->assertRegisterIsInThisObject(currentInstruction[2].u.registerPointer)),
+ OpInfo(prediction));
+ set(currentInstruction[1].u.operand, getGlobalVar);
+ NEXT_OPCODE(op_get_global_var_watchable);
+ }
+
+ // The watchpoint is still intact! This means that we will get notified if the
+ // current value in the global variable changes. So, we can inline that value.
+ // Moreover, currently we can assume that this value is a JSFunction*, which
+ // implies that it's a cell. This simplifies things, since in general we'd have
+ // to use a JSConstant for non-cells and a WeakJSConstant for cells. So instead
+ // of having both cases we just assert that the value is a cell.
+
+ // NB. If it wasn't for CSE, GlobalVarWatchpoint would have no need for the
+ // register pointer. But CSE tracks effects on global variables by comparing
+ // register pointers. Because CSE executes multiple times while the backend
+ // executes once, we use the following performance trade-off:
+ // - The node refers directly to the register pointer to make CSE super cheap.
+ // - To perform backend code generation, the node only contains the identifier
+ // number, from which it is possible to get (via a few average-time O(1)
+ // lookups) to the WatchpointSet.
+
+ addToGraph(
+ GlobalVarWatchpoint,
+ OpInfo(globalObject->assertRegisterIsInThisObject(currentInstruction[2].u.registerPointer)),
+ OpInfo(identifierNumber));
+
+ JSValue specificValue = globalObject->registerAt(entry.getIndex()).get();
+ ASSERT(specificValue.isCell());
+ set(currentInstruction[1].u.operand, cellConstant(specificValue.asCell()));
+
+ NEXT_OPCODE(op_get_global_var_watchable);
+ }
case op_put_global_var: {
NodeIndex value = get(currentInstruction[2].u.operand);
- addToGraph(PutGlobalVar, OpInfo(currentInstruction[1].u.operand), value);
+ addToGraph(
+ PutGlobalVar,
+ OpInfo(m_inlineStackTop->m_codeBlock->globalObject()->assertRegisterIsInThisObject(currentInstruction[1].u.registerPointer)),
+ value);
NEXT_OPCODE(op_put_global_var);
}
+ case op_put_global_var_check: {
+ NodeIndex value = get(currentInstruction[2].u.operand);
+ CodeBlock* codeBlock = m_inlineStackTop->m_codeBlock;
+ JSGlobalObject* globalObject = codeBlock->globalObject();
+ unsigned identifierNumber = m_inlineStackTop->m_identifierRemap[currentInstruction[4].u.operand];
+ Identifier identifier = m_codeBlock->identifier(identifierNumber);
+ SymbolTableEntry entry = globalObject->symbolTable().get(identifier.impl());
+ if (!entry.couldBeWatched()) {
+ addToGraph(
+ PutGlobalVar,
+ OpInfo(globalObject->assertRegisterIsInThisObject(currentInstruction[1].u.registerPointer)),
+ value);
+ NEXT_OPCODE(op_put_global_var_check);
+ }
+ addToGraph(
+ PutGlobalVarCheck,
+ OpInfo(codeBlock->globalObject()->assertRegisterIsInThisObject(currentInstruction[1].u.registerPointer)),
+ OpInfo(identifierNumber),
+ value);
+ NEXT_OPCODE(op_put_global_var_check);
+ }
+
// === Block terminators. ===
case op_jmp: {
@@ -2433,7 +2586,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
Instruction* putInstruction = currentInstruction + OPCODE_LENGTH(op_call_varargs);
- PredictedType prediction = PredictNone;
+ SpeculatedType prediction = SpecNone;
if (interpreter->getOpcodeID(putInstruction->u.opcode) == op_call_put_result) {
m_currentProfilingIndex = m_currentIndex + OPCODE_LENGTH(op_call_varargs);
prediction = getPrediction();
@@ -2471,7 +2624,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
LAST_OPCODE(op_jneq_ptr);
case op_resolve: {
- PredictedType prediction = getPrediction();
+ SpeculatedType prediction = getPrediction();
unsigned identifier = m_inlineStackTop->m_identifierRemap[currentInstruction[2].u.operand];
@@ -2482,7 +2635,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
}
case op_resolve_base: {
- PredictedType prediction = getPrediction();
+ SpeculatedType prediction = getPrediction();
unsigned identifier = m_inlineStackTop->m_identifierRemap[currentInstruction[2].u.operand];
@@ -2493,7 +2646,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
}
case op_resolve_global: {
- PredictedType prediction = getPrediction();
+ SpeculatedType prediction = getPrediction();
NodeIndex resolve = addToGraph(ResolveGlobal, OpInfo(m_graph.m_resolveGlobalData.size()), OpInfo(prediction));
m_graph.m_resolveGlobalData.append(ResolveGlobalData());
@@ -2747,7 +2900,7 @@ void ByteCodeParser::processPhiStack()
}
}
-void ByteCodeParser::fixVariableAccessPredictions()
+void ByteCodeParser::fixVariableAccessSpeculations()
{
for (unsigned i = 0; i < m_graph.m_variableAccessData.size(); ++i) {
VariableAccessData* data = &m_graph.m_variableAccessData[i];
@@ -2843,7 +2996,7 @@ ByteCodeParser::InlineStackEntry::InlineStackEntry(
, m_caller(byteCodeParser->m_inlineStackTop)
{
m_argumentPositions.resize(argumentCountIncludingThis);
- for (unsigned i = argumentCountIncludingThis; i--;) {
+ for (int i = 0; i < argumentCountIncludingThis; ++i) {
byteCodeParser->m_graph.m_argumentPositions.append(ArgumentPosition());
ArgumentPosition* argumentPosition = &byteCodeParser->m_graph.m_argumentPositions.last();
m_argumentPositions[i] = argumentPosition;
@@ -3073,7 +3226,7 @@ bool ByteCodeParser::parse()
m_graph.m_blocks[blockIndex].clear();
}
- fixVariableAccessPredictions();
+ fixVariableAccessSpeculations();
m_graph.m_preservedVars = m_preservedVars;
m_graph.m_localVars = m_numLocals;
diff --git a/Source/JavaScriptCore/dfg/DFGCCallHelpers.h b/Source/JavaScriptCore/dfg/DFGCCallHelpers.h
index dc3af636e..4cacd45c1 100644
--- a/Source/JavaScriptCore/dfg/DFGCCallHelpers.h
+++ b/Source/JavaScriptCore/dfg/DFGCCallHelpers.h
@@ -94,6 +94,12 @@ public:
addCallArgument(arg1);
addCallArgument(arg2);
}
+
+ ALWAYS_INLINE void setupArguments(TrustedImmPtr arg1)
+ {
+ resetCallArguments();
+ addCallArgument(arg1);
+ }
ALWAYS_INLINE void setupArgumentsExecState()
{
@@ -216,6 +222,15 @@ public:
addCallArgument(arg4);
}
+ ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, TrustedImmPtr arg2, GPRReg arg3)
+ {
+ resetCallArguments();
+ addCallArgument(GPRInfo::callFrameRegister);
+ addCallArgument(arg1);
+ addCallArgument(arg2);
+ addCallArgument(arg3);
+ }
+
ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, TrustedImmPtr arg4)
{
resetCallArguments();
@@ -424,6 +439,11 @@ public:
{
setupTwoStubArgs<GPRInfo::argumentGPR0, GPRInfo::argumentGPR1>(arg1, arg2);
}
+
+ ALWAYS_INLINE void setupArguments(TrustedImmPtr arg1)
+ {
+ move(arg1, GPRInfo::argumentGPR0);
+ }
ALWAYS_INLINE void setupArgumentsExecState()
{
@@ -554,6 +574,14 @@ public:
move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
}
+ ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, TrustedImmPtr arg2, GPRReg arg3)
+ {
+ move(arg3, GPRInfo::argumentGPR3);
+ move(arg1, GPRInfo::argumentGPR1);
+ move(arg2, GPRInfo::argumentGPR2);
+ move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+ }
+
ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, GPRReg arg2, TrustedImm32 arg3)
{
move(arg2, GPRInfo::argumentGPR2);
diff --git a/Source/JavaScriptCore/dfg/DFGCFGSimplificationPhase.cpp b/Source/JavaScriptCore/dfg/DFGCFGSimplificationPhase.cpp
index 0f0a22562..161f51e30 100644
--- a/Source/JavaScriptCore/dfg/DFGCFGSimplificationPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGCFGSimplificationPhase.cpp
@@ -288,7 +288,7 @@ private:
if (child.op() != GetLocal)
return;
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
- dataLog(" Considering GetLocal at @%u.\n", edge.index());
+ dataLog(" Considering GetLocal at @%u, local r%d.\n", edge.index(), child.local());
#endif
if (child.variableAccessData()->isCaptured()) {
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
@@ -302,6 +302,10 @@ private:
#endif
ASSERT(originalNodeIndex != NoNode);
Node* originalNode = &m_graph[originalNodeIndex];
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+ dataLog(" Original has local r%d.\n", originalNode->local());
+#endif
+ ASSERT(child.local() == originalNode->local());
if (changeRef)
ASSERT(originalNode->shouldGenerate());
// Possibilities:
@@ -389,7 +393,7 @@ private:
if (myNode.op() == GetLocal)
myNodeIndex = myNode.child1().index();
for (unsigned j = 0; j < AdjacencyList::Size; ++j)
- removePotentiallyDeadPhiReference(myNodeIndex, phiNode, j);
+ removePotentiallyDeadPhiReference(myNodeIndex, phiNode, j, sourceBlock->isReachable);
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
dataLog("\n");
#endif
@@ -414,14 +418,14 @@ private:
fixPhis(blockIndex, jettisonedBlockIndex);
}
- void removePotentiallyDeadPhiReference(NodeIndex myNodeIndex, Node& phiNode, unsigned edgeIndex)
+ void removePotentiallyDeadPhiReference(NodeIndex myNodeIndex, Node& phiNode, unsigned edgeIndex, bool changeRef)
{
if (phiNode.children.child(edgeIndex).indexUnchecked() != myNodeIndex)
return;
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
dataLog(" Removing reference at child %u.", edgeIndex);
#endif
- if (phiNode.shouldGenerate())
+ if (changeRef && phiNode.shouldGenerate())
m_graph.deref(myNodeIndex);
phiNode.children.removeEdgeFromBag(edgeIndex);
}
@@ -600,6 +604,8 @@ private:
NodeIndex nodeIndex = secondBlock->at(i);
Node& node = m_graph[nodeIndex];
+ bool childrenAlreadyFixed = false;
+
switch (node.op()) {
case Phantom: {
if (!node.child1())
@@ -611,8 +617,12 @@ private:
NodeIndex setLocalIndex =
firstBlock->variablesAtTail.operand(possibleLocalOp.local());
Node& setLocal = m_graph[setLocalIndex];
- if (setLocal.op() == SetLocal)
+ if (setLocal.op() == SetLocal) {
m_graph.changeEdge(node.children.child1(), setLocal.child1());
+ ASSERT(!node.child2());
+ ASSERT(!node.child3());
+ childrenAlreadyFixed = true;
+ }
}
break;
}
@@ -632,6 +642,19 @@ private:
NodeIndex atFirstIndex = firstBlock->variablesAtTail.operand(node.local());
m_graph.changeEdge(node.children.child1(), Edge(skipGetLocal(atFirstIndex)), node.shouldGenerate());
+ childrenAlreadyFixed = true;
+
+ if (node.op() != GetLocal)
+ break;
+
+ NodeIndex atFirstHeadIndex = firstBlock->variablesAtHead.operand(node.local());
+ if (atFirstHeadIndex == NoNode)
+ break;
+
+ if (m_graph[atFirstHeadIndex].op() != Phi)
+ break;
+
+ firstBlock->variablesAtHead.operand(node.local()) = nodeIndex;
break;
}
@@ -639,20 +662,22 @@ private:
break;
}
- bool changeRef = node.shouldGenerate();
+ if (!childrenAlreadyFixed) {
+ bool changeRef = node.shouldGenerate();
- // If the child is a GetLocal, then we might like to fix it.
- if (node.flags() & NodeHasVarArgs) {
- for (unsigned childIdx = node.firstChild();
- childIdx < node.firstChild() + node.numChildren();
- ++childIdx)
- fixPossibleGetLocal(firstBlock, m_graph.m_varArgChildren[childIdx], changeRef);
- } else if (!!node.child1()) {
- fixPossibleGetLocal(firstBlock, node.children.child1(), changeRef);
- if (!!node.child2()) {
- fixPossibleGetLocal(firstBlock, node.children.child2(), changeRef);
- if (!!node.child3())
- fixPossibleGetLocal(firstBlock, node.children.child3(), changeRef);
+ // If the child is a GetLocal, then we might like to fix it.
+ if (node.flags() & NodeHasVarArgs) {
+ for (unsigned childIdx = node.firstChild();
+ childIdx < node.firstChild() + node.numChildren();
+ ++childIdx)
+ fixPossibleGetLocal(firstBlock, m_graph.m_varArgChildren[childIdx], changeRef);
+ } else if (!!node.child1()) {
+ fixPossibleGetLocal(firstBlock, node.children.child1(), changeRef);
+ if (!!node.child2()) {
+ fixPossibleGetLocal(firstBlock, node.children.child2(), changeRef);
+ if (!!node.child3())
+ fixPossibleGetLocal(firstBlock, node.children.child3(), changeRef);
+ }
}
}
diff --git a/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp b/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp
index 31488cb1c..a362e6e97 100644
--- a/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp
@@ -48,9 +48,10 @@ public:
bool run()
{
+ m_changed = false;
for (unsigned block = 0; block < m_graph.m_blocks.size(); ++block)
performBlockCSE(m_graph.m_blocks[block].get());
- return true; // Maybe we'll need to make this reason about whether it changed the graph in an actionable way?
+ return m_changed;
}
private:
@@ -193,18 +194,18 @@ private:
return NoNode;
}
- NodeIndex globalVarLoadElimination(unsigned varNumber, JSGlobalObject* globalObject)
+ NodeIndex globalVarLoadElimination(WriteBarrier<Unknown>* registerPointer)
{
for (unsigned i = m_indexInBlock; i--;) {
NodeIndex index = m_currentBlock->at(i);
Node& node = m_graph[index];
switch (node.op()) {
case GetGlobalVar:
- if (node.varNumber() == varNumber && codeBlock()->globalObjectFor(node.codeOrigin) == globalObject)
+ if (node.registerPointer() == registerPointer)
return index;
break;
case PutGlobalVar:
- if (node.varNumber() == varNumber && codeBlock()->globalObjectFor(node.codeOrigin) == globalObject)
+ if (node.registerPointer() == registerPointer)
return node.child1().index();
break;
default:
@@ -216,7 +217,30 @@ private:
return NoNode;
}
- NodeIndex globalVarStoreElimination(unsigned varNumber, JSGlobalObject* globalObject)
+ bool globalVarWatchpointElimination(WriteBarrier<Unknown>* registerPointer)
+ {
+ for (unsigned i = m_indexInBlock; i--;) {
+ NodeIndex index = m_currentBlock->at(i);
+ Node& node = m_graph[index];
+ switch (node.op()) {
+ case GlobalVarWatchpoint:
+ if (node.registerPointer() == registerPointer)
+ return true;
+ break;
+ case PutGlobalVar:
+ if (node.registerPointer() == registerPointer)
+ return false;
+ break;
+ default:
+ break;
+ }
+ if (m_graph.clobbersWorld(index))
+ break;
+ }
+ return false;
+ }
+
+ NodeIndex globalVarStoreElimination(WriteBarrier<Unknown>* registerPointer)
{
for (unsigned i = m_indexInBlock; i--;) {
NodeIndex index = m_currentBlock->at(i);
@@ -225,12 +249,13 @@ private:
continue;
switch (node.op()) {
case PutGlobalVar:
- if (node.varNumber() == varNumber && codeBlock()->globalObjectFor(node.codeOrigin) == globalObject)
+ case PutGlobalVarCheck:
+ if (node.registerPointer() == registerPointer)
return index;
break;
case GetGlobalVar:
- if (node.varNumber() == varNumber && codeBlock()->globalObjectFor(node.codeOrigin) == globalObject)
+ if (node.registerPointer() == registerPointer)
return NoNode;
break;
@@ -316,6 +341,12 @@ private:
return true;
break;
+ case StructureTransitionWatchpoint:
+ if (node.child1() == child1
+ && structureSet.contains(node.structure()))
+ return true;
+ break;
+
case PutStructure:
if (node.child1() == child1
&& structureSet.contains(node.structureTransitionData().newStructure))
@@ -347,6 +378,53 @@ private:
return false;
}
+ bool structureTransitionWatchpointElimination(Structure* structure, NodeIndex child1)
+ {
+ for (unsigned i = m_indexInBlock; i--;) {
+ NodeIndex index = m_currentBlock->at(i);
+ if (index == child1)
+ break;
+
+ Node& node = m_graph[index];
+ switch (node.op()) {
+ case CheckStructure:
+ if (node.child1() == child1
+ && node.structureSet().containsOnly(structure))
+ return true;
+ break;
+
+ case PutStructure:
+ ASSERT(node.structureTransitionData().previousStructure != structure);
+ break;
+
+ case PutByOffset:
+ // Setting a property cannot change the structure.
+ break;
+
+ case PutByVal:
+ case PutByValAlias:
+ if (m_graph.byValIsPure(node)) {
+ // If PutByVal speculates that it's accessing an array with an
+ // integer index, then it's impossible for it to cause a structure
+ // change.
+ break;
+ }
+ return false;
+
+ case StructureTransitionWatchpoint:
+ if (node.structure() == structure && node.child1() == child1)
+ return true;
+ break;
+
+ default:
+ if (m_graph.clobbersWorld(index))
+ return false;
+ break;
+ }
+ }
+ return false;
+ }
+
NodeIndex putStructureStoreElimination(NodeIndex child1)
{
for (unsigned i = m_indexInBlock; i--;) {
@@ -538,8 +616,8 @@ private:
Node& node = m_graph[index];
switch (node.op()) {
case GetIndexedPropertyStorage: {
- PredictedType basePrediction = m_graph[node.child2()].prediction();
- bool nodeHasIntegerIndexPrediction = !(!(basePrediction & PredictInt32) && basePrediction);
+ SpeculatedType basePrediction = m_graph[node.child2()].prediction();
+ bool nodeHasIntegerIndexPrediction = !(!(basePrediction & SpecInt32) && basePrediction);
if (node.child1() == child1 && hasIntegerIndexPrediction == nodeHasIntegerIndexPrediction)
return index;
break;
@@ -556,7 +634,7 @@ private:
break;
case PutByVal:
- if (isFixedIndexedStorageObjectPrediction(m_graph[node.child1()].prediction()) && m_graph.byValIsPure(node))
+ if (isFixedIndexedStorageObjectSpeculation(m_graph[node.child1()].prediction()) && m_graph.byValIsPure(node))
break;
return NoNode;
@@ -619,9 +697,22 @@ private:
return NoNode;
}
- // This returns the Flush node that is keeping a SetLocal alive.
- NodeIndex setLocalStoreElimination(VirtualRegister local, NodeIndex expectedNodeIndex)
+ struct SetLocalStoreEliminationResult {
+ SetLocalStoreEliminationResult()
+ : mayBeAccessed(false)
+ , mayExit(false)
+ , mayClobberWorld(false)
+ {
+ }
+
+ bool mayBeAccessed;
+ bool mayExit;
+ bool mayClobberWorld;
+ };
+ SetLocalStoreEliminationResult setLocalStoreElimination(
+ VirtualRegister local, NodeIndex expectedNodeIndex)
{
+ SetLocalStoreEliminationResult result;
for (unsigned i = m_indexInBlock; i--;) {
NodeIndex index = m_currentBlock->at(i);
Node& node = m_graph[index];
@@ -631,46 +722,67 @@ private:
case GetLocal:
case Flush:
if (node.local() == local)
- return NoNode;
+ result.mayBeAccessed = true;
break;
case GetLocalUnlinked:
if (node.unlinkedLocal() == local)
- return NoNode;
+ result.mayBeAccessed = true;
break;
case SetLocal: {
if (node.local() != local)
break;
if (index != expectedNodeIndex)
- return NoNode;
+ result.mayBeAccessed = true;
if (m_graph[index].refCount() > 1)
- return NoNode;
- return index;
+ result.mayBeAccessed = true;
+ return result;
}
case GetScopeChain:
if (m_graph.uncheckedActivationRegisterFor(node.codeOrigin) == local)
- return NoNode;
+ result.mayBeAccessed = true;
+ break;
+
+ case CheckArgumentsNotCreated:
+ case GetMyArgumentsLength:
+ case GetMyArgumentsLengthSafe:
+ if (m_graph.uncheckedArgumentsRegisterFor(node.codeOrigin) == local)
+ result.mayBeAccessed = true;
+ break;
+
+ case GetMyArgumentByVal:
+ case GetMyArgumentByValSafe:
+ result.mayBeAccessed = true;
+ break;
+
+ case GetByVal:
+ // If this is accessing arguments then it's potentially accessing locals.
+ if (m_graph[node.child1()].shouldSpeculateArguments())
+ result.mayBeAccessed = true;
break;
+ case CreateArguments:
case TearOffActivation:
case TearOffArguments:
// If an activation is being torn off then it means that captured variables
// are live. We could be clever here and check if the local qualifies as an
// argument register. But that seems like it would buy us very little since
// any kind of tear offs are rare to begin with.
- return NoNode;
+ result.mayBeAccessed = true;
+ break;
default:
- if (m_graph.clobbersWorld(index))
- return NoNode;
break;
}
- if (node.canExit())
- return NoNode;
+ result.mayExit |= node.canExit();
+ result.mayClobberWorld |= m_graph.clobbersWorld(index);
}
- return NoNode;
+ ASSERT_NOT_REACHED();
+ // Be safe in release mode.
+ result.mayBeAccessed = true;
+ return result;
}
void performSubstitution(Edge& child, bool addRef = true)
@@ -848,35 +960,64 @@ private:
m_graph.ref(phiIndex);
}
}
+ m_changed = true;
break;
}
case GetLocalUnlinked: {
NodeIndex relevantLocalOpIgnored;
- setReplacement(getLocalLoadElimination(node.unlinkedLocal(), relevantLocalOpIgnored));
+ m_changed |= setReplacement(getLocalLoadElimination(node.unlinkedLocal(), relevantLocalOpIgnored));
break;
}
case Flush: {
- if (m_fixpointState == FixpointNotConverged)
- break;
VariableAccessData* variableAccessData = node.variableAccessData();
- if (!variableAccessData->isCaptured())
- break;
VirtualRegister local = variableAccessData->local();
- NodeIndex replacementIndex = setLocalStoreElimination(local, node.child1().index());
- if (replacementIndex == NoNode)
- break;
+ NodeIndex replacementIndex = node.child1().index();
Node& replacement = m_graph[replacementIndex];
+ if (replacement.op() != SetLocal)
+ break;
+ ASSERT(replacement.variableAccessData() == variableAccessData);
+ // FIXME: We should be able to remove SetLocals that can exit; we just need
+ // to replace them with appropriate type checks.
+ if (m_fixpointState == FixpointNotConverged) {
+ // Need to be conservative at this time; if the SetLocal has any chance of performing
+ // any speculations then we cannot do anything.
+ if (variableAccessData->isCaptured()) {
+ // Captured SetLocals never speculate and hence never exit.
+ } else {
+ if (variableAccessData->shouldUseDoubleFormat())
+ break;
+ SpeculatedType prediction = variableAccessData->argumentAwarePrediction();
+ if (isInt32Speculation(prediction))
+ break;
+ if (isArraySpeculation(prediction))
+ break;
+ if (isBooleanSpeculation(prediction))
+ break;
+ }
+ } else {
+ if (replacement.canExit())
+ break;
+ }
+ SetLocalStoreEliminationResult result =
+ setLocalStoreElimination(local, replacementIndex);
+ if (result.mayBeAccessed || result.mayClobberWorld)
+ break;
ASSERT(replacement.op() == SetLocal);
ASSERT(replacement.refCount() == 1);
ASSERT(replacement.shouldGenerate());
+ // FIXME: Investigate using mayExit as a further optimization.
node.setOpAndDefaultFlags(Phantom);
NodeIndex dataNodeIndex = replacement.child1().index();
ASSERT(m_graph[dataNodeIndex].hasResult());
m_graph.clearAndDerefChild1(node);
node.children.child1() = Edge(dataNodeIndex);
m_graph.ref(dataNodeIndex);
+ NodeIndex oldTailIndex = m_currentBlock->variablesAtTail.operand(local);
+ if (oldTailIndex == m_compileIndex)
+ m_currentBlock->variablesAtTail.operand(local) = replacementIndex;
+ m_changed = true;
break;
}
@@ -918,13 +1059,19 @@ private:
// Finally handle heap accesses. These are not quite pure, but we can still
// optimize them provided that some subtle conditions are met.
case GetGlobalVar:
- setReplacement(globalVarLoadElimination(node.varNumber(), codeBlock()->globalObjectFor(node.codeOrigin)));
+ setReplacement(globalVarLoadElimination(node.registerPointer()));
+ break;
+
+ case GlobalVarWatchpoint:
+ if (globalVarWatchpointElimination(node.registerPointer()))
+ eliminate();
break;
case PutGlobalVar:
+ case PutGlobalVarCheck:
if (m_fixpointState == FixpointNotConverged)
break;
- eliminate(globalVarStoreElimination(node.varNumber(), codeBlock()->globalObjectFor(node.codeOrigin)));
+ eliminate(globalVarStoreElimination(node.registerPointer()));
break;
case GetByVal:
@@ -944,6 +1091,11 @@ private:
eliminate();
break;
+ case StructureTransitionWatchpoint:
+ if (structureTransitionWatchpointElimination(node.structure(), node.child1().index()))
+ eliminate();
+ break;
+
case PutStructure:
if (m_fixpointState == FixpointNotConverged)
break;
@@ -956,8 +1108,8 @@ private:
break;
case GetIndexedPropertyStorage: {
- PredictedType basePrediction = m_graph[node.child2()].prediction();
- bool nodeHasIntegerIndexPrediction = !(!(basePrediction & PredictInt32) && basePrediction);
+ SpeculatedType basePrediction = m_graph[node.child2()].prediction();
+ bool nodeHasIntegerIndexPrediction = !(!(basePrediction & SpecInt32) && basePrediction);
setReplacement(getIndexedPropertyStorageLoadElimination(node.child1().index(), nodeHasIntegerIndexPrediction));
break;
}
@@ -1010,6 +1162,7 @@ private:
Vector<NodeIndex, 16> m_replacements;
FixedArray<unsigned, LastNodeType> m_lastSeen;
OptimizationFixpointState m_fixpointState;
+ bool m_changed; // Only tracks changes that have a substantive effect on other optimizations.
};
bool performCSE(Graph& graph, OptimizationFixpointState fixpointState)
diff --git a/Source/JavaScriptCore/dfg/DFGCapabilities.h b/Source/JavaScriptCore/dfg/DFGCapabilities.h
index 694e886ee..027b0f78b 100644
--- a/Source/JavaScriptCore/dfg/DFGCapabilities.h
+++ b/Source/JavaScriptCore/dfg/DFGCapabilities.h
@@ -123,7 +123,9 @@ inline CapabilityLevel canCompileOpcode(OpcodeID opcodeID, CodeBlock*, Instructi
case op_put_by_id_transition_direct:
case op_put_by_id_transition_normal:
case op_get_global_var:
+ case op_get_global_var_watchable:
case op_put_global_var:
+ case op_put_global_var_check:
case op_jmp:
case op_loop:
case op_jtrue:
diff --git a/Source/JavaScriptCore/dfg/DFGCommon.h b/Source/JavaScriptCore/dfg/DFGCommon.h
index b2e3bb4ee..fce76c68c 100644
--- a/Source/JavaScriptCore/dfg/DFGCommon.h
+++ b/Source/JavaScriptCore/dfg/DFGCommon.h
@@ -55,6 +55,8 @@
#else
#define DFG_ENABLE_VALIDATION 0
#endif
+// Enable validation on completion of each phase.
+#define DFG_ENABLE_PER_PHASE_VALIDATION 0
// Consistency check contents compiler data structures.
#define DFG_ENABLE_CONSISTENCY_CHECK 0
// Emit a breakpoint into the head of every generated function, to aid debugging in GDB.
diff --git a/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp b/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp
index 1e75ddea1..9e6720c80 100644
--- a/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp
@@ -56,15 +56,44 @@ public:
continue;
if (!block->cfaFoundConstants)
continue;
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+ dataLog("Constant folding considering Block #%u.\n", blockIndex);
+#endif
state.beginBasicBlock(block);
for (unsigned indexInBlock = 0; indexInBlock < block->size(); ++indexInBlock) {
if (!state.isValid())
break;
- state.execute(indexInBlock);
NodeIndex nodeIndex = block->at(indexInBlock);
Node& node = m_graph[nodeIndex];
+
+ bool eliminated = false;
+
+ switch (node.op()) {
+ case CheckArgumentsNotCreated: {
+ if (!isEmptySpeculation(
+ state.variables().operand(
+ m_graph.argumentsRegisterFor(node.codeOrigin)).m_type))
+ break;
+ ASSERT(node.refCount() == 1);
+ node.setOpAndDefaultFlags(Phantom);
+ eliminated = true;
+ break;
+ }
+
+ // FIXME: This would be a great place to remove CheckStructure's.
+
+ default:
+ break;
+ }
+
+ if (eliminated) {
+ changed = true;
+ continue;
+ }
+
+ state.execute(indexInBlock);
if (!node.shouldGenerate()
- || m_graph.clobbersWorld(node)
+ || state.didClobber()
|| node.hasConstant())
continue;
JSValue value = state.forNode(nodeIndex).value();
@@ -74,11 +103,9 @@ public:
Node phantom(Phantom, node.codeOrigin);
if (node.op() == GetLocal) {
- ASSERT(m_graph[node.child1()].op() == Phi);
- ASSERT(!m_graph[node.child1()].hasResult());
-
NodeIndex previousLocalAccess = NoNode;
- if (block->variablesAtHead.operand(node.local()) == nodeIndex) {
+ if (block->variablesAtHead.operand(node.local()) == nodeIndex
+ && m_graph[node.child1()].op() == Phi) {
// We expect this to be the common case.
ASSERT(block->isInPhis(node.child1().index()));
previousLocalAccess = node.child1().index();
@@ -86,7 +113,7 @@ public:
} else {
ASSERT(indexInBlock > 0);
// Must search for the previous access to this local.
- for (BlockIndex subIndexInBlock = indexInBlock - 1; subIndexInBlock--;) {
+ for (BlockIndex subIndexInBlock = indexInBlock; subIndexInBlock--;) {
NodeIndex subNodeIndex = block->at(subIndexInBlock);
Node& subNode = m_graph[subNodeIndex];
if (!subNode.shouldGenerate())
@@ -97,13 +124,6 @@ public:
continue;
// The two must have been unified.
ASSERT(subNode.variableAccessData() == node.variableAccessData());
- // Currently, the previous node must be a flush.
- // NOTE: This assertion should be removed if we ever do
- // constant folding on captured variables. In particular,
- // this code does not require the previous node to be a flush,
- // but we are asserting this anyway because it is a constraint
- // of the IR and this is as good a place as any to assert it.
- ASSERT(subNode.op() == Flush);
previousLocalAccess = subNodeIndex;
break;
}
diff --git a/Source/JavaScriptCore/dfg/DFGCorrectableJumpPoint.h b/Source/JavaScriptCore/dfg/DFGCorrectableJumpPoint.h
index bfa149604..93cb49c01 100644
--- a/Source/JavaScriptCore/dfg/DFGCorrectableJumpPoint.h
+++ b/Source/JavaScriptCore/dfg/DFGCorrectableJumpPoint.h
@@ -66,6 +66,11 @@ public:
#endif
}
+ bool isSet()
+ {
+ return m_codeOffset != std::numeric_limits<uint32_t>::max();
+ }
+
void switchToLateJump(MacroAssembler::PatchableJump check)
{
#ifndef NDEBUG
diff --git a/Source/JavaScriptCore/dfg/DFGDriver.cpp b/Source/JavaScriptCore/dfg/DFGDriver.cpp
index 6ebe338f5..e932792df 100644
--- a/Source/JavaScriptCore/dfg/DFGDriver.cpp
+++ b/Source/JavaScriptCore/dfg/DFGDriver.cpp
@@ -82,10 +82,11 @@ inline bool compile(CompileMode compileMode, ExecState* exec, CodeBlock* codeBlo
changed |= performConstantFolding(dfg);
changed |= performArgumentsSimplification(dfg);
changed |= performCFGSimplification(dfg);
+ changed |= performCSE(dfg, FixpointNotConverged);
if (!changed)
break;
- performCSE(dfg, FixpointNotConverged);
dfg.resetExitStates();
+ performFixup(dfg);
}
performCSE(dfg, FixpointConverged);
#if DFG_ENABLE(DEBUG_VERBOSE)
@@ -94,10 +95,13 @@ inline bool compile(CompileMode compileMode, ExecState* exec, CodeBlock* codeBlo
dfg.m_dominators.compute(dfg);
performVirtualRegisterAllocation(dfg);
+ GraphDumpMode modeForFinalValidate = DumpGraph;
#if DFG_ENABLE(DEBUG_VERBOSE)
dataLog("Graph after optimization:\n");
dfg.dump();
+ modeForFinalValidate = DontDumpGraph;
#endif
+ validate(dfg, modeForFinalValidate);
JITCompiler dataFlowJIT(dfg);
bool result;
diff --git a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
index e54d2cfaf..f6e3c0a96 100644
--- a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
@@ -74,13 +74,13 @@ private:
switch (op) {
case GetById: {
- if (!isInt32Prediction(m_graph[m_compileIndex].prediction()))
+ if (!isInt32Speculation(m_graph[m_compileIndex].prediction()))
break;
if (codeBlock()->identifier(node.identifierNumber()) != globalData().propertyNames->length)
break;
- bool isArray = isArrayPrediction(m_graph[node.child1()].prediction());
- bool isArguments = isArgumentsPrediction(m_graph[node.child1()].prediction());
- bool isString = isStringPrediction(m_graph[node.child1()].prediction());
+ bool isArray = isArraySpeculation(m_graph[node.child1()].prediction());
+ bool isArguments = isArgumentsSpeculation(m_graph[node.child1()].prediction());
+ bool isString = isStringSpeculation(m_graph[node.child1()].prediction());
bool isInt8Array = m_graph[node.child1()].shouldSpeculateInt8Array();
bool isInt16Array = m_graph[node.child1()].shouldSpeculateInt16Array();
bool isInt32Array = m_graph[node.child1()].shouldSpeculateInt32Array();
@@ -129,10 +129,10 @@ private:
break;
}
case GetIndexedPropertyStorage: {
- PredictedType basePrediction = m_graph[node.child2()].prediction();
- if ((!(basePrediction & PredictInt32) && basePrediction)
+ SpeculatedType basePrediction = m_graph[node.child2()].prediction();
+ if ((!(basePrediction & SpecInt32) && basePrediction)
|| m_graph[node.child1()].shouldSpeculateArguments()
- || !isActionableArrayPrediction(m_graph[node.child1()].prediction())) {
+ || !isActionableArraySpeculation(m_graph[node.child1()].prediction())) {
node.setOpAndDefaultFlags(Nop);
m_graph.clearAndDerefChild1(node);
m_graph.clearAndDerefChild2(node);
@@ -150,7 +150,8 @@ private:
}
case ValueToInt32: {
- if (m_graph[node.child1()].shouldSpeculateNumber()) {
+ if (m_graph[node.child1()].shouldSpeculateNumber()
+ && node.mustGenerate()) {
node.clearFlags(NodeMustGenerate);
m_graph.deref(m_compileIndex);
}
@@ -284,7 +285,7 @@ private:
Node newDivision = oldDivision;
newDivision.setRefCount(2);
- newDivision.predict(PredictDouble);
+ newDivision.predict(SpecDouble);
NodeIndex newDivisionIndex = m_graph.size();
oldDivision.setOp(DoubleAsInt32);
@@ -318,7 +319,7 @@ private:
break;
if (!m_graph[node.child2()].shouldSpeculateInteger())
break;
- if (isActionableIntMutableArrayPrediction(m_graph[node.child1()].prediction())) {
+ if (isActionableIntMutableArraySpeculation(m_graph[node.child1()].prediction())) {
if (m_graph[node.child3()].isConstant())
break;
if (m_graph[node.child3()].shouldSpeculateInteger())
@@ -326,7 +327,7 @@ private:
fixDoubleEdge(2);
break;
}
- if (isActionableFloatMutableArrayPrediction(m_graph[node.child1()].prediction())) {
+ if (isActionableFloatMutableArraySpeculation(m_graph[node.child1()].prediction())) {
fixDoubleEdge(2);
break;
}
@@ -390,7 +391,7 @@ private:
m_insertionSet.append(m_indexInBlock, resultIndex);
Node& int32ToDouble = m_graph[resultIndex];
- int32ToDouble.predict(PredictDouble);
+ int32ToDouble.predict(SpecDouble);
int32ToDouble.ref();
}
diff --git a/Source/JavaScriptCore/dfg/DFGGraph.cpp b/Source/JavaScriptCore/dfg/DFGGraph.cpp
index 4562e30ee..93de024d7 100644
--- a/Source/JavaScriptCore/dfg/DFGGraph.cpp
+++ b/Source/JavaScriptCore/dfg/DFGGraph.cpp
@@ -76,7 +76,7 @@ const char* Graph::nameOfVariableAccessData(VariableAccessData* variableAccessDa
if (variableAccessData->isCaptured())
*ptr++ = '*';
- ptr.strcat(predictionToAbbreviatedString(variableAccessData->prediction()));
+ ptr.strcat(speculationToAbbreviatedString(variableAccessData->prediction()));
*ptr++ = 0;
@@ -169,7 +169,7 @@ void Graph::dump(NodeIndex nodeIndex)
dataLog("%s@%u%s",
useKindToString(m_varArgChildren[childIdx].useKind()),
m_varArgChildren[childIdx].index(),
- predictionToAbbreviatedString(
+ speculationToAbbreviatedString(
at(m_varArgChildren[childIdx]).prediction()));
}
} else {
@@ -177,19 +177,19 @@ void Graph::dump(NodeIndex nodeIndex)
dataLog("%s@%u%s",
useKindToString(node.child1().useKind()),
node.child1().index(),
- predictionToAbbreviatedString(at(node.child1()).prediction()));
+ speculationToAbbreviatedString(at(node.child1()).prediction()));
}
if (!!node.child2()) {
dataLog(", %s@%u%s",
useKindToString(node.child2().useKind()),
node.child2().index(),
- predictionToAbbreviatedString(at(node.child2()).prediction()));
+ speculationToAbbreviatedString(at(node.child2()).prediction()));
}
if (!!node.child3()) {
dataLog(", %s@%u%s",
useKindToString(node.child3().useKind()),
node.child3().index(),
- predictionToAbbreviatedString(at(node.child3()).prediction()));
+ speculationToAbbreviatedString(at(node.child3()).prediction()));
}
hasPrinted = !!node.child1();
}
@@ -202,6 +202,13 @@ void Graph::dump(NodeIndex nodeIndex)
dataLog("%svar%u", hasPrinted ? ", " : "", node.varNumber());
hasPrinted = true;
}
+ if (node.hasRegisterPointer()) {
+ dataLog(
+ "%sglobal%u(%p)", hasPrinted ? ", " : "",
+ globalObjectFor(node.codeOrigin)->findRegisterIndex(node.registerPointer()),
+ node.registerPointer());
+ hasPrinted = true;
+ }
if (node.hasIdentifier()) {
dataLog("%sid%u{%s}", hasPrinted ? ", " : "", node.identifierNumber(), m_codeBlock->identifier(node.identifierNumber()).ustring().utf8().data());
hasPrinted = true;
@@ -212,6 +219,10 @@ void Graph::dump(NodeIndex nodeIndex)
hasPrinted = true;
}
}
+ if (node.hasStructure()) {
+ dataLog("%sstruct(%p)", hasPrinted ? ", " : "", node.structure());
+ hasPrinted = true;
+ }
if (node.hasStructureTransitionData()) {
dataLog("%sstruct(%p -> %p)", hasPrinted ? ", " : "", node.structureTransitionData().previousStructure, node.structureTransitionData().newStructure);
hasPrinted = true;
@@ -269,9 +280,9 @@ void Graph::dump(NodeIndex nodeIndex)
if (!skipped) {
if (node.hasVariableAccessData())
- dataLog(" predicting %s, double ratio %lf%s", predictionToString(node.variableAccessData()->prediction()), node.variableAccessData()->doubleVoteRatio(), node.variableAccessData()->shouldUseDoubleFormat() ? ", forcing double" : "");
+ dataLog(" predicting %s, double ratio %lf%s", speculationToString(node.variableAccessData()->prediction()), node.variableAccessData()->doubleVoteRatio(), node.variableAccessData()->shouldUseDoubleFormat() ? ", forcing double" : "");
else if (node.hasHeapPrediction())
- dataLog(" predicting %s", predictionToString(node.getHeapPrediction()));
+ dataLog(" predicting %s", speculationToString(node.getHeapPrediction()));
}
dataLog("\n");
@@ -386,7 +397,7 @@ void Graph::predictArgumentTypes()
at(m_arguments[arg]).variableAccessData()->predict(profile->computeUpdatedPrediction());
#if DFG_ENABLE(DEBUG_VERBOSE)
- dataLog("Argument [%zu] prediction: %s\n", arg, predictionToString(at(m_arguments[arg]).variableAccessData()->prediction()));
+ dataLog("Argument [%zu] prediction: %s\n", arg, speculationToString(at(m_arguments[arg]).variableAccessData()->prediction()));
#endif
}
}
diff --git a/Source/JavaScriptCore/dfg/DFGGraph.h b/Source/JavaScriptCore/dfg/DFGGraph.h
index 8ca3e2047..acc9ff472 100644
--- a/Source/JavaScriptCore/dfg/DFGGraph.h
+++ b/Source/JavaScriptCore/dfg/DFGGraph.h
@@ -187,9 +187,9 @@ public:
BlockIndex blockIndexForBytecodeOffset(Vector<BlockIndex>& blocks, unsigned bytecodeBegin);
- PredictedType getJSConstantPrediction(Node& node)
+ SpeculatedType getJSConstantSpeculation(Node& node)
{
- return predictionFromValue(node.valueOfJSConstant(m_codeBlock));
+ return speculationFromValue(node.valueOfJSConstant(m_codeBlock));
}
bool addShouldSpeculateInteger(Node& add)
@@ -258,6 +258,13 @@ public:
{
return at(nodeIndex).isBooleanConstant(m_codeBlock);
}
+ bool isCellConstant(NodeIndex nodeIndex)
+ {
+ if (!isJSConstant(nodeIndex))
+ return false;
+ JSValue value = valueOfJSConstant(nodeIndex);
+ return value.isCell() && !!value;
+ }
bool isFunctionConstant(NodeIndex nodeIndex)
{
if (!isJSConstant(nodeIndex))
@@ -310,6 +317,11 @@ public:
return &m_structureTransitionData.last();
}
+ JSGlobalObject* globalObjectFor(CodeOrigin codeOrigin)
+ {
+ return m_codeBlock->globalObjectFor(codeOrigin);
+ }
+
ExecutableBase* executableFor(InlineCallFrame* inlineCallFrame)
{
if (!inlineCallFrame)
@@ -424,17 +436,17 @@ public:
bool isPredictedNumerical(Node& node)
{
- PredictedType left = at(node.child1()).prediction();
- PredictedType right = at(node.child2()).prediction();
- return isNumberPrediction(left) && isNumberPrediction(right);
+ SpeculatedType left = at(node.child1()).prediction();
+ SpeculatedType right = at(node.child2()).prediction();
+ return isNumberSpeculation(left) && isNumberSpeculation(right);
}
bool byValIsPure(Node& node)
{
return at(node.child2()).shouldSpeculateInteger()
&& ((node.op() == PutByVal || node.op() == PutByValAlias)
- ? isActionableMutableArrayPrediction(at(node.child1()).prediction())
- : isActionableArrayPrediction(at(node.child1()).prediction()));
+ ? isActionableMutableArraySpeculation(at(node.child1()).prediction())
+ : isActionableArraySpeculation(at(node.child1()).prediction()));
}
bool clobbersWorld(Node& node)
diff --git a/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp b/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp
index 54b5aaee6..561f51615 100644
--- a/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp
+++ b/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp
@@ -44,7 +44,11 @@ void JITCompiler::linkOSRExits()
{
for (unsigned i = 0; i < codeBlock()->numberOfOSRExits(); ++i) {
OSRExit& exit = codeBlock()->osrExit(i);
- exit.m_check.initialJump().link(this);
+ ASSERT(!exit.m_check.isSet() == (exit.m_watchpointIndex != std::numeric_limits<unsigned>::max()));
+ if (exit.m_watchpointIndex == std::numeric_limits<unsigned>::max())
+ exit.m_check.initialJump().link(this);
+ else
+ codeBlock()->watchpoint(exit.m_watchpointIndex).setDestination(label());
jitAssertHasValidCallFrame();
store32(TrustedImm32(i), &globalData()->osrExitIndex);
exit.m_check.switchToLateJump(patchableJump());
@@ -124,16 +128,14 @@ void JITCompiler::link(LinkBuffer& linkBuffer)
for (unsigned i = 0; i < m_calls.size(); ++i)
linkBuffer.link(m_calls[i].m_call, m_calls[i].m_function);
- if (m_codeBlock->needsCallReturnIndices()) {
- m_codeBlock->callReturnIndexVector().reserveCapacity(m_exceptionChecks.size());
- for (unsigned i = 0; i < m_exceptionChecks.size(); ++i) {
- unsigned returnAddressOffset = linkBuffer.returnAddressOffset(m_exceptionChecks[i].m_call);
- CodeOrigin codeOrigin = m_exceptionChecks[i].m_codeOrigin;
- while (codeOrigin.inlineCallFrame)
- codeOrigin = codeOrigin.inlineCallFrame->caller;
- unsigned exceptionInfo = codeOrigin.bytecodeIndex;
- m_codeBlock->callReturnIndexVector().append(CallReturnOffsetToBytecodeOffset(returnAddressOffset, exceptionInfo));
- }
+ m_codeBlock->callReturnIndexVector().reserveCapacity(m_exceptionChecks.size());
+ for (unsigned i = 0; i < m_exceptionChecks.size(); ++i) {
+ unsigned returnAddressOffset = linkBuffer.returnAddressOffset(m_exceptionChecks[i].m_call);
+ CodeOrigin codeOrigin = m_exceptionChecks[i].m_codeOrigin;
+ while (codeOrigin.inlineCallFrame)
+ codeOrigin = codeOrigin.inlineCallFrame->caller;
+ unsigned exceptionInfo = codeOrigin.bytecodeIndex;
+ m_codeBlock->callReturnIndexVector().append(CallReturnOffsetToBytecodeOffset(returnAddressOffset, exceptionInfo));
}
Vector<CodeOriginAtCallReturnOffset>& codeOrigins = m_codeBlock->codeOrigins();
@@ -190,6 +192,8 @@ void JITCompiler::link(LinkBuffer& linkBuffer)
OSRExit& exit = codeBlock()->osrExit(i);
linkBuffer.link(exit.m_check.lateJump(), target);
exit.m_check.correctLateJump(linkBuffer);
+ if (exit.m_watchpointIndex != std::numeric_limits<unsigned>::max())
+ codeBlock()->watchpoint(exit.m_watchpointIndex).correctLabels(linkBuffer);
}
codeBlock()->shrinkToFit(CodeBlock::LateShrink);
@@ -216,7 +220,9 @@ bool JITCompiler::compile(JITCode& entry)
link(linkBuffer);
speculative.linkOSREntries(linkBuffer);
- entry = JITCode(linkBuffer.finalizeCode(), JITCode::DFGJIT);
+ entry = JITCode(
+ FINALIZE_CODE(linkBuffer, ("DFG program/eval CodeBlock %p", m_codeBlock)),
+ JITCode::DFGJIT);
return true;
}
@@ -298,7 +304,9 @@ bool JITCompiler::compileFunction(JITCode& entry, MacroAssemblerCodePtr& entryWi
linkBuffer.link(callArityCheck, m_codeBlock->m_isConstructor ? cti_op_construct_arityCheck : cti_op_call_arityCheck);
entryWithArityCheck = linkBuffer.locationOf(arityCheck);
- entry = JITCode(linkBuffer.finalizeCode(), JITCode::DFGJIT);
+ entry = JITCode(
+ FINALIZE_CODE(linkBuffer, ("DFG function CodeBlock %p", m_codeBlock)),
+ JITCode::DFGJIT);
return true;
}
diff --git a/Source/JavaScriptCore/dfg/DFGJITCompiler.h b/Source/JavaScriptCore/dfg/DFGJITCompiler.h
index d3ff3be07..9d69ec9f3 100644
--- a/Source/JavaScriptCore/dfg/DFGJITCompiler.h
+++ b/Source/JavaScriptCore/dfg/DFGJITCompiler.h
@@ -260,9 +260,9 @@ public:
}
// Helper methods to get predictions
- PredictedType getPrediction(Node& node) { return node.prediction(); }
- PredictedType getPrediction(NodeIndex nodeIndex) { return getPrediction(graph()[nodeIndex]); }
- PredictedType getPrediction(Edge nodeUse) { return getPrediction(nodeUse.index()); }
+ SpeculatedType getSpeculation(Node& node) { return node.prediction(); }
+ SpeculatedType getSpeculation(NodeIndex nodeIndex) { return getSpeculation(graph()[nodeIndex]); }
+ SpeculatedType getSpeculation(Edge nodeUse) { return getSpeculation(nodeUse.index()); }
#if USE(JSVALUE32_64)
void* addressOfDoubleConstant(NodeIndex nodeIndex)
@@ -288,6 +288,12 @@ public:
m_codeBlock->appendWeakReference(target);
}
+ void addWeakReferences(const StructureSet& structureSet)
+ {
+ for (unsigned i = structureSet.size(); i--;)
+ addWeakReference(structureSet[i]);
+ }
+
void addWeakReferenceTransition(JSCell* codeOrigin, JSCell* from, JSCell* to)
{
m_codeBlock->appendWeakReferenceTransition(codeOrigin, from, to);
diff --git a/Source/JavaScriptCore/dfg/DFGNode.h b/Source/JavaScriptCore/dfg/DFGNode.h
index 12ebba823..64e6fe097 100644
--- a/Source/JavaScriptCore/dfg/DFGNode.h
+++ b/Source/JavaScriptCore/dfg/DFGNode.h
@@ -39,7 +39,7 @@
#include "DFGVariableAccessData.h"
#include "JSValue.h"
#include "Operands.h"
-#include "PredictedType.h"
+#include "SpeculatedType.h"
#include "ValueProfile.h"
namespace JSC { namespace DFG {
@@ -82,7 +82,7 @@ struct Node {
, children(AdjacencyList::Fixed, child1, child2, child3)
, m_virtualRegister(InvalidVirtualRegister)
, m_refCount(0)
- , m_prediction(PredictNone)
+ , m_prediction(SpecNone)
{
setOpAndDefaultFlags(op);
ASSERT(!(m_flags & NodeHasVarArgs));
@@ -95,7 +95,7 @@ struct Node {
, m_virtualRegister(InvalidVirtualRegister)
, m_refCount(0)
, m_opInfo(imm.m_value)
- , m_prediction(PredictNone)
+ , m_prediction(SpecNone)
{
setOpAndDefaultFlags(op);
ASSERT(!(m_flags & NodeHasVarArgs));
@@ -109,7 +109,7 @@ struct Node {
, m_refCount(0)
, m_opInfo(imm1.m_value)
, m_opInfo2(safeCast<unsigned>(imm2.m_value))
- , m_prediction(PredictNone)
+ , m_prediction(SpecNone)
{
setOpAndDefaultFlags(op);
ASSERT(!(m_flags & NodeHasVarArgs));
@@ -123,7 +123,7 @@ struct Node {
, m_refCount(0)
, m_opInfo(imm1.m_value)
, m_opInfo2(safeCast<unsigned>(imm2.m_value))
- , m_prediction(PredictNone)
+ , m_prediction(SpecNone)
{
setOpAndDefaultFlags(op);
ASSERT(m_flags & NodeHasVarArgs);
@@ -421,7 +421,7 @@ struct Node {
bool hasVarNumber()
{
- return op() == GetGlobalVar || op() == PutGlobalVar || op() == GetScopedVar || op() == PutScopedVar;
+ return op() == GetScopedVar || op() == PutScopedVar;
}
unsigned varNumber()
@@ -429,6 +429,27 @@ struct Node {
ASSERT(hasVarNumber());
return m_opInfo;
}
+
+ bool hasIdentifierNumberForCheck()
+ {
+ return op() == GlobalVarWatchpoint || op() == PutGlobalVarCheck;
+ }
+
+ unsigned identifierNumberForCheck()
+ {
+ ASSERT(hasIdentifierNumberForCheck());
+ return m_opInfo2;
+ }
+
+ bool hasRegisterPointer()
+ {
+ return op() == GetGlobalVar || op() == PutGlobalVar || op() == GlobalVarWatchpoint || op() == PutGlobalVarCheck;
+ }
+
+ WriteBarrier<Unknown>* registerPointer()
+ {
+ return bitwise_cast<WriteBarrier<Unknown>*>(m_opInfo);
+ }
bool hasScopeChainDepth()
{
@@ -584,17 +605,17 @@ struct Node {
}
}
- PredictedType getHeapPrediction()
+ SpeculatedType getHeapPrediction()
{
ASSERT(hasHeapPrediction());
- return static_cast<PredictedType>(m_opInfo2);
+ return static_cast<SpeculatedType>(m_opInfo2);
}
- bool predictHeap(PredictedType prediction)
+ bool predictHeap(SpeculatedType prediction)
{
ASSERT(hasHeapPrediction());
- return mergePrediction(m_opInfo2, prediction);
+ return mergeSpeculation(m_opInfo2, prediction);
}
bool hasFunctionCheckData()
@@ -630,6 +651,17 @@ struct Node {
return *reinterpret_cast<StructureSet*>(m_opInfo);
}
+ bool hasStructure()
+ {
+ return op() == StructureTransitionWatchpoint;
+ }
+
+ Structure* structure()
+ {
+ ASSERT(hasStructure());
+ return reinterpret_cast<Structure*>(m_opInfo);
+ }
+
bool hasStorageAccessData()
{
return op() == GetByOffset || op() == PutByOffset;
@@ -682,6 +714,17 @@ struct Node {
ASSERT(m_virtualRegister == InvalidVirtualRegister);
m_virtualRegister = virtualRegister;
}
+
+ bool hasArgumentPositionStart()
+ {
+ return op() == InlineStart;
+ }
+
+ unsigned argumentPositionStart()
+ {
+ ASSERT(hasArgumentPositionStart());
+ return m_opInfo;
+ }
bool shouldGenerate()
{
@@ -756,114 +799,114 @@ struct Node {
return children.numChildren();
}
- PredictedType prediction()
+ SpeculatedType prediction()
{
return m_prediction;
}
- bool predict(PredictedType prediction)
+ bool predict(SpeculatedType prediction)
{
- return mergePrediction(m_prediction, prediction);
+ return mergeSpeculation(m_prediction, prediction);
}
bool shouldSpeculateInteger()
{
- return isInt32Prediction(prediction());
+ return isInt32Speculation(prediction());
}
bool shouldSpeculateDouble()
{
- return isDoublePrediction(prediction());
+ return isDoubleSpeculation(prediction());
}
bool shouldSpeculateNumber()
{
- return isNumberPrediction(prediction());
+ return isNumberSpeculation(prediction());
}
bool shouldSpeculateBoolean()
{
- return isBooleanPrediction(prediction());
+ return isBooleanSpeculation(prediction());
}
bool shouldSpeculateFinalObject()
{
- return isFinalObjectPrediction(prediction());
+ return isFinalObjectSpeculation(prediction());
}
bool shouldSpeculateFinalObjectOrOther()
{
- return isFinalObjectOrOtherPrediction(prediction());
+ return isFinalObjectOrOtherSpeculation(prediction());
}
bool shouldSpeculateArray()
{
- return isArrayPrediction(prediction());
+ return isArraySpeculation(prediction());
}
bool shouldSpeculateArguments()
{
- return isArgumentsPrediction(prediction());
+ return isArgumentsSpeculation(prediction());
}
bool shouldSpeculateInt8Array()
{
- return isInt8ArrayPrediction(prediction());
+ return isInt8ArraySpeculation(prediction());
}
bool shouldSpeculateInt16Array()
{
- return isInt16ArrayPrediction(prediction());
+ return isInt16ArraySpeculation(prediction());
}
bool shouldSpeculateInt32Array()
{
- return isInt32ArrayPrediction(prediction());
+ return isInt32ArraySpeculation(prediction());
}
bool shouldSpeculateUint8Array()
{
- return isUint8ArrayPrediction(prediction());
+ return isUint8ArraySpeculation(prediction());
}
bool shouldSpeculateUint8ClampedArray()
{
- return isUint8ClampedArrayPrediction(prediction());
+ return isUint8ClampedArraySpeculation(prediction());
}
bool shouldSpeculateUint16Array()
{
- return isUint16ArrayPrediction(prediction());
+ return isUint16ArraySpeculation(prediction());
}
bool shouldSpeculateUint32Array()
{
- return isUint32ArrayPrediction(prediction());
+ return isUint32ArraySpeculation(prediction());
}
bool shouldSpeculateFloat32Array()
{
- return isFloat32ArrayPrediction(prediction());
+ return isFloat32ArraySpeculation(prediction());
}
bool shouldSpeculateFloat64Array()
{
- return isFloat64ArrayPrediction(prediction());
+ return isFloat64ArraySpeculation(prediction());
}
bool shouldSpeculateArrayOrOther()
{
- return isArrayOrOtherPrediction(prediction());
+ return isArrayOrOtherSpeculation(prediction());
}
bool shouldSpeculateObject()
{
- return isObjectPrediction(prediction());
+ return isObjectSpeculation(prediction());
}
bool shouldSpeculateCell()
{
- return isCellPrediction(prediction());
+ return isCellSpeculation(prediction());
}
static bool shouldSpeculateInteger(Node& op1, Node& op2)
@@ -921,7 +964,7 @@ private:
uintptr_t m_opInfo;
unsigned m_opInfo2;
// The prediction ascribed to this node after propagation.
- PredictedType m_prediction;
+ SpeculatedType m_prediction;
};
} } // namespace JSC::DFG
diff --git a/Source/JavaScriptCore/dfg/DFGNodeType.h b/Source/JavaScriptCore/dfg/DFGNodeType.h
index 743f87955..4671f6b6c 100644
--- a/Source/JavaScriptCore/dfg/DFGNodeType.h
+++ b/Source/JavaScriptCore/dfg/DFGNodeType.h
@@ -118,6 +118,18 @@ namespace JSC { namespace DFG {
macro(PutById, NodeMustGenerate | NodeClobbersWorld) \
macro(PutByIdDirect, NodeMustGenerate | NodeClobbersWorld) \
macro(CheckStructure, NodeMustGenerate) \
+ /* Transition watchpoints are a contract between the party setting the watchpoint */\
+ /* and the runtime system, where the party promises that the child object once had */\
+ /* the structure being watched, and the runtime system in turn promises that the */\
+ /* watchpoint will be turned into an OSR exit if any object with that structure */\
+ /* ever transitions to a different structure. Hence, the child object must have */\
+ /* previously had a CheckStructure executed on it or we're dealing with an object */\
+ /* constant (WeakJSConstant) and the object was known to have that structure at */\
+ /* compile-time. In the latter case this means that no structure checks have to be */\
+ /* performed for this object by JITted code. In the former case this means that*/\
+ /* the object's structure does not need to be rechecked due to side-effecting */\
+ /* (clobbering) operations. */\
+ macro(StructureTransitionWatchpoint, NodeMustGenerate) \
macro(PutStructure, NodeMustGenerate) \
macro(PhantomPutStructure, NodeMustGenerate | NodeDoesNotExit) \
macro(GetPropertyStorage, NodeResultStorage) \
@@ -141,6 +153,8 @@ namespace JSC { namespace DFG {
macro(PutScopedVar, NodeMustGenerate | NodeClobbersWorld) \
macro(GetGlobalVar, NodeResultJS | NodeMustGenerate) \
macro(PutGlobalVar, NodeMustGenerate) \
+ macro(GlobalVarWatchpoint, NodeMustGenerate) \
+ macro(PutGlobalVarCheck, NodeMustGenerate) \
macro(CheckFunction, NodeMustGenerate) \
\
/* Optimizations for array mutation. */\
diff --git a/Source/JavaScriptCore/dfg/DFGOSRExit.cpp b/Source/JavaScriptCore/dfg/DFGOSRExit.cpp
index bcb98a1ed..d0e0de9da 100644
--- a/Source/JavaScriptCore/dfg/DFGOSRExit.cpp
+++ b/Source/JavaScriptCore/dfg/DFGOSRExit.cpp
@@ -51,6 +51,7 @@ OSRExit::OSRExit(ExitKind kind, JSValueSource jsValueSource, MethodOfGettingAVal
, m_codeOrigin(jit->m_codeOriginForOSR)
, m_codeOriginForExitProfile(m_codeOrigin)
, m_recoveryIndex(recoveryIndex)
+ , m_watchpointIndex(std::numeric_limits<unsigned>::max())
, m_kind(kind)
, m_count(0)
, m_arguments(jit->m_arguments.size())
diff --git a/Source/JavaScriptCore/dfg/DFGOSRExit.h b/Source/JavaScriptCore/dfg/DFGOSRExit.h
index 841fdddb3..683f260f1 100644
--- a/Source/JavaScriptCore/dfg/DFGOSRExit.h
+++ b/Source/JavaScriptCore/dfg/DFGOSRExit.h
@@ -96,6 +96,7 @@ struct OSRExit {
CodeOrigin m_codeOriginForExitProfile;
unsigned m_recoveryIndex;
+ unsigned m_watchpointIndex;
ExitKind m_kind;
uint32_t m_count;
diff --git a/Source/JavaScriptCore/dfg/DFGOSRExitCompiler.cpp b/Source/JavaScriptCore/dfg/DFGOSRExitCompiler.cpp
index 888a4a2c5..d46d59650 100644
--- a/Source/JavaScriptCore/dfg/DFGOSRExitCompiler.cpp
+++ b/Source/JavaScriptCore/dfg/DFGOSRExitCompiler.cpp
@@ -79,11 +79,11 @@ void compileOSRExit(ExecState* exec)
exitCompiler.compileExit(exit, recovery);
LinkBuffer patchBuffer(*globalData, &jit, codeBlock);
- exit.m_code = patchBuffer.finalizeCode();
-
-#if DFG_ENABLE(DEBUG_VERBOSE)
- dataLog("OSR exit code at [%p, %p).\n", patchBuffer.debugAddress(), static_cast<char*>(patchBuffer.debugAddress()) + patchBuffer.debugSize());
-#endif
+ exit.m_code = FINALIZE_CODE(
+ patchBuffer,
+ ("DFG OSR exit #%u (bc#%u, @%u, %s) from CodeBlock %p",
+ exitIndex, exit.m_codeOrigin.bytecodeIndex, exit.m_nodeIndex,
+ exitKindToString(exit.m_kind), codeBlock));
}
{
diff --git a/Source/JavaScriptCore/dfg/DFGOSRExitCompiler.h b/Source/JavaScriptCore/dfg/DFGOSRExitCompiler.h
index 86345b0eb..ae29a92d5 100644
--- a/Source/JavaScriptCore/dfg/DFGOSRExitCompiler.h
+++ b/Source/JavaScriptCore/dfg/DFGOSRExitCompiler.h
@@ -78,7 +78,7 @@ private:
};
extern "C" {
-void DFG_OPERATION compileOSRExit(ExecState*);
+void DFG_OPERATION compileOSRExit(ExecState*) WTF_INTERNAL;
}
} } // namespace JSC::DFG
diff --git a/Source/JavaScriptCore/dfg/DFGOSRExitCompiler32_64.cpp b/Source/JavaScriptCore/dfg/DFGOSRExitCompiler32_64.cpp
index d773cb4ac..09912b3e5 100644
--- a/Source/JavaScriptCore/dfg/DFGOSRExitCompiler32_64.cpp
+++ b/Source/JavaScriptCore/dfg/DFGOSRExitCompiler32_64.cpp
@@ -533,70 +533,6 @@ void OSRExitCompiler::compileExit(const OSRExit& exit, SpeculationRecovery* reco
}
}
- // 11) Create arguments if necessary and place them into the appropriate aliased
- // registers.
-
- if (haveArguments) {
- for (int index = 0; index < exit.numberOfRecoveries(); ++index) {
- const ValueRecovery& recovery = exit.valueRecovery(index);
- if (recovery.technique() != ArgumentsThatWereNotCreated)
- continue;
- int operand = exit.operandForIndex(index);
- // Find the right inline call frame.
- InlineCallFrame* inlineCallFrame = 0;
- for (InlineCallFrame* current = exit.m_codeOrigin.inlineCallFrame;
- current;
- current = current->caller.inlineCallFrame) {
- if (current->stackOffset <= operand) {
- inlineCallFrame = current;
- break;
- }
- }
- int argumentsRegister = m_jit.argumentsRegisterFor(inlineCallFrame);
-
- m_jit.load32(AssemblyHelpers::payloadFor(argumentsRegister), GPRInfo::regT0);
- AssemblyHelpers::Jump haveArguments = m_jit.branch32(
- AssemblyHelpers::NotEqual,
- AssemblyHelpers::tagFor(argumentsRegister),
- AssemblyHelpers::TrustedImm32(JSValue::EmptyValueTag));
-
- if (inlineCallFrame) {
- m_jit.setupArgumentsWithExecState(
- AssemblyHelpers::TrustedImmPtr(inlineCallFrame));
- m_jit.move(
- AssemblyHelpers::TrustedImmPtr(
- bitwise_cast<void*>(operationCreateInlinedArguments)),
- GPRInfo::nonArgGPR0);
- } else {
- m_jit.setupArgumentsExecState();
- m_jit.move(
- AssemblyHelpers::TrustedImmPtr(
- bitwise_cast<void*>(operationCreateArguments)),
- GPRInfo::nonArgGPR0);
- }
- m_jit.call(GPRInfo::nonArgGPR0);
- m_jit.store32(
- AssemblyHelpers::TrustedImm32(JSValue::CellTag),
- AssemblyHelpers::tagFor(argumentsRegister));
- m_jit.store32(
- GPRInfo::returnValueGPR,
- AssemblyHelpers::payloadFor(argumentsRegister));
- m_jit.store32(
- AssemblyHelpers::TrustedImm32(JSValue::CellTag),
- AssemblyHelpers::tagFor(unmodifiedArgumentsRegister(argumentsRegister)));
- m_jit.store32(
- GPRInfo::returnValueGPR,
- AssemblyHelpers::payloadFor(unmodifiedArgumentsRegister(argumentsRegister)));
- m_jit.move(GPRInfo::returnValueGPR, GPRInfo::regT0); // no-op move on almost all platforms.
-
- haveArguments.link(&m_jit);
- m_jit.store32(
- AssemblyHelpers::TrustedImm32(JSValue::CellTag),
- AssemblyHelpers::tagFor(operand));
- m_jit.store32(GPRInfo::regT0, AssemblyHelpers::payloadFor(operand));
- }
- }
-
// 12) Adjust the old JIT's execute counter. Since we are exiting OSR, we know
// that all new calls into this code will go to the new JIT, so the execute
// counter only affects call frames that performed OSR exit and call frames
@@ -635,14 +571,7 @@ void OSRExitCompiler::compileExit(const OSRExit& exit, SpeculationRecovery* reco
handleExitCounts(exit);
- // 13) Load the result of the last bytecode operation into regT0.
-
- if (exit.m_lastSetOperand != std::numeric_limits<int>::max()) {
- m_jit.load32(AssemblyHelpers::payloadFor((VirtualRegister)exit.m_lastSetOperand), GPRInfo::cachedResultRegister);
- m_jit.load32(AssemblyHelpers::tagFor((VirtualRegister)exit.m_lastSetOperand), GPRInfo::cachedResultRegister2);
- }
-
- // 14) Fix call frame (s).
+ // 13) Reify inlined call frames.
ASSERT(m_jit.baselineCodeBlock()->getJITType() == JITCode::BaselineJIT);
m_jit.storePtr(AssemblyHelpers::TrustedImmPtr(m_jit.baselineCodeBlock()), AssemblyHelpers::addressFor((VirtualRegister)RegisterFile::CodeBlock));
@@ -678,10 +607,83 @@ void OSRExitCompiler::compileExit(const OSRExit& exit, SpeculationRecovery* reco
m_jit.storePtr(AssemblyHelpers::TrustedImmPtr(inlineCallFrame->callee.get()), AssemblyHelpers::payloadFor((VirtualRegister)(inlineCallFrame->stackOffset + RegisterFile::Callee)));
}
+ // 14) Create arguments if necessary and place them into the appropriate aliased
+ // registers.
+
+ if (haveArguments) {
+ for (int index = 0; index < exit.numberOfRecoveries(); ++index) {
+ const ValueRecovery& recovery = exit.valueRecovery(index);
+ if (recovery.technique() != ArgumentsThatWereNotCreated)
+ continue;
+ int operand = exit.operandForIndex(index);
+ // Find the right inline call frame.
+ InlineCallFrame* inlineCallFrame = 0;
+ for (InlineCallFrame* current = exit.m_codeOrigin.inlineCallFrame;
+ current;
+ current = current->caller.inlineCallFrame) {
+ if (current->stackOffset <= operand) {
+ inlineCallFrame = current;
+ break;
+ }
+ }
+ int argumentsRegister = m_jit.argumentsRegisterFor(inlineCallFrame);
+
+ m_jit.load32(AssemblyHelpers::payloadFor(argumentsRegister), GPRInfo::regT0);
+ AssemblyHelpers::Jump haveArguments = m_jit.branch32(
+ AssemblyHelpers::NotEqual,
+ AssemblyHelpers::tagFor(argumentsRegister),
+ AssemblyHelpers::TrustedImm32(JSValue::EmptyValueTag));
+
+ if (inlineCallFrame) {
+ m_jit.setupArgumentsWithExecState(
+ AssemblyHelpers::TrustedImmPtr(inlineCallFrame));
+ m_jit.move(
+ AssemblyHelpers::TrustedImmPtr(
+ bitwise_cast<void*>(operationCreateInlinedArguments)),
+ GPRInfo::nonArgGPR0);
+ } else {
+ m_jit.setupArgumentsExecState();
+ m_jit.move(
+ AssemblyHelpers::TrustedImmPtr(
+ bitwise_cast<void*>(operationCreateArguments)),
+ GPRInfo::nonArgGPR0);
+ }
+ m_jit.call(GPRInfo::nonArgGPR0);
+ m_jit.store32(
+ AssemblyHelpers::TrustedImm32(JSValue::CellTag),
+ AssemblyHelpers::tagFor(argumentsRegister));
+ m_jit.store32(
+ GPRInfo::returnValueGPR,
+ AssemblyHelpers::payloadFor(argumentsRegister));
+ m_jit.store32(
+ AssemblyHelpers::TrustedImm32(JSValue::CellTag),
+ AssemblyHelpers::tagFor(unmodifiedArgumentsRegister(argumentsRegister)));
+ m_jit.store32(
+ GPRInfo::returnValueGPR,
+ AssemblyHelpers::payloadFor(unmodifiedArgumentsRegister(argumentsRegister)));
+ m_jit.move(GPRInfo::returnValueGPR, GPRInfo::regT0); // no-op move on almost all platforms.
+
+ haveArguments.link(&m_jit);
+ m_jit.store32(
+ AssemblyHelpers::TrustedImm32(JSValue::CellTag),
+ AssemblyHelpers::tagFor(operand));
+ m_jit.store32(GPRInfo::regT0, AssemblyHelpers::payloadFor(operand));
+ }
+ }
+
+ // 15) Load the result of the last bytecode operation into regT0.
+
+ if (exit.m_lastSetOperand != std::numeric_limits<int>::max()) {
+ m_jit.load32(AssemblyHelpers::payloadFor((VirtualRegister)exit.m_lastSetOperand), GPRInfo::cachedResultRegister);
+ m_jit.load32(AssemblyHelpers::tagFor((VirtualRegister)exit.m_lastSetOperand), GPRInfo::cachedResultRegister2);
+ }
+
+ // 16) Adjust the call frame pointer.
+
if (exit.m_codeOrigin.inlineCallFrame)
m_jit.addPtr(AssemblyHelpers::TrustedImm32(exit.m_codeOrigin.inlineCallFrame->stackOffset * sizeof(EncodedJSValue)), GPRInfo::callFrameRegister);
- // 15) Jump into the corresponding baseline JIT code.
+ // 17) Jump into the corresponding baseline JIT code.
CodeBlock* baselineCodeBlock = m_jit.baselineCodeBlockFor(exit.m_codeOrigin);
Vector<BytecodeAndMachineOffset>& decodedCodeMap = m_jit.decodedCodeMapFor(baselineCodeBlock);
diff --git a/Source/JavaScriptCore/dfg/DFGOSRExitCompiler64.cpp b/Source/JavaScriptCore/dfg/DFGOSRExitCompiler64.cpp
index 22b236115..33ba69a35 100644
--- a/Source/JavaScriptCore/dfg/DFGOSRExitCompiler64.cpp
+++ b/Source/JavaScriptCore/dfg/DFGOSRExitCompiler64.cpp
@@ -511,58 +511,7 @@ void OSRExitCompiler::compileExit(const OSRExit& exit, SpeculationRecovery* reco
}
}
- // 13) Create arguments if necessary and place them into the appropriate aliased
- // registers.
-
- if (haveArguments) {
- for (int index = 0; index < exit.numberOfRecoveries(); ++index) {
- const ValueRecovery& recovery = exit.valueRecovery(index);
- if (recovery.technique() != ArgumentsThatWereNotCreated)
- continue;
- int operand = exit.operandForIndex(index);
- // Find the right inline call frame.
- InlineCallFrame* inlineCallFrame = 0;
- for (InlineCallFrame* current = exit.m_codeOrigin.inlineCallFrame;
- current;
- current = current->caller.inlineCallFrame) {
- if (current->stackOffset <= operand) {
- inlineCallFrame = current;
- break;
- }
- }
- int argumentsRegister = m_jit.argumentsRegisterFor(inlineCallFrame);
-
- m_jit.loadPtr(AssemblyHelpers::addressFor(argumentsRegister), GPRInfo::regT0);
- AssemblyHelpers::Jump haveArguments = m_jit.branchTestPtr(
- AssemblyHelpers::NonZero, GPRInfo::regT0);
-
- if (inlineCallFrame) {
- m_jit.setupArgumentsWithExecState(
- AssemblyHelpers::TrustedImmPtr(inlineCallFrame));
- m_jit.move(
- AssemblyHelpers::TrustedImmPtr(
- bitwise_cast<void*>(operationCreateInlinedArguments)),
- GPRInfo::nonArgGPR0);
- } else {
- m_jit.setupArgumentsExecState();
- m_jit.move(
- AssemblyHelpers::TrustedImmPtr(
- bitwise_cast<void*>(operationCreateArguments)),
- GPRInfo::nonArgGPR0);
- }
- m_jit.call(GPRInfo::nonArgGPR0);
- m_jit.storePtr(GPRInfo::returnValueGPR, AssemblyHelpers::addressFor(argumentsRegister));
- m_jit.storePtr(
- GPRInfo::returnValueGPR,
- AssemblyHelpers::addressFor(unmodifiedArgumentsRegister(argumentsRegister)));
- m_jit.move(GPRInfo::returnValueGPR, GPRInfo::regT0); // no-op move on almost all platforms.
-
- haveArguments.link(&m_jit);
- m_jit.storePtr(GPRInfo::regT0, AssemblyHelpers::addressFor(operand));
- }
- }
-
- // 14) Adjust the old JIT's execute counter. Since we are exiting OSR, we know
+ // 13) Adjust the old JIT's execute counter. Since we are exiting OSR, we know
// that all new calls into this code will go to the new JIT, so the execute
// counter only affects call frames that performed OSR exit and call frames
// that were still executing the old JIT at the time of another call frame's
@@ -600,12 +549,7 @@ void OSRExitCompiler::compileExit(const OSRExit& exit, SpeculationRecovery* reco
handleExitCounts(exit);
- // 15) Load the result of the last bytecode operation into regT0.
-
- if (exit.m_lastSetOperand != std::numeric_limits<int>::max())
- m_jit.loadPtr(AssemblyHelpers::addressFor((VirtualRegister)exit.m_lastSetOperand), GPRInfo::cachedResultRegister);
-
- // 16) Fix call frame(s).
+ // 14) Reify inlined call frames.
ASSERT(m_jit.baselineCodeBlock()->getJITType() == JITCode::BaselineJIT);
m_jit.storePtr(AssemblyHelpers::TrustedImmPtr(m_jit.baselineCodeBlock()), AssemblyHelpers::addressFor((VirtualRegister)RegisterFile::CodeBlock));
@@ -638,10 +582,63 @@ void OSRExitCompiler::compileExit(const OSRExit& exit, SpeculationRecovery* reco
m_jit.storePtr(AssemblyHelpers::TrustedImmPtr(inlineCallFrame->callee.get()), AssemblyHelpers::addressFor((VirtualRegister)(inlineCallFrame->stackOffset + RegisterFile::Callee)));
}
+ // 15) Create arguments if necessary and place them into the appropriate aliased
+ // registers.
+
+ if (haveArguments) {
+ for (int index = 0; index < exit.numberOfRecoveries(); ++index) {
+ const ValueRecovery& recovery = exit.valueRecovery(index);
+ if (recovery.technique() != ArgumentsThatWereNotCreated)
+ continue;
+ int operand = exit.operandForIndex(index);
+ // Find the right inline call frame.
+ InlineCallFrame* inlineCallFrame = 0;
+ for (InlineCallFrame* current = exit.m_codeOrigin.inlineCallFrame;
+ current;
+ current = current->caller.inlineCallFrame) {
+ if (current->stackOffset <= operand) {
+ inlineCallFrame = current;
+ break;
+ }
+ }
+ int argumentsRegister = m_jit.argumentsRegisterFor(inlineCallFrame);
+
+ m_jit.loadPtr(AssemblyHelpers::addressFor(argumentsRegister), GPRInfo::regT0);
+ AssemblyHelpers::Jump haveArguments = m_jit.branchTestPtr(
+ AssemblyHelpers::NonZero, GPRInfo::regT0);
+
+ if (inlineCallFrame) {
+ m_jit.addPtr(AssemblyHelpers::TrustedImm32(inlineCallFrame->stackOffset * sizeof(EncodedJSValue)), GPRInfo::callFrameRegister, GPRInfo::regT0);
+ m_jit.setupArguments(GPRInfo::regT0);
+ } else
+ m_jit.setupArgumentsExecState();
+ m_jit.move(
+ AssemblyHelpers::TrustedImmPtr(
+ bitwise_cast<void*>(operationCreateArguments)),
+ GPRInfo::nonArgGPR0);
+ m_jit.call(GPRInfo::nonArgGPR0);
+ m_jit.storePtr(GPRInfo::returnValueGPR, AssemblyHelpers::addressFor(argumentsRegister));
+ m_jit.storePtr(
+ GPRInfo::returnValueGPR,
+ AssemblyHelpers::addressFor(unmodifiedArgumentsRegister(argumentsRegister)));
+ m_jit.move(GPRInfo::returnValueGPR, GPRInfo::regT0); // no-op move on almost all platforms.
+
+ haveArguments.link(&m_jit);
+ m_jit.storePtr(GPRInfo::regT0, AssemblyHelpers::addressFor(operand));
+ }
+ }
+
+ // 16) Load the result of the last bytecode operation into regT0.
+
+ if (exit.m_lastSetOperand != std::numeric_limits<int>::max())
+ m_jit.loadPtr(AssemblyHelpers::addressFor((VirtualRegister)exit.m_lastSetOperand), GPRInfo::cachedResultRegister);
+
+ // 17) Adjust the call frame pointer.
+
if (exit.m_codeOrigin.inlineCallFrame)
m_jit.addPtr(AssemblyHelpers::TrustedImm32(exit.m_codeOrigin.inlineCallFrame->stackOffset * sizeof(EncodedJSValue)), GPRInfo::callFrameRegister);
- // 17) Jump into the corresponding baseline JIT code.
+ // 18) Jump into the corresponding baseline JIT code.
CodeBlock* baselineCodeBlock = m_jit.baselineCodeBlockFor(exit.m_codeOrigin);
Vector<BytecodeAndMachineOffset>& decodedCodeMap = m_jit.decodedCodeMapFor(baselineCodeBlock);
diff --git a/Source/JavaScriptCore/dfg/DFGOperations.cpp b/Source/JavaScriptCore/dfg/DFGOperations.cpp
index b5ac4601a..06a1cf883 100644
--- a/Source/JavaScriptCore/dfg/DFGOperations.cpp
+++ b/Source/JavaScriptCore/dfg/DFGOperations.cpp
@@ -51,7 +51,7 @@
HIDE_SYMBOL(function) "\n" \
SYMBOL_STRING(function) ":" "\n" \
"mov (%rsp), %" STRINGIZE(register) "\n" \
- "jmp " SYMBOL_STRING_RELOCATION(function##WithReturnAddress) "\n" \
+ "jmp " LOCAL_REFERENCE(function##WithReturnAddress) "\n" \
);
#define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_E(function) FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, rsi)
#define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_ECI(function) FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, rcx)
@@ -68,7 +68,7 @@
SYMBOL_STRING(function) ":" "\n" \
"mov (%esp), %eax\n" \
"mov %eax, " STRINGIZE(offset) "(%esp)\n" \
- "jmp " SYMBOL_STRING_RELOCATION(function##WithReturnAddress) "\n" \
+ "jmp " LOCAL_REFERENCE(function##WithReturnAddress) "\n" \
);
#define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_E(function) FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, 8)
#define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_ECI(function) FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, 16)
@@ -87,7 +87,7 @@
".thumb_func " THUMB_FUNC_PARAM(function) "\n" \
SYMBOL_STRING(function) ":" "\n" \
"mov a2, lr" "\n" \
- "b " SYMBOL_STRING_RELOCATION(function) "WithReturnAddress" "\n" \
+ "b " LOCAL_REFERENCE(function) "WithReturnAddress" "\n" \
);
#define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_ECI(function) \
@@ -100,7 +100,7 @@
".thumb_func " THUMB_FUNC_PARAM(function) "\n" \
SYMBOL_STRING(function) ":" "\n" \
"mov a4, lr" "\n" \
- "b " SYMBOL_STRING_RELOCATION(function) "WithReturnAddress" "\n" \
+ "b " LOCAL_REFERENCE(function) "WithReturnAddress" "\n" \
);
// EncodedJSValue in JSVALUE32_64 is a 64-bit integer. When being compiled in ARM EABI, it must be aligned even-numbered register (r0, r2 or [sp]).
@@ -123,7 +123,7 @@
".thumb_func " THUMB_FUNC_PARAM(function) "\n" \
SYMBOL_STRING(function) ":" "\n" \
INSTRUCTION_STORE_RETURN_ADDRESS_EJI "\n" \
- "b " SYMBOL_STRING_RELOCATION(function) "WithReturnAddress" "\n" \
+ "b " LOCAL_REFERENCE(function) "WithReturnAddress" "\n" \
);
#define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(function) \
@@ -136,25 +136,25 @@
".thumb_func " THUMB_FUNC_PARAM(function) "\n" \
SYMBOL_STRING(function) ":" "\n" \
INSTRUCTION_STORE_RETURN_ADDRESS_EJCI "\n" \
- "b " SYMBOL_STRING_RELOCATION(function) "WithReturnAddress" "\n" \
+ "b " LOCAL_REFERENCE(function) "WithReturnAddress" "\n" \
);
#endif
#define P_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_E(function) \
-void* DFG_OPERATION function##WithReturnAddress(ExecState*, ReturnAddressPtr) REFERENCED_FROM_ASM; \
+void* DFG_OPERATION function##WithReturnAddress(ExecState*, ReturnAddressPtr) REFERENCED_FROM_ASM WTF_INTERNAL; \
FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_E(function)
#define J_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_ECI(function) \
-EncodedJSValue DFG_OPERATION function##WithReturnAddress(ExecState*, JSCell*, Identifier*, ReturnAddressPtr) REFERENCED_FROM_ASM; \
+EncodedJSValue DFG_OPERATION function##WithReturnAddress(ExecState*, JSCell*, Identifier*, ReturnAddressPtr) REFERENCED_FROM_ASM WTF_INTERNAL; \
FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_ECI(function)
#define J_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJI(function) \
-EncodedJSValue DFG_OPERATION function##WithReturnAddress(ExecState*, EncodedJSValue, Identifier*, ReturnAddressPtr) REFERENCED_FROM_ASM; \
+EncodedJSValue DFG_OPERATION function##WithReturnAddress(ExecState*, EncodedJSValue, Identifier*, ReturnAddressPtr) REFERENCED_FROM_ASM WTF_INTERNAL; \
FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJI(function)
#define V_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(function) \
-void DFG_OPERATION function##WithReturnAddress(ExecState*, EncodedJSValue, JSCell*, Identifier*, ReturnAddressPtr) REFERENCED_FROM_ASM; \
+void DFG_OPERATION function##WithReturnAddress(ExecState*, EncodedJSValue, JSCell*, Identifier*, ReturnAddressPtr) REFERENCED_FROM_ASM WTF_INTERNAL; \
FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(function)
namespace JSC { namespace DFG {
@@ -924,6 +924,11 @@ void* DFG_OPERATION operationVirtualConstruct(ExecState* execCallee)
return virtualFor(execCallee, CodeForConstruct);
}
+void DFG_OPERATION operationNotifyGlobalVarWrite(WatchpointSet* watchpointSet)
+{
+ watchpointSet->notifyWrite();
+}
+
EncodedJSValue DFG_OPERATION operationResolve(ExecState* exec, Identifier* propertyName)
{
JSGlobalData* globalData = &exec->globalData();
@@ -1096,6 +1101,8 @@ void DFG_OPERATION operationTearOffInlinedArguments(
EncodedJSValue DFG_OPERATION operationGetArgumentsLength(ExecState* exec, int32_t argumentsRegister)
{
+ // Here we can assume that the argumernts were created. Because otherwise the JIT code would
+ // have not made this call.
Identifier ident(&exec->globalData(), "length");
JSValue baseValue = exec->uncheckedR(argumentsRegister).jsValue();
PropertySlot slot(baseValue);
@@ -1104,8 +1111,29 @@ EncodedJSValue DFG_OPERATION operationGetArgumentsLength(ExecState* exec, int32_
EncodedJSValue DFG_OPERATION operationGetArgumentByVal(ExecState* exec, int32_t argumentsRegister, int32_t index)
{
- return JSValue::encode(
- exec->uncheckedR(argumentsRegister).jsValue().get(exec, index));
+ JSValue argumentsValue = exec->uncheckedR(argumentsRegister).jsValue();
+
+ // If there are no arguments, and we're accessing out of bounds, then we have to create the
+ // arguments in case someone has installed a getter on a numeric property.
+ if (!argumentsValue)
+ exec->uncheckedR(argumentsRegister) = argumentsValue = Arguments::create(exec->globalData(), exec);
+
+ return JSValue::encode(argumentsValue.get(exec, index));
+}
+
+EncodedJSValue DFG_OPERATION operationGetInlinedArgumentByVal(
+ ExecState* exec, int32_t argumentsRegister, InlineCallFrame* inlineCallFrame, int32_t index)
+{
+ JSValue argumentsValue = exec->uncheckedR(argumentsRegister).jsValue();
+
+ // If there are no arguments, and we're accessing out of bounds, then we have to create the
+ // arguments in case someone has installed a getter on a numeric property.
+ if (!argumentsValue) {
+ exec->uncheckedR(argumentsRegister) = argumentsValue =
+ Arguments::create(exec->globalData(), exec, inlineCallFrame);
+ }
+
+ return JSValue::encode(argumentsValue.get(exec, index));
}
JSCell* DFG_OPERATION operationNewFunction(ExecState* exec, JSCell* functionExecutable)
@@ -1241,7 +1269,7 @@ HIDE_SYMBOL(getHostCallReturnValue) "\n"
SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
"mov -40(%r13), %r13\n"
"mov %r13, %rdi\n"
- "jmp " SYMBOL_STRING_RELOCATION(getHostCallReturnValueWithExecState) "\n"
+ "jmp " LOCAL_REFERENCE(getHostCallReturnValueWithExecState) "\n"
);
#elif CPU(X86)
asm (
@@ -1251,7 +1279,7 @@ HIDE_SYMBOL(getHostCallReturnValue) "\n"
SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
"mov -40(%edi), %edi\n"
"mov %edi, 4(%esp)\n"
- "jmp " SYMBOL_STRING_RELOCATION(getHostCallReturnValueWithExecState) "\n"
+ "jmp " LOCAL_REFERENCE(getHostCallReturnValueWithExecState) "\n"
);
#elif CPU(ARM_THUMB2)
asm (
@@ -1264,7 +1292,7 @@ HIDE_SYMBOL(getHostCallReturnValue) "\n"
SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
"ldr r5, [r5, #-40]" "\n"
"mov r0, r5" "\n"
- "b " SYMBOL_STRING_RELOCATION(getHostCallReturnValueWithExecState) "\n"
+ "b " LOCAL_REFERENCE(getHostCallReturnValueWithExecState) "\n"
);
#endif
diff --git a/Source/JavaScriptCore/dfg/DFGOperations.h b/Source/JavaScriptCore/dfg/DFGOperations.h
index 03f198e9d..38166a83f 100644
--- a/Source/JavaScriptCore/dfg/DFGOperations.h
+++ b/Source/JavaScriptCore/dfg/DFGOperations.h
@@ -77,6 +77,7 @@ typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EPP)(ExecState*, void*, vo
typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EPS)(ExecState*, void*, size_t);
typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_ESS)(ExecState*, size_t, size_t);
typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EZ)(ExecState*, int32_t);
+typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EZIcfZ)(ExecState*, int32_t, InlineCallFrame*, int32_t);
typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EZZ)(ExecState*, int32_t, int32_t);
typedef JSCell* DFG_OPERATION (*C_DFGOperation_E)(ExecState*);
typedef JSCell* DFG_OPERATION (*C_DFGOperation_EC)(ExecState*, JSCell*);
@@ -99,78 +100,81 @@ typedef void DFG_OPERATION (*V_DFGOperation_EJCI)(ExecState*, EncodedJSValue, JS
typedef void DFG_OPERATION (*V_DFGOperation_EJJJ)(ExecState*, EncodedJSValue, EncodedJSValue, EncodedJSValue);
typedef void DFG_OPERATION (*V_DFGOperation_EJPP)(ExecState*, EncodedJSValue, EncodedJSValue, void*);
typedef void DFG_OPERATION (*V_DFGOperation_EPZJ)(ExecState*, void*, int32_t, EncodedJSValue);
+typedef void DFG_OPERATION (*V_DFGOperation_W)(WatchpointSet*);
typedef void* DFG_OPERATION (*P_DFGOperation_E)(ExecState*);
// These routines are provide callbacks out to C++ implementations of operations too complex to JIT.
-JSCell* DFG_OPERATION operationNewObject(ExecState*);
-JSCell* DFG_OPERATION operationCreateThis(ExecState*, JSCell* constructor);
-EncodedJSValue DFG_OPERATION operationConvertThis(ExecState*, EncodedJSValue encodedOp1);
-EncodedJSValue DFG_OPERATION operationValueAdd(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2);
-EncodedJSValue DFG_OPERATION operationValueAddNotNumber(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2);
-EncodedJSValue DFG_OPERATION operationGetByVal(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedProperty);
-EncodedJSValue DFG_OPERATION operationGetByValCell(ExecState*, JSCell*, EncodedJSValue encodedProperty);
-EncodedJSValue DFG_OPERATION operationGetById(ExecState*, EncodedJSValue, Identifier*);
-EncodedJSValue DFG_OPERATION operationGetByIdBuildList(ExecState*, EncodedJSValue, Identifier*);
-EncodedJSValue DFG_OPERATION operationGetByIdProtoBuildList(ExecState*, EncodedJSValue, Identifier*);
-EncodedJSValue DFG_OPERATION operationGetByIdOptimize(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*);
-EncodedJSValue DFG_OPERATION operationResolveGlobal(ExecState*, GlobalResolveInfo*, Identifier*);
-EncodedJSValue DFG_OPERATION operationToPrimitive(ExecState*, EncodedJSValue);
-EncodedJSValue DFG_OPERATION operationStrCat(ExecState*, void*, size_t);
-EncodedJSValue DFG_OPERATION operationNewArray(ExecState*, void*, size_t);
-EncodedJSValue DFG_OPERATION operationNewArrayBuffer(ExecState*, size_t, size_t);
-EncodedJSValue DFG_OPERATION operationNewRegexp(ExecState*, void*);
-void DFG_OPERATION operationPutByValStrict(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue);
-void DFG_OPERATION operationPutByValNonStrict(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue);
-void DFG_OPERATION operationPutByValCellStrict(ExecState*, JSCell*, EncodedJSValue encodedProperty, EncodedJSValue encodedValue);
-void DFG_OPERATION operationPutByValCellNonStrict(ExecState*, JSCell*, EncodedJSValue encodedProperty, EncodedJSValue encodedValue);
-void DFG_OPERATION operationPutByValBeyondArrayBoundsStrict(ExecState*, JSArray*, int32_t index, EncodedJSValue encodedValue);
-void DFG_OPERATION operationPutByValBeyondArrayBoundsNonStrict(ExecState*, JSArray*, int32_t index, EncodedJSValue encodedValue);
-EncodedJSValue DFG_OPERATION operationArrayPush(ExecState*, EncodedJSValue encodedValue, JSArray*);
-EncodedJSValue DFG_OPERATION operationArrayPop(ExecState*, JSArray*);
-EncodedJSValue DFG_OPERATION operationRegExpExec(ExecState*, JSCell*, JSCell*);
-void DFG_OPERATION operationPutByIdStrict(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*);
-void DFG_OPERATION operationPutByIdNonStrict(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*);
-void DFG_OPERATION operationPutByIdDirectStrict(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*);
-void DFG_OPERATION operationPutByIdDirectNonStrict(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*);
-void DFG_OPERATION operationPutByIdStrictOptimize(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*);
-void DFG_OPERATION operationPutByIdNonStrictOptimize(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*);
-void DFG_OPERATION operationPutByIdDirectStrictOptimize(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*);
-void DFG_OPERATION operationPutByIdDirectNonStrictOptimize(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*);
-void DFG_OPERATION operationPutByIdStrictBuildList(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*);
-void DFG_OPERATION operationPutByIdNonStrictBuildList(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*);
-void DFG_OPERATION operationPutByIdDirectStrictBuildList(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*);
-void DFG_OPERATION operationPutByIdDirectNonStrictBuildList(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*);
+JSCell* DFG_OPERATION operationNewObject(ExecState*) WTF_INTERNAL;
+JSCell* DFG_OPERATION operationCreateThis(ExecState*, JSCell* constructor) WTF_INTERNAL;
+EncodedJSValue DFG_OPERATION operationConvertThis(ExecState*, EncodedJSValue encodedOp1) WTF_INTERNAL;
+EncodedJSValue DFG_OPERATION operationValueAdd(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
+EncodedJSValue DFG_OPERATION operationValueAddNotNumber(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
+EncodedJSValue DFG_OPERATION operationGetByVal(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedProperty) WTF_INTERNAL;
+EncodedJSValue DFG_OPERATION operationGetByValCell(ExecState*, JSCell*, EncodedJSValue encodedProperty) WTF_INTERNAL;
+EncodedJSValue DFG_OPERATION operationGetById(ExecState*, EncodedJSValue, Identifier*) WTF_INTERNAL;
+EncodedJSValue DFG_OPERATION operationGetByIdBuildList(ExecState*, EncodedJSValue, Identifier*) WTF_INTERNAL;
+EncodedJSValue DFG_OPERATION operationGetByIdProtoBuildList(ExecState*, EncodedJSValue, Identifier*) WTF_INTERNAL;
+EncodedJSValue DFG_OPERATION operationGetByIdOptimize(ExecState*, EncodedJSValue, Identifier*) WTF_INTERNAL;
+EncodedJSValue DFG_OPERATION operationCallCustomGetter(ExecState*, JSCell*, PropertySlot::GetValueFunc, Identifier*) WTF_INTERNAL;
+EncodedJSValue DFG_OPERATION operationCallGetter(ExecState*, JSCell*, JSCell*) WTF_INTERNAL;
+void DFG_OPERATION operationNotifyGlobalVarWrite(WatchpointSet* watchpointSet) WTF_INTERNAL;
+EncodedJSValue DFG_OPERATION operationResolve(ExecState*, Identifier*) WTF_INTERNAL;
+EncodedJSValue DFG_OPERATION operationResolveBase(ExecState*, Identifier*) WTF_INTERNAL;
+EncodedJSValue DFG_OPERATION operationResolveBaseStrictPut(ExecState*, Identifier*) WTF_INTERNAL;
+EncodedJSValue DFG_OPERATION operationResolveGlobal(ExecState*, GlobalResolveInfo*, Identifier*) WTF_INTERNAL;
+EncodedJSValue DFG_OPERATION operationToPrimitive(ExecState*, EncodedJSValue) WTF_INTERNAL;
+EncodedJSValue DFG_OPERATION operationStrCat(ExecState*, void*, size_t) WTF_INTERNAL;
+EncodedJSValue DFG_OPERATION operationNewArray(ExecState*, void*, size_t) WTF_INTERNAL;
+EncodedJSValue DFG_OPERATION operationNewArrayBuffer(ExecState*, size_t, size_t) WTF_INTERNAL;
+EncodedJSValue DFG_OPERATION operationNewRegexp(ExecState*, void*) WTF_INTERNAL;
+void DFG_OPERATION operationPutByValStrict(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue) WTF_INTERNAL;
+void DFG_OPERATION operationPutByValNonStrict(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue) WTF_INTERNAL;
+void DFG_OPERATION operationPutByValCellStrict(ExecState*, JSCell*, EncodedJSValue encodedProperty, EncodedJSValue encodedValue) WTF_INTERNAL;
+void DFG_OPERATION operationPutByValCellNonStrict(ExecState*, JSCell*, EncodedJSValue encodedProperty, EncodedJSValue encodedValue) WTF_INTERNAL;
+void DFG_OPERATION operationPutByValBeyondArrayBoundsStrict(ExecState*, JSArray*, int32_t index, EncodedJSValue encodedValue) WTF_INTERNAL;
+void DFG_OPERATION operationPutByValBeyondArrayBoundsNonStrict(ExecState*, JSArray*, int32_t index, EncodedJSValue encodedValue) WTF_INTERNAL;
+EncodedJSValue DFG_OPERATION operationArrayPush(ExecState*, EncodedJSValue encodedValue, JSArray*) WTF_INTERNAL;
+EncodedJSValue DFG_OPERATION operationArrayPop(ExecState*, JSArray*) WTF_INTERNAL;
+EncodedJSValue DFG_OPERATION operationRegExpExec(ExecState*, JSCell*, JSCell*) WTF_INTERNAL;
+void DFG_OPERATION operationPutByIdStrict(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*) WTF_INTERNAL;
+void DFG_OPERATION operationPutByIdNonStrict(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*) WTF_INTERNAL;
+void DFG_OPERATION operationPutByIdDirectStrict(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*) WTF_INTERNAL;
+void DFG_OPERATION operationPutByIdDirectNonStrict(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*) WTF_INTERNAL;
+void DFG_OPERATION operationPutByIdStrictOptimize(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*) WTF_INTERNAL;
+void DFG_OPERATION operationPutByIdNonStrictOptimize(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*) WTF_INTERNAL;
+void DFG_OPERATION operationPutByIdDirectStrictOptimize(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*) WTF_INTERNAL;
+void DFG_OPERATION operationPutByIdDirectNonStrictOptimize(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*) WTF_INTERNAL;
+void DFG_OPERATION operationPutByIdStrictBuildList(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*) WTF_INTERNAL;
+void DFG_OPERATION operationPutByIdNonStrictBuildList(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*) WTF_INTERNAL;
+void DFG_OPERATION operationPutByIdDirectStrictBuildList(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*) WTF_INTERNAL;
+void DFG_OPERATION operationPutByIdDirectNonStrictBuildList(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*) WTF_INTERNAL;
// These comparisons return a boolean within a size_t such that the value is zero extended to fill the register.
-size_t DFG_OPERATION operationRegExpTest(ExecState*, JSCell*, JSCell*);
-size_t DFG_OPERATION operationCompareLess(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2);
-size_t DFG_OPERATION operationCompareLessEq(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2);
-size_t DFG_OPERATION operationCompareGreater(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2);
-size_t DFG_OPERATION operationCompareGreaterEq(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2);
-size_t DFG_OPERATION operationCompareEq(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2);
-size_t DFG_OPERATION operationCompareStrictEqCell(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2);
-size_t DFG_OPERATION operationCompareStrictEq(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2);
-void* DFG_OPERATION operationVirtualCall(ExecState*);
-void* DFG_OPERATION operationLinkCall(ExecState*);
-void* DFG_OPERATION operationVirtualConstruct(ExecState*);
-void* DFG_OPERATION operationLinkConstruct(ExecState*);
-JSCell* DFG_OPERATION operationCreateActivation(ExecState*);
-JSCell* DFG_OPERATION operationCreateArguments(ExecState*);
-JSCell* DFG_OPERATION operationCreateInlinedArguments(ExecState*, InlineCallFrame*);
-void DFG_OPERATION operationTearOffActivation(ExecState*, JSCell*, int32_t unmodifiedArgumentsRegister);
-void DFG_OPERATION operationTearOffArguments(ExecState*, JSCell*);
-void DFG_OPERATION operationTearOffInlinedArguments(ExecState*, JSCell*, InlineCallFrame*);
-EncodedJSValue DFG_OPERATION operationGetArgumentsLength(ExecState*, int32_t);
-EncodedJSValue DFG_OPERATION operationGetArgumentByVal(ExecState*, int32_t, int32_t);
-JSCell* DFG_OPERATION operationNewFunction(ExecState*, JSCell*);
-JSCell* DFG_OPERATION operationNewFunctionExpression(ExecState*, JSCell*);
-double DFG_OPERATION operationFModOnInts(int32_t, int32_t);
-size_t DFG_OPERATION operationIsObject(EncodedJSValue);
-size_t DFG_OPERATION operationIsFunction(EncodedJSValue);
+size_t DFG_OPERATION operationRegExpTest(ExecState*, JSCell*, JSCell*) WTF_INTERNAL;
+size_t DFG_OPERATION operationCompareLess(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
+size_t DFG_OPERATION operationCompareLessEq(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
+size_t DFG_OPERATION operationCompareGreater(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
+size_t DFG_OPERATION operationCompareGreaterEq(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
+size_t DFG_OPERATION operationCompareEq(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
+size_t DFG_OPERATION operationCompareStrictEqCell(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
+size_t DFG_OPERATION operationCompareStrictEq(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
+void* DFG_OPERATION operationVirtualCall(ExecState*) WTF_INTERNAL;
+void* DFG_OPERATION operationLinkCall(ExecState*) WTF_INTERNAL;
+void* DFG_OPERATION operationVirtualConstruct(ExecState*) WTF_INTERNAL;
+void* DFG_OPERATION operationLinkConstruct(ExecState*) WTF_INTERNAL;
+JSCell* DFG_OPERATION operationCreateActivation(ExecState*) WTF_INTERNAL;
+JSCell* DFG_OPERATION operationCreateArguments(ExecState*) WTF_INTERNAL;
+JSCell* DFG_OPERATION operationCreateInlinedArguments(ExecState*, InlineCallFrame*) WTF_INTERNAL;
+void DFG_OPERATION operationTearOffActivation(ExecState*, JSCell*, int32_t unmodifiedArgumentsRegister) WTF_INTERNAL;
+void DFG_OPERATION operationTearOffArguments(ExecState*, JSCell*) WTF_INTERNAL;
+void DFG_OPERATION operationTearOffInlinedArguments(ExecState*, JSCell*, InlineCallFrame*) WTF_INTERNAL;
+EncodedJSValue DFG_OPERATION operationGetArgumentsLength(ExecState*, int32_t) WTF_INTERNAL;
+EncodedJSValue DFG_OPERATION operationGetInlinedArgumentByVal(ExecState*, int32_t, InlineCallFrame*, int32_t) WTF_INTERNAL;
+EncodedJSValue DFG_OPERATION operationGetArgumentByVal(ExecState*, int32_t, int32_t) WTF_INTERNAL;
+JSCell* DFG_OPERATION operationNewFunction(ExecState*, JSCell*) WTF_INTERNAL;
+JSCell* DFG_OPERATION operationNewFunctionExpression(ExecState*, JSCell*) WTF_INTERNAL;
+double DFG_OPERATION operationFModOnInts(int32_t, int32_t) WTF_INTERNAL;
+size_t DFG_OPERATION operationIsObject(EncodedJSValue) WTF_INTERNAL;
+size_t DFG_OPERATION operationIsFunction(EncodedJSValue) WTF_INTERNAL;
// This method is used to lookup an exception hander, keyed by faultLocation, which is
// the return location from one of the calls out to one of the helper operations above.
@@ -210,17 +214,17 @@ inline DFGHandlerEncoded dfgHandlerEncoded(ExecState* exec, void* handler)
return createDFGHandler(exec, handler).u.encoded;
}
#endif
-DFGHandlerEncoded DFG_OPERATION lookupExceptionHandler(ExecState*, uint32_t);
-DFGHandlerEncoded DFG_OPERATION lookupExceptionHandlerInStub(ExecState*, StructureStubInfo*);
+DFGHandlerEncoded DFG_OPERATION lookupExceptionHandler(ExecState*, uint32_t) WTF_INTERNAL;
+DFGHandlerEncoded DFG_OPERATION lookupExceptionHandlerInStub(ExecState*, StructureStubInfo*) WTF_INTERNAL;
// These operations implement the implicitly called ToInt32, ToNumber, and ToBoolean conversions from ES5.
-double DFG_OPERATION dfgConvertJSValueToNumber(ExecState*, EncodedJSValue);
+double DFG_OPERATION dfgConvertJSValueToNumber(ExecState*, EncodedJSValue) WTF_INTERNAL;
// This conversion returns an int32_t within a size_t such that the value is zero extended to fill the register.
-size_t DFG_OPERATION dfgConvertJSValueToInt32(ExecState*, EncodedJSValue);
-size_t DFG_OPERATION dfgConvertJSValueToBoolean(ExecState*, EncodedJSValue);
+size_t DFG_OPERATION dfgConvertJSValueToInt32(ExecState*, EncodedJSValue) WTF_INTERNAL;
+size_t DFG_OPERATION dfgConvertJSValueToBoolean(ExecState*, EncodedJSValue) WTF_INTERNAL;
#if DFG_ENABLE(VERBOSE_SPECULATION_FAILURE)
-void DFG_OPERATION debugOperationPrintSpeculationFailure(ExecState*, void*);
+void DFG_OPERATION debugOperationPrintSpeculationFailure(ExecState*, void*) WTF_INTERNAL;
#endif
} // extern "C"
diff --git a/Source/JavaScriptCore/dfg/DFGPhase.cpp b/Source/JavaScriptCore/dfg/DFGPhase.cpp
index ecf669704..f97c49e31 100644
--- a/Source/JavaScriptCore/dfg/DFGPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGPhase.cpp
@@ -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
@@ -39,7 +39,9 @@ void Phase::beginPhase()
dataLog("Graph before %s:\n", m_name);
m_graph.dump();
}
+#endif
+#if DFG_ENABLE(PER_PHASE_VALIDATION)
void Phase::endPhase()
{
validate(m_graph, DumpGraph);
diff --git a/Source/JavaScriptCore/dfg/DFGPhase.h b/Source/JavaScriptCore/dfg/DFGPhase.h
index 6d13bcd25..53055a215 100644
--- a/Source/JavaScriptCore/dfg/DFGPhase.h
+++ b/Source/JavaScriptCore/dfg/DFGPhase.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
@@ -65,11 +65,14 @@ private:
// Call these hooks when starting and finishing.
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
void beginPhase();
- void endPhase();
-#else // DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+#else
void beginPhase() { }
+#endif
+#if DFG_ENABLE(PER_PHASE_VALIDATION)
+ void endPhase();
+#else
void endPhase() { }
-#endif // DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+#endif
};
template<typename PhaseType>
diff --git a/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp b/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
index 75f0b7a74..bcb79a96a 100644
--- a/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
@@ -82,20 +82,20 @@ public:
}
private:
- bool setPrediction(PredictedType prediction)
+ bool setPrediction(SpeculatedType prediction)
{
ASSERT(m_graph[m_compileIndex].hasResult());
// setPrediction() is used when we know that there is no way that we can change
// our minds about what the prediction is going to be. There is no semantic
- // difference between setPrediction() and mergePrediction() other than the
+ // difference between setPrediction() and mergeSpeculation() other than the
// increased checking to validate this property.
- ASSERT(m_graph[m_compileIndex].prediction() == PredictNone || m_graph[m_compileIndex].prediction() == prediction);
+ ASSERT(m_graph[m_compileIndex].prediction() == SpecNone || m_graph[m_compileIndex].prediction() == prediction);
return m_graph[m_compileIndex].predict(prediction);
}
- bool mergePrediction(PredictedType prediction)
+ bool mergePrediction(SpeculatedType prediction)
{
ASSERT(m_graph[m_compileIndex].hasResult());
@@ -134,13 +134,13 @@ private:
switch (op) {
case JSConstant:
case WeakJSConstant: {
- changed |= setPrediction(predictionFromValue(m_graph.valueOfJSConstant(m_compileIndex)));
+ changed |= setPrediction(speculationFromValue(m_graph.valueOfJSConstant(m_compileIndex)));
break;
}
case GetLocal: {
VariableAccessData* variableAccessData = node.variableAccessData();
- PredictedType prediction = variableAccessData->prediction();
+ SpeculatedType prediction = variableAccessData->prediction();
if (prediction)
changed |= mergePrediction(prediction);
@@ -168,7 +168,7 @@ private:
case BitRShift:
case BitLShift:
case BitURShift: {
- changed |= setPrediction(PredictInt32);
+ changed |= setPrediction(SpecInt32);
flags |= NodeUsedAsInt;
flags &= ~(NodeUsedAsNumber | NodeNeedsNegZero);
changed |= m_graph[node.child1()].mergeFlags(flags);
@@ -177,7 +177,7 @@ private:
}
case ValueToInt32: {
- changed |= setPrediction(PredictInt32);
+ changed |= setPrediction(SpecInt32);
flags |= NodeUsedAsInt;
flags &= ~(NodeUsedAsNumber | NodeNeedsNegZero);
changed |= m_graph[node.child1()].mergeFlags(flags);
@@ -205,22 +205,22 @@ private:
}
case StringCharCodeAt: {
- changed |= mergePrediction(PredictInt32);
+ changed |= mergePrediction(SpecInt32);
changed |= m_graph[node.child1()].mergeFlags(NodeUsedAsValue);
changed |= m_graph[node.child2()].mergeFlags(NodeUsedAsNumber | NodeUsedAsInt);
break;
}
case ArithMod: {
- PredictedType left = m_graph[node.child1()].prediction();
- PredictedType right = m_graph[node.child2()].prediction();
+ SpeculatedType left = m_graph[node.child1()].prediction();
+ SpeculatedType right = m_graph[node.child2()].prediction();
if (left && right) {
- if (isInt32Prediction(mergePredictions(left, right))
+ if (isInt32Speculation(mergeSpeculations(left, right))
&& nodeCanSpeculateInteger(node.arithNodeFlags()))
- changed |= mergePrediction(PredictInt32);
+ changed |= mergePrediction(SpecInt32);
else
- changed |= mergePrediction(PredictDouble);
+ changed |= mergePrediction(SpecDouble);
}
flags |= NodeUsedAsValue;
@@ -231,29 +231,29 @@ private:
case UInt32ToNumber: {
if (nodeCanSpeculateInteger(node.arithNodeFlags()))
- changed |= mergePrediction(PredictInt32);
+ changed |= mergePrediction(SpecInt32);
else
- changed |= mergePrediction(PredictNumber);
+ changed |= mergePrediction(SpecNumber);
changed |= m_graph[node.child1()].mergeFlags(flags);
break;
}
case ValueAdd: {
- PredictedType left = m_graph[node.child1()].prediction();
- PredictedType right = m_graph[node.child2()].prediction();
+ SpeculatedType left = m_graph[node.child1()].prediction();
+ SpeculatedType right = m_graph[node.child2()].prediction();
if (left && right) {
- if (isNumberPrediction(left) && isNumberPrediction(right)) {
+ if (isNumberSpeculation(left) && isNumberSpeculation(right)) {
if (m_graph.addShouldSpeculateInteger(node))
- changed |= mergePrediction(PredictInt32);
+ changed |= mergePrediction(SpecInt32);
else
- changed |= mergePrediction(PredictDouble);
- } else if (!(left & PredictNumber) || !(right & PredictNumber)) {
+ changed |= mergePrediction(SpecDouble);
+ } else if (!(left & SpecNumber) || !(right & SpecNumber)) {
// left or right is definitely something other than a number.
- changed |= mergePrediction(PredictString);
+ changed |= mergePrediction(SpecString);
} else
- changed |= mergePrediction(PredictString | PredictInt32 | PredictDouble);
+ changed |= mergePrediction(SpecString | SpecInt32 | SpecDouble);
}
if (isNotNegZero(node.child1().index()) || isNotNegZero(node.child2().index()))
@@ -265,14 +265,14 @@ private:
}
case ArithAdd: {
- PredictedType left = m_graph[node.child1()].prediction();
- PredictedType right = m_graph[node.child2()].prediction();
+ SpeculatedType left = m_graph[node.child1()].prediction();
+ SpeculatedType right = m_graph[node.child2()].prediction();
if (left && right) {
if (m_graph.addShouldSpeculateInteger(node))
- changed |= mergePrediction(PredictInt32);
+ changed |= mergePrediction(SpecInt32);
else
- changed |= mergePrediction(PredictDouble);
+ changed |= mergePrediction(SpecDouble);
}
if (isNotNegZero(node.child1().index()) || isNotNegZero(node.child2().index()))
@@ -284,14 +284,14 @@ private:
}
case ArithSub: {
- PredictedType left = m_graph[node.child1()].prediction();
- PredictedType right = m_graph[node.child2()].prediction();
+ SpeculatedType left = m_graph[node.child1()].prediction();
+ SpeculatedType right = m_graph[node.child2()].prediction();
if (left && right) {
if (m_graph.addShouldSpeculateInteger(node))
- changed |= mergePrediction(PredictInt32);
+ changed |= mergePrediction(SpecInt32);
else
- changed |= mergePrediction(PredictDouble);
+ changed |= mergePrediction(SpecDouble);
}
if (isNotZero(node.child1().index()) || isNotZero(node.child2().index()))
@@ -305,9 +305,9 @@ private:
case ArithNegate:
if (m_graph[node.child1()].prediction()) {
if (m_graph.negateShouldSpeculateInteger(node))
- changed |= mergePrediction(PredictInt32);
+ changed |= mergePrediction(SpecInt32);
else
- changed |= mergePrediction(PredictDouble);
+ changed |= mergePrediction(SpecDouble);
}
changed |= m_graph[node.child1()].mergeFlags(flags);
@@ -315,15 +315,15 @@ private:
case ArithMin:
case ArithMax: {
- PredictedType left = m_graph[node.child1()].prediction();
- PredictedType right = m_graph[node.child2()].prediction();
+ SpeculatedType left = m_graph[node.child1()].prediction();
+ SpeculatedType right = m_graph[node.child2()].prediction();
if (left && right) {
- if (isInt32Prediction(mergePredictions(left, right))
+ if (isInt32Speculation(mergeSpeculations(left, right))
&& nodeCanSpeculateInteger(node.arithNodeFlags()))
- changed |= mergePrediction(PredictInt32);
+ changed |= mergePrediction(SpecInt32);
else
- changed |= mergePrediction(PredictDouble);
+ changed |= mergePrediction(SpecDouble);
}
flags |= NodeUsedAsNumber;
@@ -333,14 +333,14 @@ private:
}
case ArithMul: {
- PredictedType left = m_graph[node.child1()].prediction();
- PredictedType right = m_graph[node.child2()].prediction();
+ SpeculatedType left = m_graph[node.child1()].prediction();
+ SpeculatedType right = m_graph[node.child2()].prediction();
if (left && right) {
if (m_graph.mulShouldSpeculateInteger(node))
- changed |= mergePrediction(PredictInt32);
+ changed |= mergePrediction(SpecInt32);
else
- changed |= mergePrediction(PredictDouble);
+ changed |= mergePrediction(SpecDouble);
}
// As soon as a multiply happens, we can easily end up in the part
@@ -355,15 +355,15 @@ private:
}
case ArithDiv: {
- PredictedType left = m_graph[node.child1()].prediction();
- PredictedType right = m_graph[node.child2()].prediction();
+ SpeculatedType left = m_graph[node.child1()].prediction();
+ SpeculatedType right = m_graph[node.child2()].prediction();
if (left && right) {
- if (isInt32Prediction(mergePredictions(left, right))
+ if (isInt32Speculation(mergeSpeculations(left, right))
&& nodeCanSpeculateInteger(node.arithNodeFlags()))
- changed |= mergePrediction(PredictInt32);
+ changed |= mergePrediction(SpecInt32);
else
- changed |= mergePrediction(PredictDouble);
+ changed |= mergePrediction(SpecDouble);
}
// As soon as a multiply happens, we can easily end up in the part
@@ -378,17 +378,17 @@ private:
}
case ArithSqrt: {
- changed |= setPrediction(PredictDouble);
+ changed |= setPrediction(SpecDouble);
changed |= m_graph[node.child1()].mergeFlags(flags | NodeUsedAsValue);
break;
}
case ArithAbs: {
- PredictedType child = m_graph[node.child1()].prediction();
+ SpeculatedType child = m_graph[node.child1()].prediction();
if (nodeCanSpeculateInteger(node.arithNodeFlags()))
changed |= mergePrediction(child);
else
- changed |= setPrediction(PredictDouble);
+ changed |= setPrediction(SpecDouble);
flags &= ~NodeNeedsNegZero;
changed |= m_graph[node.child1()].mergeFlags(flags);
@@ -409,7 +409,7 @@ private:
case IsString:
case IsObject:
case IsFunction: {
- changed |= setPrediction(PredictBoolean);
+ changed |= setPrediction(SpecBoolean);
changed |= mergeDefaultFlags(node);
break;
}
@@ -428,7 +428,7 @@ private:
case GetByVal: {
if (m_graph[node.child1()].shouldSpeculateFloat32Array()
|| m_graph[node.child1()].shouldSpeculateFloat64Array())
- changed |= mergePrediction(PredictDouble);
+ changed |= mergePrediction(SpecDouble);
else
changed |= mergePrediction(node.getHeapPrediction());
@@ -444,13 +444,13 @@ private:
}
case GetMyArgumentsLengthSafe: {
- changed |= setPrediction(PredictInt32);
+ changed |= setPrediction(SpecInt32);
break;
}
case GetPropertyStorage:
case GetIndexedPropertyStorage: {
- changed |= setPrediction(PredictOther);
+ changed |= setPrediction(SpecOther);
changed |= mergeDefaultFlags(node);
break;
}
@@ -474,11 +474,11 @@ private:
}
case ConvertThis: {
- PredictedType prediction = m_graph[node.child1()].prediction();
+ SpeculatedType prediction = m_graph[node.child1()].prediction();
if (prediction) {
- if (prediction & ~PredictObjectMask) {
- prediction &= PredictObjectMask;
- prediction = mergePredictions(prediction, PredictObjectOther);
+ if (prediction & ~SpecObjectMask) {
+ prediction &= SpecObjectMask;
+ prediction = mergeSpeculations(prediction, SpecObjectOther);
}
changed |= mergePrediction(prediction);
}
@@ -491,7 +491,8 @@ private:
break;
}
- case PutGlobalVar: {
+ case PutGlobalVar:
+ case PutGlobalVarCheck: {
changed |= m_graph[node.child1()].mergeFlags(NodeUsedAsValue);
break;
}
@@ -501,30 +502,30 @@ private:
case ResolveBase:
case ResolveBaseStrictPut:
case ResolveGlobal: {
- PredictedType prediction = node.getHeapPrediction();
+ SpeculatedType prediction = node.getHeapPrediction();
changed |= mergePrediction(prediction);
break;
}
case GetScopeChain: {
- changed |= setPrediction(PredictCellOther);
+ changed |= setPrediction(SpecCellOther);
break;
}
case GetCallee: {
- changed |= setPrediction(PredictFunction);
+ changed |= setPrediction(SpecFunction);
break;
}
case CreateThis:
case NewObject: {
- changed |= setPrediction(PredictFinalObject);
+ changed |= setPrediction(SpecFinalObject);
changed |= mergeDefaultFlags(node);
break;
}
case NewArray: {
- changed |= setPrediction(PredictArray);
+ changed |= setPrediction(SpecArray);
for (unsigned childIdx = node.firstChild();
childIdx < node.firstChild() + node.numChildren();
++childIdx) {
@@ -535,24 +536,24 @@ private:
}
case NewArrayBuffer: {
- changed |= setPrediction(PredictArray);
+ changed |= setPrediction(SpecArray);
break;
}
case NewRegexp: {
- changed |= setPrediction(PredictObjectOther);
+ changed |= setPrediction(SpecObjectOther);
break;
}
case StringCharAt: {
- changed |= setPrediction(PredictString);
+ changed |= setPrediction(SpecString);
changed |= m_graph[node.child1()].mergeFlags(NodeUsedAsValue);
changed |= m_graph[node.child2()].mergeFlags(NodeUsedAsNumber | NodeUsedAsInt);
break;
}
case StrCat: {
- changed |= setPrediction(PredictString);
+ changed |= setPrediction(SpecString);
for (unsigned childIdx = node.firstChild();
childIdx < node.firstChild() + node.numChildren();
++childIdx)
@@ -561,20 +562,20 @@ private:
}
case ToPrimitive: {
- PredictedType child = m_graph[node.child1()].prediction();
+ SpeculatedType child = m_graph[node.child1()].prediction();
if (child) {
- if (isObjectPrediction(child)) {
+ if (isObjectSpeculation(child)) {
// I'd love to fold this case into the case below, but I can't, because
- // removing PredictObjectMask from something that only has an object
- // prediction and nothing else means we have an ill-formed PredictedType
+ // removing SpecObjectMask from something that only has an object
+ // prediction and nothing else means we have an ill-formed SpeculatedType
// (strong predict-none). This should be killed once we remove all traces
// of static (aka weak) predictions.
- changed |= mergePrediction(PredictString);
- } else if (child & PredictObjectMask) {
+ changed |= mergePrediction(SpecString);
+ } else if (child & SpecObjectMask) {
// Objects get turned into strings. So if the input has hints of objectness,
// the output will have hinsts of stringiness.
changed |= mergePrediction(
- mergePredictions(child & ~PredictObjectMask, PredictString));
+ mergeSpeculations(child & ~SpecObjectMask, SpecString));
} else
changed |= mergePrediction(child);
}
@@ -583,21 +584,21 @@ private:
}
case CreateActivation: {
- changed |= setPrediction(PredictObjectOther);
+ changed |= setPrediction(SpecObjectOther);
break;
}
case CreateArguments: {
// At this stage we don't try to predict whether the arguments are ours or
// someone else's. We could, but we don't, yet.
- changed |= setPrediction(PredictArguments);
+ changed |= setPrediction(SpecArguments);
break;
}
case NewFunction:
case NewFunctionNoCheck:
case NewFunctionExpression: {
- changed |= setPrediction(PredictFunction);
+ changed |= setPrediction(SpecFunction);
break;
}
@@ -663,12 +664,14 @@ private:
case ForceOSRExit:
case SetArgument:
case CheckStructure:
+ case StructureTransitionWatchpoint:
case CheckFunction:
case PutStructure:
case TearOffActivation:
case TearOffArguments:
case CheckNumber:
case CheckArgumentsNotCreated:
+ case GlobalVarWatchpoint:
changed |= mergeDefaultFlags(node);
break;
@@ -689,7 +692,7 @@ private:
}
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
- dataLog("%s\n", predictionToString(m_graph[m_compileIndex].prediction()));
+ dataLog("%s\n", speculationToString(m_graph[m_compileIndex].prediction()));
#endif
m_changed |= changed;
@@ -784,12 +787,12 @@ private:
case ValueAdd:
case ArithAdd:
case ArithSub: {
- PredictedType left = m_graph[node.child1()].prediction();
- PredictedType right = m_graph[node.child2()].prediction();
+ SpeculatedType left = m_graph[node.child1()].prediction();
+ SpeculatedType right = m_graph[node.child2()].prediction();
VariableAccessData::Ballot ballot;
- if (isNumberPrediction(left) && isNumberPrediction(right)
+ if (isNumberSpeculation(left) && isNumberSpeculation(right)
&& !m_graph.addShouldSpeculateInteger(node))
ballot = VariableAccessData::VoteDouble;
else
@@ -801,12 +804,12 @@ private:
}
case ArithMul: {
- PredictedType left = m_graph[node.child1()].prediction();
- PredictedType right = m_graph[node.child2()].prediction();
+ SpeculatedType left = m_graph[node.child1()].prediction();
+ SpeculatedType right = m_graph[node.child2()].prediction();
VariableAccessData::Ballot ballot;
- if (isNumberPrediction(left) && isNumberPrediction(right)
+ if (isNumberSpeculation(left) && isNumberSpeculation(right)
&& !m_graph.mulShouldSpeculateInteger(node))
ballot = VariableAccessData::VoteDouble;
else
@@ -821,12 +824,12 @@ private:
case ArithMax:
case ArithMod:
case ArithDiv: {
- PredictedType left = m_graph[node.child1()].prediction();
- PredictedType right = m_graph[node.child2()].prediction();
+ SpeculatedType left = m_graph[node.child1()].prediction();
+ SpeculatedType right = m_graph[node.child2()].prediction();
VariableAccessData::Ballot ballot;
- if (isNumberPrediction(left) && isNumberPrediction(right)
+ if (isNumberSpeculation(left) && isNumberSpeculation(right)
&& !(Node::shouldSpeculateInteger(m_graph[node.child1()], m_graph[node.child1()])
&& node.canSpeculateInteger()))
ballot = VariableAccessData::VoteDouble;
@@ -854,10 +857,10 @@ private:
break;
case SetLocal: {
- PredictedType prediction = m_graph[node.child1()].prediction();
- if (isDoublePrediction(prediction))
+ SpeculatedType prediction = m_graph[node.child1()].prediction();
+ if (isDoubleSpeculation(prediction))
node.variableAccessData()->vote(VariableAccessData::VoteDouble);
- else if (!isNumberPrediction(prediction) || isInt32Prediction(prediction))
+ else if (!isNumberSpeculation(prediction) || isInt32Speculation(prediction))
node.variableAccessData()->vote(VariableAccessData::VoteValue);
break;
}
diff --git a/Source/JavaScriptCore/dfg/DFGRepatch.cpp b/Source/JavaScriptCore/dfg/DFGRepatch.cpp
index 794538184..9c3391be5 100644
--- a/Source/JavaScriptCore/dfg/DFGRepatch.cpp
+++ b/Source/JavaScriptCore/dfg/DFGRepatch.cpp
@@ -155,7 +155,10 @@ static void generateProtoChainAccessStub(ExecState* exec, StructureStubInfo& stu
linkRestoreScratch(patchBuffer, needToRestoreScratch, success, fail, failureCases, successLabel, slowCaseLabel);
- stubRoutine = patchBuffer.finalizeCode();
+ stubRoutine = FINALIZE_CODE(
+ patchBuffer,
+ ("DFG prototype chain access stub for CodeBlock %p, return point %p",
+ exec->codeBlock(), successLabel.executableAddress()));
}
static bool tryCacheGetByID(ExecState* exec, JSValue baseValue, const Identifier& propertyName, const PropertySlot& slot, StructureStubInfo& stubInfo)
@@ -206,7 +209,11 @@ static bool tryCacheGetByID(ExecState* exec, JSValue baseValue, const Identifier
linkRestoreScratch(patchBuffer, needToRestoreScratch, stubInfo, success, fail, failureCases);
- stubInfo.stubRoutine = patchBuffer.finalizeCode();
+ stubInfo.stubRoutine = FINALIZE_CODE(
+ patchBuffer,
+ ("DFG GetById array length stub for CodeBlock %p, return point %p",
+ exec->codeBlock(), stubInfo.callReturnLocation.labelAtOffset(
+ stubInfo.patch.dfg.deltaCallToDone).executableAddress()));
RepatchBuffer repatchBuffer(codeBlock);
repatchBuffer.relink(stubInfo.callReturnLocation.jumpAtOffset(stubInfo.patch.dfg.deltaCallToStructCheck), CodeLocationLabel(stubInfo.stubRoutine.code()));
@@ -261,7 +268,7 @@ static bool tryCacheGetByID(ExecState* exec, JSValue baseValue, const Identifier
repatchBuffer.relink(stubInfo.callReturnLocation.jumpAtOffset(stubInfo.patch.dfg.deltaCallToStructCheck), CodeLocationLabel(stubInfo.stubRoutine.code()));
repatchBuffer.relink(stubInfo.callReturnLocation, operationGetByIdProtoBuildList);
- stubInfo.initGetByIdChain(*globalData, codeBlock->ownerExecutable(), structure, prototypeChain);
+ stubInfo.initGetByIdChain(*globalData, codeBlock->ownerExecutable(), structure, prototypeChain, count, true);
return true;
}
@@ -405,7 +412,11 @@ static bool tryBuildGetByIDList(ExecState* exec, JSValue baseValue, const Identi
patchBuffer.link(handlerCall, lookupExceptionHandlerInStub);
}
- MacroAssemblerCodeRef stubRoutine = patchBuffer.finalizeCode();
+ MacroAssemblerCodeRef stubRoutine = FINALIZE_CODE(
+ patchBuffer,
+ ("DFG GetById polymorphic list access for CodeBlock %p, return point %p",
+ exec->codeBlock(), stubInfo.callReturnLocation.labelAtOffset(
+ stubInfo.patch.dfg.deltaCallToDone).executableAddress()));
polymorphicStructureList->list[listIndex].set(*globalData, codeBlock->ownerExecutable(), stubRoutine, structure, isDirect);
@@ -611,7 +622,11 @@ static void emitPutReplaceStub(
patchBuffer.link(success, stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.dfg.deltaCallToDone));
patchBuffer.link(failure, failureLabel);
- stubRoutine = patchBuffer.finalizeCode();
+ stubRoutine = FINALIZE_CODE(
+ patchBuffer,
+ ("DFG PutById replace stub for CodeBlock %p, return point %p",
+ exec->codeBlock(), stubInfo.callReturnLocation.labelAtOffset(
+ stubInfo.patch.dfg.deltaCallToDone).executableAddress()));
}
static void emitPutTransitionStub(
@@ -649,6 +664,8 @@ static void emitPutTransitionStub(
needToRestoreScratch = true;
}
+ ASSERT(oldStructure->transitionWatchpointSetHasBeenInvalidated());
+
failureCases.append(stubJit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::structureOffset()), MacroAssembler::TrustedImmPtr(oldStructure)));
testPrototype(stubJit, scratchGPR, oldStructure->storedPrototype(), failureCases);
@@ -705,7 +722,11 @@ static void emitPutTransitionStub(
else
patchBuffer.link(failureCases, failureLabel);
- stubRoutine = patchBuffer.finalizeCode();
+ stubRoutine = FINALIZE_CODE(
+ patchBuffer,
+ ("DFG PutById transition stub for CodeBlock %p, return point %p",
+ exec->codeBlock(), stubInfo.callReturnLocation.labelAtOffset(
+ stubInfo.patch.dfg.deltaCallToDone).executableAddress()));
}
static bool tryCachePutByID(ExecState* exec, JSValue baseValue, const Identifier& ident, const PutPropertySlot& slot, StructureStubInfo& stubInfo, PutKind putKind)
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
index 9b82121b3..852f74387 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
@@ -292,7 +292,7 @@ void SpeculativeJIT::writeBarrier(GPRReg ownerGPR, GPRReg valueGPR, Edge valueUs
JITCompiler::Jump rhsNotCell;
bool hadCellCheck = false;
- if (!isKnownCell(valueUse.index()) && !isCellPrediction(m_jit.getPrediction(valueUse.index()))) {
+ if (!isKnownCell(valueUse.index()) && !isCellSpeculation(m_jit.getSpeculation(valueUse.index()))) {
hadCellCheck = true;
rhsNotCell = m_jit.branchIfNotCell(valueGPR);
}
@@ -354,7 +354,7 @@ void SpeculativeJIT::writeBarrier(JSCell* owner, GPRReg valueGPR, Edge valueUse,
#if ENABLE(GGC)
JITCompiler::Jump rhsNotCell;
bool hadCellCheck = false;
- if (!isKnownCell(valueUse.index()) && !isCellPrediction(m_jit.getPrediction(valueUse.index()))) {
+ if (!isKnownCell(valueUse.index()) && !isCellSpeculation(m_jit.getSpeculation(valueUse.index()))) {
hadCellCheck = true;
rhsNotCell = m_jit.branchIfNotCell(valueGPR);
}
@@ -826,7 +826,7 @@ void SpeculativeJIT::compilePeepHoleDoubleBranch(Node& node, NodeIndex branchNod
jump(notTaken);
}
-void SpeculativeJIT::compilePeepHoleObjectEquality(Node& node, NodeIndex branchNodeIndex, const ClassInfo* classInfo, PredictionChecker predictionCheck)
+void SpeculativeJIT::compilePeepHoleObjectEquality(Node& node, NodeIndex branchNodeIndex, const ClassInfo* classInfo, SpeculatedTypeChecker speculatedTypeChecker)
{
Node& branchNode = at(branchNodeIndex);
BlockIndex taken = branchNode.takenBlockIndex();
@@ -847,9 +847,9 @@ void SpeculativeJIT::compilePeepHoleObjectEquality(Node& node, NodeIndex branchN
GPRReg op1GPR = op1.gpr();
GPRReg op2GPR = op2.gpr();
- if (!predictionCheck(m_state.forNode(node.child1()).m_type))
+ if (!speculatedTypeChecker(m_state.forNode(node.child1()).m_type))
speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), node.child1().index(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1GPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(classInfo)));
- if (!predictionCheck(m_state.forNode(node.child2()).m_type))
+ if (!speculatedTypeChecker(m_state.forNode(node.child2()).m_type))
speculationCheck(BadType, JSValueSource::unboxedCell(op2GPR), node.child2().index(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op2GPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(classInfo)));
branchPtr(condition, op1GPR, op2GPR, taken);
@@ -909,32 +909,32 @@ bool SpeculativeJIT::compilePeepHoleBranch(Node& node, MacroAssembler::Relationa
at(node.child1()), at(node.child2()))) {
compilePeepHoleObjectEquality(
node, branchNodeIndex, &JSFinalObject::s_info,
- isFinalObjectPrediction);
+ isFinalObjectSpeculation);
} else if (Node::shouldSpeculateArray(
at(node.child1()), at(node.child2()))) {
compilePeepHoleObjectEquality(
node, branchNodeIndex, &JSArray::s_info,
- isArrayPrediction);
+ isArraySpeculation);
} else if (at(node.child1()).shouldSpeculateFinalObject()
&& at(node.child2()).shouldSpeculateFinalObjectOrOther()) {
compilePeepHoleObjectToObjectOrOtherEquality(
node.child1(), node.child2(), branchNodeIndex,
- &JSFinalObject::s_info, isFinalObjectPrediction);
+ &JSFinalObject::s_info, isFinalObjectSpeculation);
} else if (at(node.child1()).shouldSpeculateFinalObjectOrOther()
&& at(node.child2()).shouldSpeculateFinalObject()) {
compilePeepHoleObjectToObjectOrOtherEquality(
node.child2(), node.child1(), branchNodeIndex,
- &JSFinalObject::s_info, isFinalObjectPrediction);
+ &JSFinalObject::s_info, isFinalObjectSpeculation);
} else if (at(node.child1()).shouldSpeculateArray()
&& at(node.child2()).shouldSpeculateArrayOrOther()) {
compilePeepHoleObjectToObjectOrOtherEquality(
node.child1(), node.child2(), branchNodeIndex,
- &JSArray::s_info, isArrayPrediction);
+ &JSArray::s_info, isArraySpeculation);
} else if (at(node.child1()).shouldSpeculateArrayOrOther()
&& at(node.child2()).shouldSpeculateArray()) {
compilePeepHoleObjectToObjectOrOtherEquality(
node.child2(), node.child1(), branchNodeIndex,
- &JSArray::s_info, isArrayPrediction);
+ &JSArray::s_info, isArraySpeculation);
} else {
nonSpeculativePeepholeBranch(node, branchNodeIndex, condition, operation);
return true;
@@ -991,7 +991,7 @@ void SpeculativeJIT::compile(BasicBlock& block)
if (nodeIndex == NoNode || m_jit.codeBlock()->argumentIsCaptured(i))
m_arguments[i] = ValueSource(ValueInRegisterFile);
else
- m_arguments[i] = ValueSource::forPrediction(at(nodeIndex).variableAccessData()->prediction());
+ m_arguments[i] = ValueSource::forSpeculation(at(nodeIndex).variableAccessData()->prediction());
}
m_state.reset();
@@ -1011,7 +1011,7 @@ void SpeculativeJIT::compile(BasicBlock& block)
else if (at(nodeIndex).variableAccessData()->shouldUseDoubleFormat())
m_variables[i] = ValueSource(DoubleInRegisterFile);
else
- m_variables[i] = ValueSource::forPrediction(at(nodeIndex).variableAccessData()->argumentAwarePrediction());
+ m_variables[i] = ValueSource::forSpeculation(at(nodeIndex).variableAccessData()->argumentAwarePrediction());
}
m_lastSetOperand = std::numeric_limits<int>::max();
@@ -1040,8 +1040,29 @@ void SpeculativeJIT::compile(BasicBlock& block)
case InlineStart: {
InlineCallFrame* inlineCallFrame = node.codeOrigin.inlineCallFrame;
int argumentCountIncludingThis = inlineCallFrame->arguments.size();
+ unsigned argumentPositionStart = node.argumentPositionStart();
+ bool argumentsAreCaptured =
+ baselineCodeBlockForInlineCallFrame(inlineCallFrame)->argumentsAreCaptured();
for (int i = 0; i < argumentCountIncludingThis; ++i) {
- ValueRecovery recovery = computeValueRecoveryFor(m_variables[inlineCallFrame->stackOffset + CallFrame::argumentOffsetIncludingThis(i)]);
+ ValueRecovery recovery;
+ if (argumentsAreCaptured)
+ recovery = ValueRecovery::alreadyInRegisterFile();
+ else {
+ ArgumentPosition& argumentPosition =
+ m_jit.graph().m_argumentPositions[argumentPositionStart + i];
+ ValueSource valueSource;
+ if (argumentPosition.shouldUseDoubleFormat())
+ valueSource = ValueSource(DoubleInRegisterFile);
+ else if (isInt32Speculation(argumentPosition.prediction()))
+ valueSource = ValueSource(Int32InRegisterFile);
+ else if (isArraySpeculation(argumentPosition.prediction()))
+ valueSource = ValueSource(CellInRegisterFile);
+ else if (isBooleanSpeculation(argumentPosition.prediction()))
+ valueSource = ValueSource(BooleanInRegisterFile);
+ else
+ valueSource = ValueSource(ValueInRegisterFile);
+ recovery = computeValueRecoveryFor(valueSource);
+ }
// The recovery should refer either to something that has already been
// stored into the register file at the right place, or to a constant,
// since the Arguments code isn't smart enough to handle anything else.
@@ -1051,12 +1072,15 @@ void SpeculativeJIT::compile(BasicBlock& block)
dataLog("\nRecovery for argument %d: ", i);
recovery.dump(WTF::dataFile());
#endif
- ASSERT(!i || (recovery.isAlreadyInRegisterFile() || recovery.isConstant()));
inlineCallFrame->arguments[i] = recovery;
}
break;
}
+ case WeakJSConstant:
+ m_jit.addWeakReference(node.weakConstant());
+ break;
+
default:
break;
}
@@ -1154,129 +1178,129 @@ void SpeculativeJIT::checkArgumentTypes()
VariableAccessData* variableAccessData = node.variableAccessData();
VirtualRegister virtualRegister = variableAccessData->local();
- PredictedType predictedType = variableAccessData->prediction();
+ SpeculatedType predictedType = variableAccessData->prediction();
JSValueSource valueSource = JSValueSource(JITCompiler::addressFor(virtualRegister));
#if USE(JSVALUE64)
- if (isInt32Prediction(predictedType))
+ if (isInt32Speculation(predictedType))
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::Below, JITCompiler::addressFor(virtualRegister), GPRInfo::tagTypeNumberRegister));
- else if (isArrayPrediction(predictedType)) {
+ else if (isArraySpeculation(predictedType)) {
GPRTemporary temp(this);
m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
- } else if (isBooleanPrediction(predictedType)) {
+ } else if (isBooleanSpeculation(predictedType)) {
GPRTemporary temp(this);
m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), temp.gpr());
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), TrustedImm32(static_cast<int32_t>(~1))));
- } else if (isInt8ArrayPrediction(predictedType)) {
+ } else if (isInt8ArraySpeculation(predictedType)) {
GPRTemporary temp(this);
m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->int8ArrayDescriptor().m_classInfo)));
- } else if (isInt16ArrayPrediction(predictedType)) {
+ } else if (isInt16ArraySpeculation(predictedType)) {
GPRTemporary temp(this);
m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->int16ArrayDescriptor().m_classInfo)));
- } else if (isInt32ArrayPrediction(predictedType)) {
+ } else if (isInt32ArraySpeculation(predictedType)) {
GPRTemporary temp(this);
m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->int32ArrayDescriptor().m_classInfo)));
- } else if (isUint8ArrayPrediction(predictedType)) {
+ } else if (isUint8ArraySpeculation(predictedType)) {
GPRTemporary temp(this);
m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint8ArrayDescriptor().m_classInfo)));
- } else if (isUint8ClampedArrayPrediction(predictedType)) {
+ } else if (isUint8ClampedArraySpeculation(predictedType)) {
GPRTemporary temp(this);
m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint8ClampedArrayDescriptor().m_classInfo)));
- } else if (isUint16ArrayPrediction(predictedType)) {
+ } else if (isUint16ArraySpeculation(predictedType)) {
GPRTemporary temp(this);
m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint16ArrayDescriptor().m_classInfo)));
- } else if (isUint32ArrayPrediction(predictedType)) {
+ } else if (isUint32ArraySpeculation(predictedType)) {
GPRTemporary temp(this);
m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint32ArrayDescriptor().m_classInfo)));
- } else if (isFloat32ArrayPrediction(predictedType)) {
+ } else if (isFloat32ArraySpeculation(predictedType)) {
GPRTemporary temp(this);
m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->float32ArrayDescriptor().m_classInfo)));
- } else if (isFloat64ArrayPrediction(predictedType)) {
+ } else if (isFloat64ArraySpeculation(predictedType)) {
GPRTemporary temp(this);
m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->float64ArrayDescriptor().m_classInfo)));
}
#else
- if (isInt32Prediction(predictedType))
+ if (isInt32Speculation(predictedType))
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::Int32Tag)));
- else if (isArrayPrediction(predictedType)) {
+ else if (isArraySpeculation(predictedType)) {
GPRTemporary temp(this);
m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
- } else if (isBooleanPrediction(predictedType))
+ } else if (isBooleanSpeculation(predictedType))
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::BooleanTag)));
- else if (isInt8ArrayPrediction(predictedType)) {
+ else if (isInt8ArraySpeculation(predictedType)) {
GPRTemporary temp(this);
m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->int8ArrayDescriptor().m_classInfo)));
- } else if (isInt16ArrayPrediction(predictedType)) {
+ } else if (isInt16ArraySpeculation(predictedType)) {
GPRTemporary temp(this);
m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->int16ArrayDescriptor().m_classInfo)));
- } else if (isInt32ArrayPrediction(predictedType)) {
+ } else if (isInt32ArraySpeculation(predictedType)) {
GPRTemporary temp(this);
m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->int32ArrayDescriptor().m_classInfo)));
- } else if (isUint8ArrayPrediction(predictedType)) {
+ } else if (isUint8ArraySpeculation(predictedType)) {
GPRTemporary temp(this);
m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint8ArrayDescriptor().m_classInfo)));
- } else if (isUint8ClampedArrayPrediction(predictedType)) {
+ } else if (isUint8ClampedArraySpeculation(predictedType)) {
GPRTemporary temp(this);
m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint8ClampedArrayDescriptor().m_classInfo)));
- } else if (isUint16ArrayPrediction(predictedType)) {
+ } else if (isUint16ArraySpeculation(predictedType)) {
GPRTemporary temp(this);
m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint16ArrayDescriptor().m_classInfo)));
- } else if (isUint32ArrayPrediction(predictedType)) {
+ } else if (isUint32ArraySpeculation(predictedType)) {
GPRTemporary temp(this);
m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint32ArrayDescriptor().m_classInfo)));
- } else if (isFloat32ArrayPrediction(predictedType)) {
+ } else if (isFloat32ArraySpeculation(predictedType)) {
GPRTemporary temp(this);
m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->float32ArrayDescriptor().m_classInfo)));
- } else if (isFloat64ArrayPrediction(predictedType)) {
+ } else if (isFloat64ArraySpeculation(predictedType)) {
GPRTemporary temp(this);
m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
@@ -1506,8 +1530,8 @@ void SpeculativeJIT::compileGetCharCodeAt(Node& node)
GPRReg indexReg = index.gpr();
GPRReg storageReg = storage.gpr();
- if (!isStringPrediction(m_state.forNode(node.child1()).m_type)) {
- ASSERT(!(at(node.child1()).prediction() & PredictString));
+ if (!isStringSpeculation(m_state.forNode(node.child1()).m_type)) {
+ ASSERT(!(at(node.child1()).prediction() & SpecString));
terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
noResult(m_compileIndex);
return;
@@ -1545,8 +1569,8 @@ void SpeculativeJIT::compileGetByValOnString(Node& node)
GPRReg propertyReg = property.gpr();
GPRReg storageReg = storage.gpr();
- if (!isStringPrediction(m_state.forNode(node.child1()).m_type)) {
- ASSERT(!(at(node.child1()).prediction() & PredictString));
+ if (!isStringSpeculation(m_state.forNode(node.child1()).m_type)) {
+ ASSERT(!(at(node.child1()).prediction() & SpecString));
terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
noResult(m_compileIndex);
return;
@@ -1680,7 +1704,7 @@ void SpeculativeJIT::compileValueToInt32(Node& node)
JITCompiler::Jump isInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, gpr, GPRInfo::tagTypeNumberRegister);
- if (!isNumberPrediction(m_state.forNode(node.child1()).m_type))
+ if (!isNumberSpeculation(m_state.forNode(node.child1()).m_type))
speculationCheck(BadType, JSValueRegs(gpr), node.child1().index(), m_jit.branchTestPtr(MacroAssembler::Zero, gpr, GPRInfo::tagTypeNumberRegister));
// First, if we get here we have a double encoded as a JSValue
@@ -1717,7 +1741,7 @@ void SpeculativeJIT::compileValueToInt32(Node& node)
JITCompiler::Jump isInteger = m_jit.branch32(MacroAssembler::Equal, tagGPR, TrustedImm32(JSValue::Int32Tag));
- if (!isNumberPrediction(m_state.forNode(node.child1()).m_type))
+ if (!isNumberSpeculation(m_state.forNode(node.child1()).m_type))
speculationCheck(BadType, JSValueRegs(tagGPR, payloadGPR), node.child1().index(), m_jit.branch32(MacroAssembler::AboveOrEqual, tagGPR, TrustedImm32(JSValue::LowestTag)));
unboxDouble(tagGPR, payloadGPR, fpr, scratch.fpr());
@@ -1829,7 +1853,7 @@ void SpeculativeJIT::compileInt32ToDouble(Node& node)
}
#endif
- if (isInt32Prediction(m_state.forNode(node.child1()).m_type)) {
+ if (isInt32Speculation(m_state.forNode(node.child1()).m_type)) {
SpeculateIntegerOperand op1(this, node.child1());
FPRTemporary result(this);
m_jit.convertInt32ToDouble(op1.gpr(), result.fpr());
@@ -1850,9 +1874,11 @@ void SpeculativeJIT::compileInt32ToDouble(Node& node)
JITCompiler::Jump isInteger = m_jit.branchPtr(
MacroAssembler::AboveOrEqual, op1GPR, GPRInfo::tagTypeNumberRegister);
- speculationCheck(
- BadType, JSValueRegs(op1GPR), node.child1(),
- m_jit.branchTestPtr(MacroAssembler::Zero, op1GPR, GPRInfo::tagTypeNumberRegister));
+ if (!isNumberSpeculation(m_state.forNode(node.child1()).m_type)) {
+ speculationCheck(
+ BadType, JSValueRegs(op1GPR), node.child1(),
+ m_jit.branchTestPtr(MacroAssembler::Zero, op1GPR, GPRInfo::tagTypeNumberRegister));
+ }
m_jit.move(op1GPR, tempGPR);
unboxDouble(tempGPR, resultFPR);
@@ -1872,9 +1898,11 @@ void SpeculativeJIT::compileInt32ToDouble(Node& node)
JITCompiler::Jump isInteger = m_jit.branch32(
MacroAssembler::Equal, op1TagGPR, TrustedImm32(JSValue::Int32Tag));
- speculationCheck(
- BadType, JSValueRegs(op1TagGPR, op1PayloadGPR), node.child1(),
- m_jit.branch32(MacroAssembler::AboveOrEqual, op1TagGPR, TrustedImm32(JSValue::LowestTag)));
+ if (!isNumberSpeculation(m_state.forNode(node.child1()).m_type)) {
+ speculationCheck(
+ BadType, JSValueRegs(op1TagGPR, op1PayloadGPR), node.child1(),
+ m_jit.branch32(MacroAssembler::AboveOrEqual, op1TagGPR, TrustedImm32(JSValue::LowestTag)));
+ }
unboxDouble(op1TagGPR, op1PayloadGPR, resultFPR, tempFPR);
JITCompiler::Jump done = m_jit.jump();
@@ -2245,8 +2273,8 @@ void SpeculativeJIT::compileInstanceOfForObject(Node&, GPRReg valueReg, GPRReg p
void SpeculativeJIT::compileInstanceOf(Node& node)
{
- if ((!!(at(node.child1()).prediction() & ~PredictCell)
- && !!(m_state.forNode(node.child1()).m_type & ~PredictCell))
+ if ((!!(at(node.child1()).prediction() & ~SpecCell)
+ && !!(m_state.forNode(node.child1()).m_type & ~SpecCell))
|| at(node.child1()).adjustedRefCount() == 1) {
// It might not be a cell. Speculate less aggressively.
// Or: it might only be used once (i.e. by us), so we get zero benefit
@@ -2780,12 +2808,12 @@ bool SpeculativeJIT::compare(Node& node, MacroAssembler::RelationalCondition con
if (node.op() == CompareEq) {
if (Node::shouldSpeculateFinalObject(at(node.child1()), at(node.child2()))) {
- compileObjectEquality(node, &JSFinalObject::s_info, isFinalObjectPrediction);
+ compileObjectEquality(node, &JSFinalObject::s_info, isFinalObjectSpeculation);
return false;
}
if (Node::shouldSpeculateArray(at(node.child1()), at(node.child2()))) {
- compileObjectEquality(node, &JSArray::s_info, isArrayPrediction);
+ compileObjectEquality(node, &JSArray::s_info, isArraySpeculation);
return false;
}
@@ -2793,7 +2821,7 @@ bool SpeculativeJIT::compare(Node& node, MacroAssembler::RelationalCondition con
&& at(node.child2()).shouldSpeculateFinalObjectOrOther()) {
compileObjectToObjectOrOtherEquality(
node.child1(), node.child2(), &JSFinalObject::s_info,
- isFinalObjectPrediction);
+ isFinalObjectSpeculation);
return false;
}
@@ -2801,7 +2829,7 @@ bool SpeculativeJIT::compare(Node& node, MacroAssembler::RelationalCondition con
&& at(node.child2()).shouldSpeculateFinalObject()) {
compileObjectToObjectOrOtherEquality(
node.child2(), node.child1(), &JSFinalObject::s_info,
- isFinalObjectPrediction);
+ isFinalObjectSpeculation);
return false;
}
@@ -2809,7 +2837,7 @@ bool SpeculativeJIT::compare(Node& node, MacroAssembler::RelationalCondition con
&& at(node.child2()).shouldSpeculateArrayOrOther()) {
compileObjectToObjectOrOtherEquality(
node.child1(), node.child2(), &JSArray::s_info,
- isArrayPrediction);
+ isArraySpeculation);
return false;
}
@@ -2817,7 +2845,7 @@ bool SpeculativeJIT::compare(Node& node, MacroAssembler::RelationalCondition con
&& at(node.child2()).shouldSpeculateArray()) {
compileObjectToObjectOrOtherEquality(
node.child2(), node.child1(), &JSArray::s_info,
- isArrayPrediction);
+ isArraySpeculation);
return false;
}
}
@@ -2957,14 +2985,14 @@ bool SpeculativeJIT::compileStrictEq(Node& node)
unsigned branchIndexInBlock = detectPeepHoleBranch();
if (branchIndexInBlock != UINT_MAX) {
NodeIndex branchNodeIndex = m_jit.graph().m_blocks[m_block]->at(branchIndexInBlock);
- compilePeepHoleObjectEquality(node, branchNodeIndex, &JSFinalObject::s_info, isFinalObjectPrediction);
+ compilePeepHoleObjectEquality(node, branchNodeIndex, &JSFinalObject::s_info, isFinalObjectSpeculation);
use(node.child1());
use(node.child2());
m_indexInBlock = branchIndexInBlock;
m_compileIndex = branchNodeIndex;
return true;
}
- compileObjectEquality(node, &JSFinalObject::s_info, isFinalObjectPrediction);
+ compileObjectEquality(node, &JSFinalObject::s_info, isFinalObjectSpeculation);
return false;
}
@@ -2972,14 +3000,14 @@ bool SpeculativeJIT::compileStrictEq(Node& node)
unsigned branchIndexInBlock = detectPeepHoleBranch();
if (branchIndexInBlock != UINT_MAX) {
NodeIndex branchNodeIndex = m_jit.graph().m_blocks[m_block]->at(branchIndexInBlock);
- compilePeepHoleObjectEquality(node, branchNodeIndex, &JSArray::s_info, isArrayPrediction);
+ compilePeepHoleObjectEquality(node, branchNodeIndex, &JSArray::s_info, isArraySpeculation);
use(node.child1());
use(node.child2());
m_indexInBlock = branchIndexInBlock;
m_compileIndex = branchNodeIndex;
return true;
}
- compileObjectEquality(node, &JSArray::s_info, isArrayPrediction);
+ compileObjectEquality(node, &JSArray::s_info, isArraySpeculation);
return false;
}
@@ -2998,8 +3026,8 @@ void SpeculativeJIT::compileGetIndexedPropertyStorage(Node& node)
SpeculateCellOperand base(this, node.child1());
GPRReg baseReg = base.gpr();
- PredictedType basePrediction = at(node.child2()).prediction();
- if (!(basePrediction & PredictInt32) && basePrediction) {
+ SpeculatedType basePrediction = at(node.child2()).prediction();
+ if (!(basePrediction & SpecInt32) && basePrediction) {
ASSERT_NOT_REACHED();
terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
noResult(m_compileIndex);
@@ -3010,8 +3038,8 @@ void SpeculativeJIT::compileGetIndexedPropertyStorage(Node& node)
GPRReg storageReg = storage.gpr();
if (at(node.child1()).shouldSpeculateArguments()) {
ASSERT_NOT_REACHED();
- } else if (at(node.child1()).prediction() == PredictString) {
- if (!isStringPrediction(m_state.forNode(node.child1()).m_type))
+ } else if (at(node.child1()).prediction() == SpecString) {
+ if (!isStringSpeculation(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(&JSString::s_info)));
m_jit.loadPtr(MacroAssembler::Address(baseReg, JSString::offsetOfValue()), storageReg);
@@ -3022,51 +3050,51 @@ void SpeculativeJIT::compileGetIndexedPropertyStorage(Node& node)
m_jit.loadPtr(MacroAssembler::Address(storageReg, StringImpl::dataOffset()), storageReg);
} else if (at(node.child1()).shouldSpeculateInt8Array()) {
const TypedArrayDescriptor& descriptor = m_jit.globalData()->int8ArrayDescriptor();
- if (!isInt8ArrayPrediction(m_state.forNode(node.child1()).m_type))
+ if (!isInt8ArraySpeculation(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()).shouldSpeculateInt16Array()) {
const TypedArrayDescriptor& descriptor = m_jit.globalData()->int16ArrayDescriptor();
- if (!isInt16ArrayPrediction(m_state.forNode(node.child1()).m_type))
+ if (!isInt16ArraySpeculation(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()).shouldSpeculateInt32Array()) {
const TypedArrayDescriptor& descriptor = m_jit.globalData()->int32ArrayDescriptor();
- if (!isInt32ArrayPrediction(m_state.forNode(node.child1()).m_type))
+ if (!isInt32ArraySpeculation(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()).shouldSpeculateUint8Array()) {
const TypedArrayDescriptor& descriptor = m_jit.globalData()->uint8ArrayDescriptor();
- if (!isUint8ArrayPrediction(m_state.forNode(node.child1()).m_type))
+ if (!isUint8ArraySpeculation(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))
+ if (!isUint8ClampedArraySpeculation(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))
+ if (!isUint16ArraySpeculation(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()).shouldSpeculateUint32Array()) {
const TypedArrayDescriptor& descriptor = m_jit.globalData()->uint32ArrayDescriptor();
- if (!isUint32ArrayPrediction(m_state.forNode(node.child1()).m_type))
+ if (!isUint32ArraySpeculation(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()).shouldSpeculateFloat32Array()) {
const TypedArrayDescriptor& descriptor = m_jit.globalData()->float32ArrayDescriptor();
- if (!isFloat32ArrayPrediction(m_state.forNode(node.child1()).m_type))
+ if (!isFloat32ArraySpeculation(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()).shouldSpeculateFloat64Array()) {
const TypedArrayDescriptor& descriptor = m_jit.globalData()->float64ArrayDescriptor();
- if (!isFloat64ArrayPrediction(m_state.forNode(node.child1()).m_type))
+ if (!isFloat64ArraySpeculation(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 (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
+ if (!isArraySpeculation(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(&JSArray::s_info)));
m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg);
}
@@ -3094,7 +3122,7 @@ void SpeculativeJIT::compileGetByValOnArguments(Node& node)
if (!m_compileOkay)
return;
- if (!isArgumentsPrediction(m_state.forNode(node.child1()).m_type)) {
+ if (!isArgumentsSpeculation(m_state.forNode(node.child1()).m_type)) {
speculationCheck(
BadType, JSValueSource::unboxedCell(baseReg), node.child1(),
m_jit.branchPtr(
@@ -3162,7 +3190,7 @@ void SpeculativeJIT::compileGetArgumentsLength(Node& node)
if (!m_compileOkay)
return;
- if (!isArgumentsPrediction(m_state.forNode(node.child1()).m_type)) {
+ if (!isArgumentsSpeculation(m_state.forNode(node.child1()).m_type)) {
speculationCheck(
BadType, JSValueSource::unboxedCell(baseReg), node.child1(),
m_jit.branchPtr(
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
index 56a1a1861..933784685 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
@@ -81,13 +81,13 @@ public:
ASSERT(kind() == HaveNode);
}
- static ValueSource forPrediction(PredictedType prediction)
+ static ValueSource forSpeculation(SpeculatedType prediction)
{
- if (isInt32Prediction(prediction))
+ if (isInt32Speculation(prediction))
return ValueSource(Int32InRegisterFile);
- if (isArrayPrediction(prediction))
+ if (isArraySpeculation(prediction))
return ValueSource(CellInRegisterFile);
- if (isBooleanPrediction(prediction))
+ if (isBooleanSpeculation(prediction))
return ValueSource(BooleanInRegisterFile);
return ValueSource(ValueInRegisterFile);
}
@@ -1294,6 +1294,11 @@ public:
m_jit.setupArgumentsWithExecState(TrustedImm32(arg1), arg2);
return appendCallWithExceptionCheckSetResult(operation, result);
}
+ JITCompiler::Call callOperation(J_DFGOperation_EZIcfZ operation, GPRReg result, int32_t arg1, InlineCallFrame* inlineCallFrame, GPRReg arg2)
+ {
+ m_jit.setupArgumentsWithExecState(TrustedImm32(arg1), TrustedImmPtr(inlineCallFrame), arg2);
+ return appendCallWithExceptionCheckSetResult(operation, result);
+ }
JITCompiler::Call callOperation(C_DFGOperation_E operation, GPRReg result)
{
m_jit.setupArgumentsExecState();
@@ -1409,6 +1414,11 @@ public:
m_jit.setupArgumentsWithExecState(arg1, TrustedImm32(arg2));
return appendCallWithExceptionCheck(operation);
}
+ JITCompiler::Call callOperation(V_DFGOperation_W operation, WatchpointSet* watchpointSet)
+ {
+ m_jit.setupArguments(TrustedImmPtr(watchpointSet));
+ return appendCall(operation);
+ }
template<typename FunctionType, typename ArgumentType1>
JITCompiler::Call callOperation(FunctionType operation, NoResultTag, ArgumentType1 arg1)
{
@@ -1547,6 +1557,11 @@ public:
m_jit.setupArgumentsWithExecState(TrustedImm32(arg1));
return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
}
+ JITCompiler::Call callOperation(J_DFGOperation_EZIcfZ operation, GPRReg resultTag, GPRReg resultPayload, int32_t arg1, InlineCallFrame* inlineCallFrame, GPRReg arg2)
+ {
+ m_jit.setupArgumentsWithExecState(TrustedImm32(arg1), TrustedImmPtr(inlineCallFrame), arg2);
+ return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
+ }
JITCompiler::Call callOperation(J_DFGOperation_EZZ operation, GPRReg resultTag, GPRReg resultPayload, int32_t arg1, GPRReg arg2)
{
m_jit.setupArgumentsWithExecState(TrustedImm32(arg1), arg2);
@@ -1662,6 +1677,11 @@ public:
m_jit.setupArgumentsWithExecState(arg1, arg2, EABI_32BIT_DUMMY_ARG arg3Payload, arg3Tag);
return appendCallWithExceptionCheck(operation);
}
+ JITCompiler::Call callOperation(V_DFGOperation_W operation, WatchpointSet* watchpointSet)
+ {
+ m_jit.setupArguments(TrustedImmPtr(watchpointSet));
+ return appendCall(operation);
+ }
template<typename FunctionType, typename ArgumentType1>
JITCompiler::Call callOperation(FunctionType operation, NoResultTag, ArgumentType1 arg1)
{
@@ -1783,6 +1803,11 @@ public:
m_jit.move(GPRInfo::returnValueGPR, result);
return call;
}
+ JITCompiler::Call appendCall(const FunctionPtr& function)
+ {
+ prepareForExternalCall();
+ return m_jit.appendCall(function);
+ }
JITCompiler::Call appendCallWithExceptionCheckSetResult(const FunctionPtr& function, GPRReg result1, GPRReg result2)
{
JITCompiler::Call call = appendCallWithExceptionCheck(function);
@@ -2034,12 +2059,12 @@ public:
bool compilePeepHoleBranch(Node&, MacroAssembler::RelationalCondition, MacroAssembler::DoubleCondition, S_DFGOperation_EJJ);
void compilePeepHoleIntegerBranch(Node&, NodeIndex branchNodeIndex, JITCompiler::RelationalCondition);
void compilePeepHoleDoubleBranch(Node&, NodeIndex branchNodeIndex, JITCompiler::DoubleCondition);
- void compilePeepHoleObjectEquality(Node&, NodeIndex branchNodeIndex, const ClassInfo*, PredictionChecker);
+ void compilePeepHoleObjectEquality(Node&, NodeIndex branchNodeIndex, const ClassInfo*, SpeculatedTypeChecker);
void compilePeepHoleObjectToObjectOrOtherEquality(
- Edge leftChild, Edge rightChild, NodeIndex branchNodeIndex, const ClassInfo*, PredictionChecker);
- void compileObjectEquality(Node&, const ClassInfo*, PredictionChecker);
+ Edge leftChild, Edge rightChild, NodeIndex branchNodeIndex, const ClassInfo*, SpeculatedTypeChecker);
+ void compileObjectEquality(Node&, const ClassInfo*, SpeculatedTypeChecker);
void compileObjectToObjectOrOtherEquality(
- Edge leftChild, Edge rightChild, const ClassInfo*, PredictionChecker);
+ Edge leftChild, Edge rightChild, const ClassInfo*, SpeculatedTypeChecker);
void compileValueAdd(Node&);
void compileObjectOrOtherLogicalNot(Edge value, const ClassInfo*, bool needSpeculationCheck);
void compileLogicalNot(Node&);
@@ -2183,6 +2208,32 @@ public:
ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes);
speculationCheck(kind, jsValueSource, nodeUse.index(), jumpToFail, recovery);
}
+ // Use this like you would use speculationCheck(), except that you don't pass it a jump
+ // (because you don't have to execute a branch; that's kind of the whole point), and you
+ // must register the returned Watchpoint with something relevant. In general, this should
+ // be used with extreme care. Use speculationCheck() unless you've got an amazing reason
+ // not to.
+ Watchpoint* speculationWatchpoint(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex)
+ {
+ if (!m_compileOkay)
+ return 0;
+ ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes);
+ OSRExit& exit = m_jit.codeBlock()->osrExit(
+ m_jit.codeBlock()->appendOSRExit(
+ OSRExit(kind, jsValueSource,
+ m_jit.graph().methodOfGettingAValueProfileFor(nodeIndex),
+ JITCompiler::Jump(), this)));
+ exit.m_watchpointIndex = m_jit.codeBlock()->appendWatchpoint(
+ Watchpoint(m_jit.watchpointLabel()));
+ return &m_jit.codeBlock()->watchpoint(exit.m_watchpointIndex);
+ }
+ // The default for speculation watchpoints is that they're uncounted, because the
+ // act of firing a watchpoint invalidates it. So, future recompilations will not
+ // attempt to set this watchpoint again.
+ Watchpoint* speculationWatchpoint()
+ {
+ return speculationWatchpoint(UncountableWatchpoint, JSValueSource(), NoNode);
+ }
void forwardSpeculationCheck(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex, MacroAssembler::Jump jumpToFail, const ValueRecovery& valueRecovery)
{
ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes);
@@ -2197,7 +2248,7 @@ public:
setLocal = &at(m_jit.graph().m_blocks[m_block]->at(++setLocalIndexInBlock));
hadInt32ToDouble = true;
}
- if (setLocal->op() == Flush)
+ if (setLocal->op() == Flush || setLocal->op() == Phantom)
setLocal = &at(m_jit.graph().m_blocks[m_block]->at(++setLocalIndexInBlock));
if (hadInt32ToDouble)
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
index 00a83000a..0c33e0748 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
@@ -30,6 +30,7 @@
#if ENABLE(DFG_JIT)
#include "DFGSlowPathGenerator.h"
+#include "JSVariableObject.h"
namespace JSC { namespace DFG {
@@ -1051,7 +1052,7 @@ GPRReg SpeculativeJIT::fillSpeculateIntInternal(NodeIndex nodeIndex, DataFormat&
return allocate();
}
- PredictedType type = m_state.forNode(nodeIndex).m_type;
+ SpeculatedType type = m_state.forNode(nodeIndex).m_type;
Node& node = at(nodeIndex);
VirtualRegister virtualRegister = node.virtualRegister();
GenerationInfo& info = m_generationInfo[virtualRegister];
@@ -1073,7 +1074,7 @@ GPRReg SpeculativeJIT::fillSpeculateIntInternal(NodeIndex nodeIndex, DataFormat&
ASSERT_UNUSED(spillFormat, (spillFormat & DataFormatJS) || spillFormat == DataFormatInteger);
// If we know this was spilled as an integer we can fill without checking.
- if (!isInt32Prediction(type))
+ if (!isInt32Speculation(type))
speculationCheck(BadType, JSValueSource(JITCompiler::addressFor(virtualRegister)), nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::Int32Tag)));
GPRReg gpr = allocate();
@@ -1091,7 +1092,7 @@ GPRReg SpeculativeJIT::fillSpeculateIntInternal(NodeIndex nodeIndex, DataFormat&
GPRReg payloadGPR = info.payloadGPR();
m_gprs.lock(tagGPR);
m_gprs.lock(payloadGPR);
- if (!isInt32Prediction(type))
+ if (!isInt32Speculation(type))
speculationCheck(BadType, JSValueRegs(tagGPR, payloadGPR), nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, tagGPR, TrustedImm32(JSValue::Int32Tag)));
m_gprs.unlock(tagGPR);
m_gprs.release(tagGPR);
@@ -1147,7 +1148,7 @@ FPRReg SpeculativeJIT::fillSpeculateDouble(NodeIndex nodeIndex)
return fprAllocate();
}
- PredictedType type = m_state.forNode(nodeIndex).m_type;
+ SpeculatedType type = m_state.forNode(nodeIndex).m_type;
Node& node = at(nodeIndex);
VirtualRegister virtualRegister = node.virtualRegister();
GenerationInfo& info = m_generationInfo[virtualRegister];
@@ -1185,7 +1186,7 @@ FPRReg SpeculativeJIT::fillSpeculateDouble(NodeIndex nodeIndex)
if (spillFormat != DataFormatJSInteger && spillFormat != DataFormatInteger) {
JITCompiler::Jump isInteger = m_jit.branch32(MacroAssembler::Equal, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::Int32Tag));
- if (!isNumberPrediction(type))
+ if (!isNumberSpeculation(type))
speculationCheck(BadType, JSValueSource(JITCompiler::addressFor(virtualRegister)), nodeIndex, m_jit.branch32(MacroAssembler::AboveOrEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::LowestTag)));
m_jit.loadDouble(JITCompiler::addressFor(virtualRegister), fpr);
hasUnboxedDouble = m_jit.jump();
@@ -1219,7 +1220,7 @@ FPRReg SpeculativeJIT::fillSpeculateDouble(NodeIndex nodeIndex)
if (info.registerFormat() != DataFormatJSInteger) {
FPRTemporary scratch(this);
JITCompiler::Jump isInteger = m_jit.branch32(MacroAssembler::Equal, tagGPR, TrustedImm32(JSValue::Int32Tag));
- if (!isNumberPrediction(type))
+ if (!isNumberSpeculation(type))
speculationCheck(BadType, JSValueRegs(tagGPR, payloadGPR), nodeIndex, m_jit.branch32(MacroAssembler::AboveOrEqual, tagGPR, TrustedImm32(JSValue::LowestTag)));
unboxDouble(tagGPR, payloadGPR, fpr, scratch.fpr());
hasUnboxedDouble = m_jit.jump();
@@ -1280,7 +1281,7 @@ GPRReg SpeculativeJIT::fillSpeculateCell(NodeIndex nodeIndex)
return allocate();
}
- PredictedType type = m_state.forNode(nodeIndex).m_type;
+ SpeculatedType type = m_state.forNode(nodeIndex).m_type;
Node& node = at(nodeIndex);
VirtualRegister virtualRegister = node.virtualRegister();
GenerationInfo& info = m_generationInfo[virtualRegister];
@@ -1299,7 +1300,7 @@ GPRReg SpeculativeJIT::fillSpeculateCell(NodeIndex nodeIndex)
}
ASSERT((info.spillFormat() & DataFormatJS) || info.spillFormat() == DataFormatCell);
- if (!isCellPrediction(type))
+ if (!isCellSpeculation(type))
speculationCheck(BadType, JSValueSource(JITCompiler::addressFor(virtualRegister)), nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::CellTag)));
GPRReg gpr = allocate();
m_jit.load32(JITCompiler::payloadFor(virtualRegister), gpr);
@@ -1320,7 +1321,7 @@ GPRReg SpeculativeJIT::fillSpeculateCell(NodeIndex nodeIndex)
GPRReg payloadGPR = info.payloadGPR();
m_gprs.lock(tagGPR);
m_gprs.lock(payloadGPR);
- if (!isCellPrediction(type))
+ if (!isCellSpeculation(type))
speculationCheck(BadType, JSValueRegs(tagGPR, payloadGPR), nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, tagGPR, TrustedImm32(JSValue::CellTag)));
m_gprs.unlock(tagGPR);
m_gprs.release(tagGPR);
@@ -1349,7 +1350,7 @@ GPRReg SpeculativeJIT::fillSpeculateBoolean(NodeIndex nodeIndex)
#if DFG_ENABLE(DEBUG_VERBOSE)
dataLog("SpecBool@%d ", nodeIndex);
#endif
- PredictedType type = m_state.forNode(nodeIndex).m_type;
+ SpeculatedType type = m_state.forNode(nodeIndex).m_type;
Node& node = m_jit.graph()[nodeIndex];
VirtualRegister virtualRegister = node.virtualRegister();
GenerationInfo& info = m_generationInfo[virtualRegister];
@@ -1374,7 +1375,7 @@ GPRReg SpeculativeJIT::fillSpeculateBoolean(NodeIndex nodeIndex)
ASSERT((info.spillFormat() & DataFormatJS) || info.spillFormat() == DataFormatBoolean);
- if (!isBooleanPrediction(type))
+ if (!isBooleanSpeculation(type))
speculationCheck(BadType, JSValueSource(JITCompiler::addressFor(virtualRegister)), nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::BooleanTag)));
GPRReg gpr = allocate();
@@ -1396,7 +1397,7 @@ GPRReg SpeculativeJIT::fillSpeculateBoolean(NodeIndex nodeIndex)
GPRReg payloadGPR = info.payloadGPR();
m_gprs.lock(tagGPR);
m_gprs.lock(payloadGPR);
- if (!isBooleanPrediction(type))
+ if (!isBooleanSpeculation(type))
speculationCheck(BadType, JSValueRegs(tagGPR, payloadGPR), nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, tagGPR, TrustedImm32(JSValue::BooleanTag)));
m_gprs.unlock(tagGPR);
@@ -1439,16 +1440,16 @@ JITCompiler::Jump SpeculativeJIT::convertToDouble(JSValueOperand& op, FPRReg res
return notNumber;
}
-void SpeculativeJIT::compileObjectEquality(Node& node, const ClassInfo* classInfo, PredictionChecker predictionCheck)
+void SpeculativeJIT::compileObjectEquality(Node& node, const ClassInfo* classInfo, SpeculatedTypeChecker speculatedTypeChecker)
{
SpeculateCellOperand op1(this, node.child1());
SpeculateCellOperand op2(this, node.child2());
GPRReg op1GPR = op1.gpr();
GPRReg op2GPR = op2.gpr();
- if (!predictionCheck(m_state.forNode(node.child1()).m_type))
+ if (!speculatedTypeChecker(m_state.forNode(node.child1()).m_type))
speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1GPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(classInfo)));
- if (!predictionCheck(m_state.forNode(node.child2()).m_type))
+ if (!speculatedTypeChecker(m_state.forNode(node.child2()).m_type))
speculationCheck(BadType, JSValueSource::unboxedCell(op2GPR), node.child2(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op2GPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(classInfo)));
GPRTemporary resultPayload(this, op2);
@@ -1466,7 +1467,7 @@ void SpeculativeJIT::compileObjectEquality(Node& node, const ClassInfo* classInf
void SpeculativeJIT::compileObjectToObjectOrOtherEquality(
Edge leftChild, Edge rightChild,
- const ClassInfo* classInfo, PredictionChecker predictionCheck)
+ const ClassInfo* classInfo, SpeculatedTypeChecker speculatedTypeChecker)
{
SpeculateCellOperand op1(this, leftChild);
JSValueOperand op2(this, rightChild);
@@ -1477,7 +1478,7 @@ void SpeculativeJIT::compileObjectToObjectOrOtherEquality(
GPRReg op2PayloadGPR = op2.payloadGPR();
GPRReg resultGPR = result.gpr();
- if (!predictionCheck(m_state.forNode(leftChild).m_type)) {
+ if (!speculatedTypeChecker(m_state.forNode(leftChild).m_type)) {
speculationCheck(
BadType, JSValueSource::unboxedCell(op1GPR), leftChild.index(),
m_jit.branchPtr(
@@ -1493,9 +1494,9 @@ void SpeculativeJIT::compileObjectToObjectOrOtherEquality(
// We know that within this branch, rightChild must be a cell. If the CFA can tell us that the
// proof, when filtered on cell, demonstrates that we have an object of the desired type
- // (predictionCheck() will test for FinalObject or Array, currently), then we can skip the
+ // (speculationCheck() will test for FinalObject or Array, currently), then we can skip the
// speculation.
- if (!predictionCheck(m_state.forNode(rightChild).m_type & PredictCell)) {
+ if (!speculatedTypeChecker(m_state.forNode(rightChild).m_type & SpecCell)) {
speculationCheck(
BadType, JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild.index(),
m_jit.branchPtr(
@@ -1514,7 +1515,7 @@ void SpeculativeJIT::compileObjectToObjectOrOtherEquality(
// We know that within this branch, rightChild must not be a cell. Check if that is enough to
// prove that it is either null or undefined.
- if (!isOtherPrediction(m_state.forNode(rightChild).m_type & ~PredictCell)) {
+ if (!isOtherSpeculation(m_state.forNode(rightChild).m_type & ~SpecCell)) {
m_jit.move(op2TagGPR, resultGPR);
m_jit.or32(TrustedImm32(1), resultGPR);
@@ -1537,7 +1538,7 @@ void SpeculativeJIT::compileObjectToObjectOrOtherEquality(
void SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality(
Edge leftChild, Edge rightChild, NodeIndex branchNodeIndex,
- const ClassInfo* classInfo, PredictionChecker predictionCheck)
+ const ClassInfo* classInfo, SpeculatedTypeChecker speculatedTypeChecker)
{
Node& branchNode = at(branchNodeIndex);
BlockIndex taken = branchNode.takenBlockIndex();
@@ -1552,7 +1553,7 @@ void SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality(
GPRReg op2PayloadGPR = op2.payloadGPR();
GPRReg resultGPR = result.gpr();
- if (!predictionCheck(m_state.forNode(leftChild).m_type)) {
+ if (!speculatedTypeChecker(m_state.forNode(leftChild).m_type)) {
speculationCheck(
BadType, JSValueSource::unboxedCell(op1GPR), leftChild.index(),
m_jit.branchPtr(
@@ -1568,9 +1569,9 @@ void SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality(
// We know that within this branch, rightChild must be a cell. If the CFA can tell us that the
// proof, when filtered on cell, demonstrates that we have an object of the desired type
- // (predictionCheck() will test for FinalObject or Array, currently), then we can skip the
+ // (speculationCheck() will test for FinalObject or Array, currently), then we can skip the
// speculation.
- if (!predictionCheck(m_state.forNode(rightChild).m_type & PredictCell)) {
+ if (!speculatedTypeChecker(m_state.forNode(rightChild).m_type & SpecCell)) {
speculationCheck(
BadType, JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild.index(),
m_jit.branchPtr(
@@ -1586,7 +1587,7 @@ void SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality(
// We know that within this branch, rightChild must not be a cell. Check if that is enough to
// prove that it is either null or undefined.
- if (isOtherPrediction(m_state.forNode(rightChild).m_type & ~PredictCell))
+ if (isOtherSpeculation(m_state.forNode(rightChild).m_type & ~SpecCell))
rightNotCell.link(&m_jit);
else {
jump(notTaken, ForceJump);
@@ -1692,11 +1693,11 @@ void SpeculativeJIT::compileLogicalNot(Node& node)
return;
}
if (at(node.child1()).shouldSpeculateFinalObjectOrOther()) {
- compileObjectOrOtherLogicalNot(node.child1(), &JSFinalObject::s_info, !isFinalObjectOrOtherPrediction(m_state.forNode(node.child1()).m_type));
+ compileObjectOrOtherLogicalNot(node.child1(), &JSFinalObject::s_info, !isFinalObjectOrOtherSpeculation(m_state.forNode(node.child1()).m_type));
return;
}
if (at(node.child1()).shouldSpeculateArrayOrOther()) {
- compileObjectOrOtherLogicalNot(node.child1(), &JSArray::s_info, !isArrayOrOtherPrediction(m_state.forNode(node.child1()).m_type));
+ compileObjectOrOtherLogicalNot(node.child1(), &JSArray::s_info, !isArrayOrOtherSpeculation(m_state.forNode(node.child1()).m_type));
return;
}
if (at(node.child1()).shouldSpeculateInteger()) {
@@ -1787,9 +1788,9 @@ void SpeculativeJIT::emitBranch(Node& node)
noResult(m_compileIndex);
} else if (at(node.child1()).shouldSpeculateFinalObjectOrOther()) {
- emitObjectOrOtherBranch(node.child1(), taken, notTaken, &JSFinalObject::s_info, !isFinalObjectOrOtherPrediction(m_state.forNode(node.child1()).m_type));
+ emitObjectOrOtherBranch(node.child1(), taken, notTaken, &JSFinalObject::s_info, !isFinalObjectOrOtherSpeculation(m_state.forNode(node.child1()).m_type));
} else if (at(node.child1()).shouldSpeculateArrayOrOther()) {
- emitObjectOrOtherBranch(node.child1(), taken, notTaken, &JSArray::s_info, !isArrayOrOtherPrediction(m_state.forNode(node.child1()).m_type));
+ emitObjectOrOtherBranch(node.child1(), taken, notTaken, &JSArray::s_info, !isArrayOrOtherSpeculation(m_state.forNode(node.child1()).m_type));
} else if (at(node.child1()).shouldSpeculateNumber()) {
if (at(node.child1()).shouldSpeculateInteger()) {
bool invert = false;
@@ -1848,7 +1849,13 @@ void SpeculativeJIT::compile(Node& node)
switch (op) {
case JSConstant:
+ initConstantInfo(m_compileIndex);
+ break;
+
case PhantomArguments:
+ // This should never be must-generate.
+ ASSERT_NOT_REACHED();
+ // But as a release-mode fall-back make it the empty value.
initConstantInfo(m_compileIndex);
break;
@@ -1858,11 +1865,11 @@ void SpeculativeJIT::compile(Node& node)
break;
case GetLocal: {
- PredictedType prediction = node.variableAccessData()->prediction();
+ SpeculatedType prediction = node.variableAccessData()->prediction();
AbstractValue& value = block()->valuesAtHead.operand(node.local());
// If we have no prediction for this local, then don't attempt to compile.
- if (prediction == PredictNone) {
+ if (prediction == SpecNone) {
terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), NoNode);
break;
}
@@ -1884,7 +1891,7 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- if (isInt32Prediction(prediction)) {
+ if (isInt32Speculation(prediction)) {
GPRTemporary result(this);
m_jit.load32(JITCompiler::payloadFor(node.local()), result.gpr());
@@ -1896,7 +1903,7 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- if (isArrayPrediction(prediction)) {
+ if (isArraySpeculation(prediction)) {
GPRTemporary result(this);
m_jit.load32(JITCompiler::payloadFor(node.local()), result.gpr());
@@ -1908,7 +1915,7 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- if (isBooleanPrediction(prediction)) {
+ if (isBooleanSpeculation(prediction)) {
GPRTemporary result(this);
m_jit.load32(JITCompiler::payloadFor(node.local()), result.gpr());
@@ -1933,7 +1940,7 @@ void SpeculativeJIT::compile(Node& node)
m_gprs.retain(tag.gpr(), virtualRegister, SpillOrderJS);
DataFormat format;
- if (isCellPrediction(value.m_type)
+ if (isCellSpeculation(value.m_type)
&& !node.variableAccessData()->isCaptured())
format = DataFormatJSCell;
else
@@ -1999,7 +2006,7 @@ void SpeculativeJIT::compile(Node& node)
valueSourceReferenceForOperand(node.local()) = ValueSource(DoubleInRegisterFile);
break;
}
- PredictedType predictedType = node.variableAccessData()->argumentAwarePrediction();
+ SpeculatedType predictedType = node.variableAccessData()->argumentAwarePrediction();
if (m_generationInfo[at(node.child1()).virtualRegister()].registerFormat() == DataFormatDouble) {
DoubleOperand value(this, node.child1());
m_jit.storeDouble(value.fpr(), JITCompiler::addressFor(node.local()));
@@ -2007,24 +2014,24 @@ void SpeculativeJIT::compile(Node& node)
valueSourceReferenceForOperand(node.local()) = ValueSource(DoubleInRegisterFile);
break;
}
- if (isInt32Prediction(predictedType)) {
+ if (isInt32Speculation(predictedType)) {
SpeculateIntegerOperand value(this, node.child1());
m_jit.store32(value.gpr(), JITCompiler::payloadFor(node.local()));
noResult(m_compileIndex);
valueSourceReferenceForOperand(node.local()) = ValueSource(Int32InRegisterFile);
break;
}
- if (isArrayPrediction(predictedType)) {
+ if (isArraySpeculation(predictedType)) {
SpeculateCellOperand cell(this, node.child1());
GPRReg cellGPR = cell.gpr();
- if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
+ if (!isArraySpeculation(m_state.forNode(node.child1()).m_type))
speculationCheck(BadType, JSValueSource::unboxedCell(cellGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(cellGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
m_jit.storePtr(cellGPR, JITCompiler::payloadFor(node.local()));
noResult(m_compileIndex);
valueSourceReferenceForOperand(node.local()) = ValueSource(CellInRegisterFile);
break;
}
- if (isBooleanPrediction(predictedType)) {
+ if (isBooleanSpeculation(predictedType)) {
SpeculateBooleanOperand value(this, node.child1());
m_jit.store32(value.gpr(), JITCompiler::payloadFor(node.local()));
noResult(m_compileIndex);
@@ -2122,7 +2129,7 @@ void SpeculativeJIT::compile(Node& node)
}
case CheckNumber: {
- if (!isNumberPrediction(m_state.forNode(node.child1()).m_type)) {
+ if (!isNumberSpeculation(m_state.forNode(node.child1()).m_type)) {
JSValueOperand op1(this, node.child1());
JITCompiler::Jump isInteger = m_jit.branch32(MacroAssembler::Equal, op1.tagGPR(), TrustedImm32(JSValue::Int32Tag));
speculationCheck(
@@ -2326,7 +2333,7 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- if (!at(node.child2()).shouldSpeculateInteger() || !isActionableArrayPrediction(at(node.child1()).prediction())) {
+ if (!at(node.child2()).shouldSpeculateInteger() || !isActionableArraySpeculation(at(node.child1()).prediction())) {
SpeculateCellOperand base(this, node.child1()); // Save a register, speculate cell. We'll probably be right.
JSValueOperand property(this, node.child2());
GPRReg baseGPR = base.gpr();
@@ -2349,7 +2356,7 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- if (at(node.child1()).prediction() == PredictString) {
+ if (at(node.child1()).prediction() == SpecString) {
compileGetByValOnString(node);
if (!m_compileOkay)
return;
@@ -2357,63 +2364,63 @@ void SpeculativeJIT::compile(Node& node)
}
if (at(node.child1()).shouldSpeculateInt8Array()) {
- compileGetByValOnIntTypedArray(m_jit.globalData()->int8ArrayDescriptor(), node, sizeof(int8_t), isInt8ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
+ compileGetByValOnIntTypedArray(m_jit.globalData()->int8ArrayDescriptor(), node, sizeof(int8_t), isInt8ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
if (!m_compileOkay)
return;
break;
}
if (at(node.child1()).shouldSpeculateInt16Array()) {
- compileGetByValOnIntTypedArray(m_jit.globalData()->int16ArrayDescriptor(), node, sizeof(int16_t), isInt16ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
+ compileGetByValOnIntTypedArray(m_jit.globalData()->int16ArrayDescriptor(), node, sizeof(int16_t), isInt16ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
if (!m_compileOkay)
return;
break;
}
if (at(node.child1()).shouldSpeculateInt32Array()) {
- compileGetByValOnIntTypedArray(m_jit.globalData()->int32ArrayDescriptor(), node, sizeof(int32_t), isInt32ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
+ compileGetByValOnIntTypedArray(m_jit.globalData()->int32ArrayDescriptor(), node, sizeof(int32_t), isInt32ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
if (!m_compileOkay)
return;
break;
}
if (at(node.child1()).shouldSpeculateUint8Array()) {
- compileGetByValOnIntTypedArray(m_jit.globalData()->uint8ArrayDescriptor(), node, sizeof(uint8_t), isUint8ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
+ compileGetByValOnIntTypedArray(m_jit.globalData()->uint8ArrayDescriptor(), node, sizeof(uint8_t), isUint8ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
if (!m_compileOkay)
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);
+ compileGetByValOnIntTypedArray(m_jit.globalData()->uint8ClampedArrayDescriptor(), node, sizeof(uint8_t), isUint8ClampedArraySpeculation(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);
+ compileGetByValOnIntTypedArray(m_jit.globalData()->uint16ArrayDescriptor(), node, sizeof(uint16_t), isUint16ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
if (!m_compileOkay)
return;
break;
}
if (at(node.child1()).shouldSpeculateUint32Array()) {
- compileGetByValOnIntTypedArray(m_jit.globalData()->uint32ArrayDescriptor(), node, sizeof(uint32_t), isUint32ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
+ compileGetByValOnIntTypedArray(m_jit.globalData()->uint32ArrayDescriptor(), node, sizeof(uint32_t), isUint32ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
if (!m_compileOkay)
return;
break;
}
if (at(node.child1()).shouldSpeculateFloat32Array()) {
- compileGetByValOnFloatTypedArray(m_jit.globalData()->float32ArrayDescriptor(), node, sizeof(float), isFloat32ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks);
+ compileGetByValOnFloatTypedArray(m_jit.globalData()->float32ArrayDescriptor(), node, sizeof(float), isFloat32ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks);
if (!m_compileOkay)
return;
break;
}
if (at(node.child1()).shouldSpeculateFloat64Array()) {
- compileGetByValOnFloatTypedArray(m_jit.globalData()->float64ArrayDescriptor(), node, sizeof(double), isFloat64ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks);
+ compileGetByValOnFloatTypedArray(m_jit.globalData()->float64ArrayDescriptor(), node, sizeof(double), isFloat64ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks);
if (!m_compileOkay)
return;
break;
@@ -2434,7 +2441,7 @@ void SpeculativeJIT::compile(Node& node)
{
SpeculateCellOperand base(this, node.child1());
GPRReg baseReg = base.gpr();
- if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
+ if (!isArraySpeculation(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(&JSArray::s_info)));
speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, JSArray::vectorLengthOffset())));
}
@@ -2460,7 +2467,7 @@ void SpeculativeJIT::compile(Node& node)
}
if (!at(node.child2()).shouldSpeculateInteger()
- || !isActionableMutableArrayPrediction(at(node.child1()).prediction())
+ || !isActionableMutableArraySpeculation(at(node.child1()).prediction())
|| at(node.child1()).shouldSpeculateArguments()) {
SpeculateCellOperand base(this, node.child1()); // Save a register, speculate cell. We'll probably be right.
JSValueOperand property(this, node.child2());
@@ -2481,63 +2488,63 @@ void SpeculativeJIT::compile(Node& node)
SpeculateCellOperand base(this, node.child1());
SpeculateStrictInt32Operand property(this, node.child2());
if (at(node.child1()).shouldSpeculateInt8Array()) {
- compilePutByValForIntTypedArray(m_jit.globalData()->int8ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(int8_t), isInt8ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
+ compilePutByValForIntTypedArray(m_jit.globalData()->int8ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(int8_t), isInt8ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
if (!m_compileOkay)
return;
break;
}
if (at(node.child1()).shouldSpeculateInt16Array()) {
- compilePutByValForIntTypedArray(m_jit.globalData()->int16ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(int16_t), isInt16ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
+ compilePutByValForIntTypedArray(m_jit.globalData()->int16ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(int16_t), isInt16ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
if (!m_compileOkay)
return;
break;
}
if (at(node.child1()).shouldSpeculateInt32Array()) {
- compilePutByValForIntTypedArray(m_jit.globalData()->int32ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(int32_t), isInt32ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
+ compilePutByValForIntTypedArray(m_jit.globalData()->int32ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(int32_t), isInt32ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
if (!m_compileOkay)
return;
break;
}
if (at(node.child1()).shouldSpeculateUint8Array()) {
- compilePutByValForIntTypedArray(m_jit.globalData()->uint8ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint8_t), isUint8ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
+ compilePutByValForIntTypedArray(m_jit.globalData()->uint8ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint8_t), isUint8ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
if (!m_compileOkay)
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);
+ compilePutByValForIntTypedArray(m_jit.globalData()->uint8ClampedArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint8_t), isUint8ClampedArraySpeculation(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);
+ compilePutByValForIntTypedArray(m_jit.globalData()->uint16ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint16_t), isUint16ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
if (!m_compileOkay)
return;
break;
}
if (at(node.child1()).shouldSpeculateUint32Array()) {
- compilePutByValForIntTypedArray(m_jit.globalData()->uint32ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint32_t), isUint32ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
+ compilePutByValForIntTypedArray(m_jit.globalData()->uint32ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint32_t), isUint32ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
if (!m_compileOkay)
return;
break;
}
if (at(node.child1()).shouldSpeculateFloat32Array()) {
- compilePutByValForFloatTypedArray(m_jit.globalData()->float32ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(float), isFloat32ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks);
+ compilePutByValForFloatTypedArray(m_jit.globalData()->float32ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(float), isFloat32ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks);
if (!m_compileOkay)
return;
break;
}
if (at(node.child1()).shouldSpeculateFloat64Array()) {
- compilePutByValForFloatTypedArray(m_jit.globalData()->float64ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(double), isFloat64ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks);
+ compilePutByValForFloatTypedArray(m_jit.globalData()->float64ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(double), isFloat64ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks);
if (!m_compileOkay)
return;
break;
@@ -2562,7 +2569,7 @@ void SpeculativeJIT::compile(Node& node)
// Check that base is an array, and that property is contained within m_vector (< m_vectorLength).
// If we have predicted the base to be type array, we can skip the check.
- if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
+ if (!isArraySpeculation(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(&JSArray::s_info)));
base.use();
@@ -2608,7 +2615,7 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- ASSERT(isActionableMutableArrayPrediction(at(node.child1()).prediction()));
+ ASSERT(isActionableMutableArraySpeculation(at(node.child1()).prediction()));
ASSERT(at(node.child2()).shouldSpeculateInteger());
SpeculateCellOperand base(this, node.child1());
@@ -2763,7 +2770,7 @@ void SpeculativeJIT::compile(Node& node)
writeBarrier(baseGPR, valueTagGPR, node.child2(), WriteBarrierForPropertyAccess, storageGPR, storageLengthGPR);
- if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
+ if (!isArraySpeculation(m_state.forNode(node.child1()).m_type))
speculationCheck(BadType, JSValueSource::unboxedCell(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), storageGPR);
@@ -2801,7 +2808,7 @@ void SpeculativeJIT::compile(Node& node)
GPRReg storageGPR = storage.gpr();
GPRReg storageLengthGPR = storageLength.gpr();
- if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
+ if (!isArraySpeculation(m_state.forNode(node.child1()).m_type))
speculationCheck(BadType, JSValueSource::unboxedCell(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), storageGPR);
@@ -2947,7 +2954,7 @@ void SpeculativeJIT::compile(Node& node)
op1.use();
- if (!(m_state.forNode(node.child1()).m_type & ~(PredictNumber | PredictBoolean))) {
+ if (!(m_state.forNode(node.child1()).m_type & ~(SpecNumber | SpecBoolean))) {
m_jit.move(op1TagGPR, resultTagGPR);
m_jit.move(op1PayloadGPR, resultPayloadGPR);
} else {
@@ -3053,7 +3060,7 @@ void SpeculativeJIT::compile(Node& node)
}
case ConvertThis: {
- if (isObjectPrediction(m_state.forNode(node.child1()).m_type)) {
+ if (isObjectSpeculation(m_state.forNode(node.child1()).m_type)) {
SpeculateCellOperand thisValue(this, node.child1());
GPRTemporary result(this, thisValue);
m_jit.move(thisValue.gpr(), result.gpr());
@@ -3061,7 +3068,7 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- if (isOtherPrediction(at(node.child1()).prediction())) {
+ if (isOtherSpeculation(at(node.child1()).prediction())) {
JSValueOperand thisValue(this, node.child1());
GPRTemporary scratch(this);
@@ -3080,11 +3087,11 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- if (isObjectPrediction(at(node.child1()).prediction())) {
+ if (isObjectSpeculation(at(node.child1()).prediction())) {
SpeculateCellOperand thisValue(this, node.child1());
GPRReg thisValueGPR = thisValue.gpr();
- if (!isObjectPrediction(m_state.forNode(node.child1()).m_type))
+ if (!isObjectSpeculation(m_state.forNode(node.child1()).m_type))
speculationCheck(BadType, JSValueSource::unboxedCell(thisValueGPR), node.child1(), m_jit.branchPtr(JITCompiler::Equal, JITCompiler::Address(thisValueGPR, JSCell::classInfoOffset()), JITCompiler::TrustedImmPtr(&JSString::s_info)));
GPRTemporary result(this, thisValue);
@@ -3214,7 +3221,7 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- if (isCellPrediction(at(node.child1()).prediction())) {
+ if (isCellSpeculation(at(node.child1()).prediction())) {
SpeculateCellOperand base(this, node.child1());
GPRTemporary resultTag(this, base);
GPRTemporary resultPayload(this);
@@ -3268,7 +3275,7 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- if (isCellPrediction(at(node.child1()).prediction())) {
+ if (isCellSpeculation(at(node.child1()).prediction())) {
SpeculateCellOperand base(this, node.child1());
GPRReg baseGPR = base.gpr();
@@ -3317,7 +3324,7 @@ void SpeculativeJIT::compile(Node& node)
SpeculateCellOperand base(this, node.child1());
GPRReg baseGPR = base.gpr();
- if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
+ if (!isArraySpeculation(m_state.forNode(node.child1()).m_type))
speculationCheck(BadType, JSValueSource::unboxedCell(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
GPRTemporary result(this);
@@ -3344,7 +3351,7 @@ void SpeculativeJIT::compile(Node& node)
GPRReg baseGPR = base.gpr();
GPRReg resultGPR = result.gpr();
- if (!isStringPrediction(m_state.forNode(node.child1()).m_type))
+ if (!isStringSpeculation(m_state.forNode(node.child1()).m_type))
speculationCheck(BadType, JSValueSource::unboxedCell(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSString::s_info)));
m_jit.load32(MacroAssembler::Address(baseGPR, JSString::offsetOfLength()), resultGPR);
@@ -3354,39 +3361,39 @@ void SpeculativeJIT::compile(Node& node)
}
case GetInt8ArrayLength: {
- compileGetTypedArrayLength(m_jit.globalData()->int8ArrayDescriptor(), node, !isInt8ArrayPrediction(m_state.forNode(node.child1()).m_type));
+ compileGetTypedArrayLength(m_jit.globalData()->int8ArrayDescriptor(), node, !isInt8ArraySpeculation(m_state.forNode(node.child1()).m_type));
break;
}
case GetInt16ArrayLength: {
- compileGetTypedArrayLength(m_jit.globalData()->int16ArrayDescriptor(), node, !isInt16ArrayPrediction(m_state.forNode(node.child1()).m_type));
+ compileGetTypedArrayLength(m_jit.globalData()->int16ArrayDescriptor(), node, !isInt16ArraySpeculation(m_state.forNode(node.child1()).m_type));
break;
}
case GetInt32ArrayLength: {
- compileGetTypedArrayLength(m_jit.globalData()->int32ArrayDescriptor(), node, !isInt32ArrayPrediction(m_state.forNode(node.child1()).m_type));
+ compileGetTypedArrayLength(m_jit.globalData()->int32ArrayDescriptor(), node, !isInt32ArraySpeculation(m_state.forNode(node.child1()).m_type));
break;
}
case GetUint8ArrayLength: {
- compileGetTypedArrayLength(m_jit.globalData()->uint8ArrayDescriptor(), node, !isUint8ArrayPrediction(m_state.forNode(node.child1()).m_type));
+ compileGetTypedArrayLength(m_jit.globalData()->uint8ArrayDescriptor(), node, !isUint8ArraySpeculation(m_state.forNode(node.child1()).m_type));
break;
}
case GetUint8ClampedArrayLength: {
- compileGetTypedArrayLength(m_jit.globalData()->uint8ClampedArrayDescriptor(), node, !isUint8ClampedArrayPrediction(m_state.forNode(node.child1()).m_type));
+ compileGetTypedArrayLength(m_jit.globalData()->uint8ClampedArrayDescriptor(), node, !isUint8ClampedArraySpeculation(m_state.forNode(node.child1()).m_type));
break;
}
case GetUint16ArrayLength: {
- compileGetTypedArrayLength(m_jit.globalData()->uint16ArrayDescriptor(), node, !isUint16ArrayPrediction(m_state.forNode(node.child1()).m_type));
+ compileGetTypedArrayLength(m_jit.globalData()->uint16ArrayDescriptor(), node, !isUint16ArraySpeculation(m_state.forNode(node.child1()).m_type));
break;
}
case GetUint32ArrayLength: {
- compileGetTypedArrayLength(m_jit.globalData()->uint32ArrayDescriptor(), node, !isUint32ArrayPrediction(m_state.forNode(node.child1()).m_type));
+ compileGetTypedArrayLength(m_jit.globalData()->uint32ArrayDescriptor(), node, !isUint32ArraySpeculation(m_state.forNode(node.child1()).m_type));
break;
}
case GetFloat32ArrayLength: {
- compileGetTypedArrayLength(m_jit.globalData()->float32ArrayDescriptor(), node, !isFloat32ArrayPrediction(m_state.forNode(node.child1()).m_type));
+ compileGetTypedArrayLength(m_jit.globalData()->float32ArrayDescriptor(), node, !isFloat32ArraySpeculation(m_state.forNode(node.child1()).m_type));
break;
}
case GetFloat64ArrayLength: {
- compileGetTypedArrayLength(m_jit.globalData()->float64ArrayDescriptor(), node, !isFloat64ArrayPrediction(m_state.forNode(node.child1()).m_type));
+ compileGetTypedArrayLength(m_jit.globalData()->float64ArrayDescriptor(), node, !isFloat64ArraySpeculation(m_state.forNode(node.child1()).m_type));
break;
}
@@ -3400,7 +3407,7 @@ void SpeculativeJIT::compile(Node& node)
case CheckStructure: {
AbstractValue& value = m_state.forNode(node.child1());
if (value.m_structure.isSubsetOf(node.structureSet())
- && isCellPrediction(value.m_type)) {
+ && isCellSpeculation(value.m_type)) {
noResult(m_compileIndex);
break;
}
@@ -3430,7 +3437,23 @@ void SpeculativeJIT::compile(Node& node)
break;
}
+ case StructureTransitionWatchpoint: {
+ m_jit.addWeakReference(node.structure());
+ node.structure()->addTransitionWatchpoint(speculationWatchpoint());
+
+#if !ASSERT_DISABLED
+ SpeculateCellOperand op1(this, node.child1());
+ JITCompiler::Jump isOK = m_jit.branchPtr(JITCompiler::Equal, JITCompiler::Address(op1.gpr(), JSCell::structureOffset()), TrustedImmPtr(node.structure()));
+ m_jit.breakpoint();
+ isOK.link(&m_jit);
+#endif
+
+ noResult(m_compileIndex);
+ break;
+ }
+
case PhantomPutStructure: {
+ ASSERT(node.structureTransitionData().previousStructure->transitionWatchpointSetHasBeenInvalidated());
m_jit.addWeakReferenceTransition(
node.codeOrigin.codeOriginOwner(),
node.structureTransitionData().previousStructure,
@@ -3440,6 +3463,8 @@ void SpeculativeJIT::compile(Node& node)
}
case PutStructure: {
+ ASSERT(node.structureTransitionData().previousStructure->transitionWatchpointSetHasBeenInvalidated());
+
SpeculateCellOperand base(this, node.child1());
GPRReg baseGPR = base.gpr();
@@ -3558,34 +3583,89 @@ void SpeculativeJIT::compile(Node& node)
}
case GetGlobalVar: {
- GPRTemporary result(this);
- GPRTemporary scratch(this);
+ GPRTemporary resultPayload(this);
+ GPRTemporary resultTag(this);
- JSVariableObject* globalObject = m_jit.globalObjectFor(node.codeOrigin);
- m_jit.loadPtr(const_cast<WriteBarrier<Unknown>**>(globalObject->addressOfRegisters()), result.gpr());
- m_jit.load32(JITCompiler::tagForGlobalVar(result.gpr(), node.varNumber()), scratch.gpr());
- m_jit.load32(JITCompiler::payloadForGlobalVar(result.gpr(), node.varNumber()), result.gpr());
+ m_jit.move(TrustedImmPtr(node.registerPointer()), resultPayload.gpr());
+ m_jit.load32(JITCompiler::Address(resultPayload.gpr(), OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)), resultTag.gpr());
+ m_jit.load32(JITCompiler::Address(resultPayload.gpr(), OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)), resultPayload.gpr());
- jsValueResult(scratch.gpr(), result.gpr(), m_compileIndex);
+ jsValueResult(resultTag.gpr(), resultPayload.gpr(), m_compileIndex);
break;
}
case PutGlobalVar: {
JSValueOperand value(this, node.child1());
- GPRTemporary globalObject(this);
- GPRTemporary scratch(this);
-
- GPRReg globalObjectReg = globalObject.gpr();
- GPRReg scratchReg = scratch.gpr();
+ if (Heap::isWriteBarrierEnabled()) {
+ GPRTemporary scratch(this);
+ GPRReg scratchReg = scratch.gpr();
+
+ writeBarrier(m_jit.globalObjectFor(node.codeOrigin), value.tagGPR(), node.child1(), WriteBarrierForVariableAccess, scratchReg);
+ }
- m_jit.move(MacroAssembler::TrustedImmPtr(m_jit.globalObjectFor(node.codeOrigin)), globalObjectReg);
+ // FIXME: if we happen to have a spare register - and _ONLY_ if we happen to have
+ // a spare register - a good optimization would be to put the register pointer into
+ // a register and then do a zero offset store followed by a four-offset store (or
+ // vice-versa depending on endianness).
+ m_jit.store32(value.tagGPR(), node.registerPointer()->tagPointer());
+ m_jit.store32(value.payloadGPR(), node.registerPointer()->payloadPointer());
- writeBarrier(m_jit.globalObjectFor(node.codeOrigin), value.tagGPR(), node.child1(), WriteBarrierForVariableAccess, scratchReg);
+ noResult(m_compileIndex);
+ break;
+ }
- m_jit.loadPtr(MacroAssembler::Address(globalObjectReg, JSVariableObject::offsetOfRegisters()), scratchReg);
- m_jit.store32(value.tagGPR(), JITCompiler::tagForGlobalVar(scratchReg, node.varNumber()));
- m_jit.store32(value.payloadGPR(), JITCompiler::payloadForGlobalVar(scratchReg, node.varNumber()));
+ case PutGlobalVarCheck: {
+ JSValueOperand value(this, node.child1());
+
+ WatchpointSet* watchpointSet =
+ m_jit.globalObjectFor(node.codeOrigin)->symbolTable().get(
+ identifier(node.identifierNumberForCheck())->impl()).watchpointSet();
+ addSlowPathGenerator(
+ slowPathCall(
+ m_jit.branchTest8(
+ JITCompiler::NonZero,
+ JITCompiler::AbsoluteAddress(watchpointSet->addressOfIsWatched())),
+ this, operationNotifyGlobalVarWrite, NoResult, watchpointSet));
+
+ if (Heap::isWriteBarrierEnabled()) {
+ GPRTemporary scratch(this);
+ GPRReg scratchReg = scratch.gpr();
+
+ writeBarrier(m_jit.globalObjectFor(node.codeOrigin), value.tagGPR(), node.child1(), WriteBarrierForVariableAccess, scratchReg);
+ }
+ // FIXME: if we happen to have a spare register - and _ONLY_ if we happen to have
+ // a spare register - a good optimization would be to put the register pointer into
+ // a register and then do a zero offset store followed by a four-offset store (or
+ // vice-versa depending on endianness).
+ m_jit.store32(value.tagGPR(), node.registerPointer()->tagPointer());
+ m_jit.store32(value.payloadGPR(), node.registerPointer()->payloadPointer());
+
+ noResult(m_compileIndex);
+ break;
+ }
+
+ case GlobalVarWatchpoint: {
+ m_jit.globalObjectFor(node.codeOrigin)->symbolTable().get(
+ identifier(node.identifierNumberForCheck())->impl()).addWatchpoint(
+ speculationWatchpoint());
+
+#if DFG_ENABLE(JIT_ASSERT)
+ GPRTemporary scratch(this);
+ GPRReg scratchGPR = scratch.gpr();
+ m_jit.load32(node.registerPointer()->tagPointer(), scratchGPR);
+ JITCompiler::Jump notOK = m_jit.branch32(
+ JITCompiler::NotEqual, scratchGPR,
+ TrustedImm32(node.registerPointer()->get().tag()));
+ m_jit.load32(node.registerPointer()->payloadPointer(), scratchGPR);
+ JITCompiler::Jump ok = m_jit.branch32(
+ JITCompiler::Equal, scratchGPR,
+ TrustedImm32(node.registerPointer()->get().payload()));
+ notOK.link(&m_jit);
+ m_jit.breakpoint();
+ ok.link(&m_jit);
+#endif
+
noResult(m_compileIndex);
break;
}
@@ -3858,16 +3938,15 @@ void SpeculativeJIT::compile(Node& node)
}
case CheckArgumentsNotCreated: {
- if (!isEmptyPrediction(
- m_state.variables().operand(
- m_jit.graph().argumentsRegisterFor(node.codeOrigin)).m_type)) {
- speculationCheck(
- Uncountable, JSValueRegs(), NoNode,
- m_jit.branch32(
- JITCompiler::NotEqual,
- JITCompiler::tagFor(m_jit.argumentsRegisterFor(node.codeOrigin)),
- TrustedImm32(JSValue::EmptyValueTag)));
- }
+ ASSERT(!isEmptySpeculation(
+ m_state.variables().operand(
+ m_jit.graph().argumentsRegisterFor(node.codeOrigin)).m_type));
+ speculationCheck(
+ Uncountable, JSValueRegs(), NoNode,
+ m_jit.branch32(
+ JITCompiler::NotEqual,
+ JITCompiler::tagFor(m_jit.argumentsRegisterFor(node.codeOrigin)),
+ TrustedImm32(JSValue::EmptyValueTag)));
noResult(m_compileIndex);
break;
}
@@ -3876,7 +3955,7 @@ void SpeculativeJIT::compile(Node& node)
GPRTemporary result(this);
GPRReg resultGPR = result.gpr();
- if (!isEmptyPrediction(
+ if (!isEmptySpeculation(
m_state.variables().operand(
m_jit.graph().argumentsRegisterFor(node.codeOrigin)).m_type)) {
speculationCheck(
@@ -3937,7 +4016,7 @@ void SpeculativeJIT::compile(Node& node)
GPRReg resultPayloadGPR = resultPayload.gpr();
GPRReg resultTagGPR = resultTag.gpr();
- if (!isEmptyPrediction(
+ if (!isEmptySpeculation(
m_state.variables().operand(
m_jit.graph().argumentsRegisterFor(node.codeOrigin)).m_type)) {
speculationCheck(
@@ -4033,11 +4112,20 @@ void SpeculativeJIT::compile(Node& node)
baseOffset + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)),
resultPayloadGPR);
- addSlowPathGenerator(
- slowPathCall(
- slowPath, this, operationGetArgumentByVal,
- JSValueRegs(resultTagGPR, resultPayloadGPR),
- m_jit.argumentsRegisterFor(node.codeOrigin), indexGPR));
+ if (node.codeOrigin.inlineCallFrame) {
+ addSlowPathGenerator(
+ slowPathCall(
+ slowPath, this, operationGetInlinedArgumentByVal,
+ JSValueRegs(resultTagGPR, resultPayloadGPR),
+ m_jit.argumentsRegisterFor(node.codeOrigin),
+ node.codeOrigin.inlineCallFrame, indexGPR));
+ } else {
+ addSlowPathGenerator(
+ slowPathCall(
+ slowPath, this, operationGetArgumentByVal,
+ JSValueRegs(resultTagGPR, resultPayloadGPR),
+ m_jit.argumentsRegisterFor(node.codeOrigin), indexGPR));
+ }
jsValueResult(resultTagGPR, resultPayloadGPR, m_compileIndex);
break;
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
index ca57743a6..0b7606b2c 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
@@ -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
@@ -1028,7 +1028,7 @@ GPRReg SpeculativeJIT::fillSpeculateIntInternal(NodeIndex nodeIndex, DataFormat&
#if DFG_ENABLE(DEBUG_VERBOSE)
dataLog("SpecInt@%d ", nodeIndex);
#endif
- PredictedType type = m_state.forNode(nodeIndex).m_type;
+ SpeculatedType type = m_state.forNode(nodeIndex).m_type;
Node& node = at(nodeIndex);
VirtualRegister virtualRegister = node.virtualRegister();
GenerationInfo& info = m_generationInfo[virtualRegister];
@@ -1086,7 +1086,7 @@ GPRReg SpeculativeJIT::fillSpeculateIntInternal(NodeIndex nodeIndex, DataFormat&
// Check the value is an integer.
GPRReg gpr = info.gpr();
m_gprs.lock(gpr);
- if (!isInt32Prediction(type))
+ if (!isInt32Speculation(type))
speculationCheck(BadType, JSValueRegs(gpr), nodeIndex, m_jit.branchPtr(MacroAssembler::Below, gpr, GPRInfo::tagTypeNumberRegister));
info.fillJSValue(gpr, DataFormatJSInteger);
// If !strict we're done, return.
@@ -1175,7 +1175,7 @@ FPRReg SpeculativeJIT::fillSpeculateDouble(NodeIndex nodeIndex)
#if DFG_ENABLE(DEBUG_VERBOSE)
dataLog("SpecDouble@%d ", nodeIndex);
#endif
- PredictedType type = m_state.forNode(nodeIndex).m_type;
+ SpeculatedType type = m_state.forNode(nodeIndex).m_type;
Node& node = at(nodeIndex);
VirtualRegister virtualRegister = node.virtualRegister();
GenerationInfo& info = m_generationInfo[virtualRegister];
@@ -1260,7 +1260,7 @@ FPRReg SpeculativeJIT::fillSpeculateDouble(NodeIndex nodeIndex)
JITCompiler::Jump isInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, jsValueGpr, GPRInfo::tagTypeNumberRegister);
- if (!isNumberPrediction(type))
+ if (!isNumberSpeculation(type))
speculationCheck(BadType, JSValueRegs(jsValueGpr), nodeIndex, m_jit.branchTestPtr(MacroAssembler::Zero, jsValueGpr, GPRInfo::tagTypeNumberRegister));
// First, if we get here we have a double encoded as a JSValue
@@ -1328,7 +1328,7 @@ GPRReg SpeculativeJIT::fillSpeculateCell(NodeIndex nodeIndex)
#if DFG_ENABLE(DEBUG_VERBOSE)
dataLog("SpecCell@%d ", nodeIndex);
#endif
- PredictedType type = m_state.forNode(nodeIndex).m_type;
+ SpeculatedType type = m_state.forNode(nodeIndex).m_type;
Node& node = at(nodeIndex);
VirtualRegister virtualRegister = node.virtualRegister();
GenerationInfo& info = m_generationInfo[virtualRegister];
@@ -1358,7 +1358,7 @@ GPRReg SpeculativeJIT::fillSpeculateCell(NodeIndex nodeIndex)
m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
info.fillJSValue(gpr, DataFormatJS);
- if (!isCellPrediction(type))
+ if (!isCellSpeculation(type))
speculationCheck(BadType, JSValueRegs(gpr), nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, gpr, GPRInfo::tagMaskRegister));
info.fillJSValue(gpr, DataFormatJSCell);
return gpr;
@@ -1374,7 +1374,7 @@ GPRReg SpeculativeJIT::fillSpeculateCell(NodeIndex nodeIndex)
case DataFormatJS: {
GPRReg gpr = info.gpr();
m_gprs.lock(gpr);
- if (!isCellPrediction(type))
+ if (!isCellSpeculation(type))
speculationCheck(BadType, JSValueRegs(gpr), nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, gpr, GPRInfo::tagMaskRegister));
info.fillJSValue(gpr, DataFormatJSCell);
return gpr;
@@ -1403,7 +1403,7 @@ GPRReg SpeculativeJIT::fillSpeculateBoolean(NodeIndex nodeIndex)
#if DFG_ENABLE(DEBUG_VERBOSE)
dataLog("SpecBool@%d ", nodeIndex);
#endif
- PredictedType type = m_state.forNode(nodeIndex).m_type;
+ SpeculatedType type = m_state.forNode(nodeIndex).m_type;
Node& node = at(nodeIndex);
VirtualRegister virtualRegister = node.virtualRegister();
GenerationInfo& info = m_generationInfo[virtualRegister];
@@ -1433,7 +1433,7 @@ GPRReg SpeculativeJIT::fillSpeculateBoolean(NodeIndex nodeIndex)
m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
info.fillJSValue(gpr, DataFormatJS);
- if (!isBooleanPrediction(type)) {
+ if (!isBooleanSpeculation(type)) {
m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
speculationCheck(BadType, JSValueRegs(gpr), nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, gpr, TrustedImm32(static_cast<int32_t>(~1))), SpeculationRecovery(BooleanSpeculationCheck, gpr, InvalidGPRReg));
m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
@@ -1452,7 +1452,7 @@ GPRReg SpeculativeJIT::fillSpeculateBoolean(NodeIndex nodeIndex)
case DataFormatJS: {
GPRReg gpr = info.gpr();
m_gprs.lock(gpr);
- if (!isBooleanPrediction(type)) {
+ if (!isBooleanSpeculation(type)) {
m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
speculationCheck(BadType, JSValueRegs(gpr), nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, gpr, TrustedImm32(static_cast<int32_t>(~1))), SpeculationRecovery(BooleanSpeculationCheck, gpr, InvalidGPRReg));
m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
@@ -1499,7 +1499,7 @@ JITCompiler::Jump SpeculativeJIT::convertToDouble(GPRReg value, FPRReg result, G
return notNumber;
}
-void SpeculativeJIT::compileObjectEquality(Node& node, const ClassInfo* classInfo, PredictionChecker predictionCheck)
+void SpeculativeJIT::compileObjectEquality(Node& node, const ClassInfo* classInfo, SpeculatedTypeChecker speculatedTypeChecker)
{
SpeculateCellOperand op1(this, node.child1());
SpeculateCellOperand op2(this, node.child2());
@@ -1509,9 +1509,9 @@ void SpeculativeJIT::compileObjectEquality(Node& node, const ClassInfo* classInf
GPRReg op2GPR = op2.gpr();
GPRReg resultGPR = result.gpr();
- if (!predictionCheck(m_state.forNode(node.child1()).m_type))
+ if (!speculatedTypeChecker(m_state.forNode(node.child1()).m_type))
speculationCheck(BadType, JSValueRegs(op1GPR), node.child1().index(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1GPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(classInfo)));
- if (!predictionCheck(m_state.forNode(node.child2()).m_type))
+ if (!speculatedTypeChecker(m_state.forNode(node.child2()).m_type))
speculationCheck(BadType, JSValueRegs(op2GPR), node.child2().index(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op2GPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(classInfo)));
MacroAssembler::Jump falseCase = m_jit.branchPtr(MacroAssembler::NotEqual, op1GPR, op2GPR);
@@ -1526,7 +1526,7 @@ void SpeculativeJIT::compileObjectEquality(Node& node, const ClassInfo* classInf
void SpeculativeJIT::compileObjectToObjectOrOtherEquality(
Edge leftChild, Edge rightChild,
- const ClassInfo* classInfo, PredictionChecker predictionCheck)
+ const ClassInfo* classInfo, SpeculatedTypeChecker speculatedTypeChecker)
{
SpeculateCellOperand op1(this, leftChild);
JSValueOperand op2(this, rightChild);
@@ -1536,7 +1536,7 @@ void SpeculativeJIT::compileObjectToObjectOrOtherEquality(
GPRReg op2GPR = op2.gpr();
GPRReg resultGPR = result.gpr();
- if (!predictionCheck(m_state.forNode(leftChild).m_type)) {
+ if (!speculatedTypeChecker(m_state.forNode(leftChild).m_type)) {
speculationCheck(
BadType, JSValueRegs(op1GPR), leftChild.index(),
m_jit.branchPtr(
@@ -1552,9 +1552,9 @@ void SpeculativeJIT::compileObjectToObjectOrOtherEquality(
// We know that within this branch, rightChild must be a cell. If the CFA can tell us that the
// proof, when filtered on cell, demonstrates that we have an object of the desired type
- // (predictionCheck() will test for FinalObject or Array, currently), then we can skip the
+ // (speculationCheck() will test for FinalObject or Array, currently), then we can skip the
// speculation.
- if (!predictionCheck(m_state.forNode(rightChild).m_type & PredictCell)) {
+ if (!speculatedTypeChecker(m_state.forNode(rightChild).m_type & SpecCell)) {
speculationCheck(
BadType, JSValueRegs(op2GPR), rightChild.index(),
m_jit.branchPtr(
@@ -1573,7 +1573,7 @@ void SpeculativeJIT::compileObjectToObjectOrOtherEquality(
// We know that within this branch, rightChild must not be a cell. Check if that is enough to
// prove that it is either null or undefined.
- if (!isOtherPrediction(m_state.forNode(rightChild).m_type & ~PredictCell)) {
+ if (!isOtherSpeculation(m_state.forNode(rightChild).m_type & ~SpecCell)) {
m_jit.move(op2GPR, resultGPR);
m_jit.andPtr(MacroAssembler::TrustedImm32(~TagBitUndefined), resultGPR);
@@ -1596,7 +1596,7 @@ void SpeculativeJIT::compileObjectToObjectOrOtherEquality(
void SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality(
Edge leftChild, Edge rightChild, NodeIndex branchNodeIndex,
- const ClassInfo* classInfo, PredictionChecker predictionCheck)
+ const ClassInfo* classInfo, SpeculatedTypeChecker speculatedTypeChecker)
{
Node& branchNode = at(branchNodeIndex);
BlockIndex taken = branchNode.takenBlockIndex();
@@ -1610,7 +1610,7 @@ void SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality(
GPRReg op2GPR = op2.gpr();
GPRReg resultGPR = result.gpr();
- if (!predictionCheck(m_state.forNode(leftChild).m_type)) {
+ if (!speculatedTypeChecker(m_state.forNode(leftChild).m_type)) {
speculationCheck(
BadType, JSValueRegs(op1GPR), leftChild.index(),
m_jit.branchPtr(
@@ -1626,9 +1626,9 @@ void SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality(
// We know that within this branch, rightChild must be a cell. If the CFA can tell us that the
// proof, when filtered on cell, demonstrates that we have an object of the desired type
- // (predictionCheck() will test for FinalObject or Array, currently), then we can skip the
+ // (speculationCheck() will test for FinalObject or Array, currently), then we can skip the
// speculation.
- if (!predictionCheck(m_state.forNode(rightChild).m_type & PredictCell)) {
+ if (!speculatedTypeChecker(m_state.forNode(rightChild).m_type & SpecCell)) {
speculationCheck(
BadType, JSValueRegs(op2GPR), rightChild.index(),
m_jit.branchPtr(
@@ -1644,7 +1644,7 @@ void SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality(
// We know that within this branch, rightChild must not be a cell. Check if that is enough to
// prove that it is either null or undefined.
- if (isOtherPrediction(m_state.forNode(rightChild).m_type & ~PredictCell))
+ if (isOtherSpeculation(m_state.forNode(rightChild).m_type & ~SpecCell))
rightNotCell.link(&m_jit);
else {
jump(notTaken, ForceJump);
@@ -1739,11 +1739,11 @@ void SpeculativeJIT::compileObjectOrOtherLogicalNot(Edge nodeUse, const ClassInf
void SpeculativeJIT::compileLogicalNot(Node& node)
{
if (at(node.child1()).shouldSpeculateFinalObjectOrOther()) {
- compileObjectOrOtherLogicalNot(node.child1(), &JSFinalObject::s_info, !isFinalObjectOrOtherPrediction(m_state.forNode(node.child1()).m_type));
+ compileObjectOrOtherLogicalNot(node.child1(), &JSFinalObject::s_info, !isFinalObjectOrOtherSpeculation(m_state.forNode(node.child1()).m_type));
return;
}
if (at(node.child1()).shouldSpeculateArrayOrOther()) {
- compileObjectOrOtherLogicalNot(node.child1(), &JSArray::s_info, !isArrayOrOtherPrediction(m_state.forNode(node.child1()).m_type));
+ compileObjectOrOtherLogicalNot(node.child1(), &JSArray::s_info, !isArrayOrOtherSpeculation(m_state.forNode(node.child1()).m_type));
return;
}
if (at(node.child1()).shouldSpeculateInteger()) {
@@ -1766,9 +1766,9 @@ void SpeculativeJIT::compileLogicalNot(Node& node)
return;
}
- PredictedType prediction = m_jit.getPrediction(node.child1());
- if (isBooleanPrediction(prediction)) {
- if (isBooleanPrediction(m_state.forNode(node.child1()).m_type)) {
+ SpeculatedType prediction = m_jit.getSpeculation(node.child1());
+ if (isBooleanSpeculation(prediction)) {
+ if (isBooleanSpeculation(m_state.forNode(node.child1()).m_type)) {
SpeculateBooleanOperand value(this, node.child1());
GPRTemporary result(this, value);
@@ -1841,9 +1841,9 @@ void SpeculativeJIT::emitBranch(Node& node)
BlockIndex notTaken = node.notTakenBlockIndex();
if (at(node.child1()).shouldSpeculateFinalObjectOrOther()) {
- emitObjectOrOtherBranch(node.child1(), taken, notTaken, &JSFinalObject::s_info, !isFinalObjectOrOtherPrediction(m_state.forNode(node.child1()).m_type));
+ emitObjectOrOtherBranch(node.child1(), taken, notTaken, &JSFinalObject::s_info, !isFinalObjectOrOtherSpeculation(m_state.forNode(node.child1()).m_type));
} else if (at(node.child1()).shouldSpeculateArrayOrOther()) {
- emitObjectOrOtherBranch(node.child1(), taken, notTaken, &JSArray::s_info, !isArrayOrOtherPrediction(m_state.forNode(node.child1()).m_type));
+ emitObjectOrOtherBranch(node.child1(), taken, notTaken, &JSArray::s_info, !isArrayOrOtherSpeculation(m_state.forNode(node.child1()).m_type));
} else if (at(node.child1()).shouldSpeculateNumber()) {
if (at(node.child1()).shouldSpeculateInteger()) {
bool invert = false;
@@ -1870,10 +1870,10 @@ void SpeculativeJIT::emitBranch(Node& node)
JSValueOperand value(this, node.child1());
GPRReg valueGPR = value.gpr();
- bool predictBoolean = isBooleanPrediction(m_jit.getPrediction(node.child1()));
+ bool predictBoolean = isBooleanSpeculation(m_jit.getSpeculation(node.child1()));
if (predictBoolean) {
- if (isBooleanPrediction(m_state.forNode(node.child1()).m_type)) {
+ if (isBooleanSpeculation(m_state.forNode(node.child1()).m_type)) {
MacroAssembler::ResultCondition condition = MacroAssembler::NonZero;
if (taken == nextBlock()) {
@@ -1924,7 +1924,13 @@ void SpeculativeJIT::compile(Node& node)
switch (op) {
case JSConstant:
+ initConstantInfo(m_compileIndex);
+ break;
+
case PhantomArguments:
+ // This should never be must-generate.
+ ASSERT_NOT_REACHED();
+ // But as a release-mode fall-back make it the empty value.
initConstantInfo(m_compileIndex);
break;
@@ -1934,11 +1940,11 @@ void SpeculativeJIT::compile(Node& node)
break;
case GetLocal: {
- PredictedType prediction = node.variableAccessData()->prediction();
+ SpeculatedType prediction = node.variableAccessData()->prediction();
AbstractValue& value = block()->valuesAtHead.operand(node.local());
// If we have no prediction for this local, then don't attempt to compile.
- if (prediction == PredictNone) {
+ if (prediction == SpecNone) {
terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), NoNode);
break;
}
@@ -1960,7 +1966,7 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- if (isInt32Prediction(value.m_type)) {
+ if (isInt32Speculation(value.m_type)) {
GPRTemporary result(this);
m_jit.load32(JITCompiler::payloadFor(node.local()), result.gpr());
@@ -1984,9 +1990,9 @@ void SpeculativeJIT::compile(Node& node)
DataFormat format;
if (node.variableAccessData()->isCaptured())
format = DataFormatJS;
- else if (isCellPrediction(value.m_type))
+ else if (isCellSpeculation(value.m_type))
format = DataFormatJSCell;
- else if (isBooleanPrediction(value.m_type))
+ else if (isBooleanSpeculation(value.m_type))
format = DataFormatJSBoolean;
else
format = DataFormatJS;
@@ -2053,25 +2059,25 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- PredictedType predictedType = node.variableAccessData()->argumentAwarePrediction();
- if (isInt32Prediction(predictedType)) {
+ SpeculatedType predictedType = node.variableAccessData()->argumentAwarePrediction();
+ if (isInt32Speculation(predictedType)) {
SpeculateIntegerOperand value(this, node.child1());
m_jit.store32(value.gpr(), JITCompiler::payloadFor(node.local()));
noResult(m_compileIndex);
valueSourceReferenceForOperand(node.local()) = ValueSource(Int32InRegisterFile);
break;
}
- if (isArrayPrediction(predictedType)) {
+ if (isArraySpeculation(predictedType)) {
SpeculateCellOperand cell(this, node.child1());
GPRReg cellGPR = cell.gpr();
- if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
+ if (!isArraySpeculation(m_state.forNode(node.child1()).m_type))
speculationCheck(BadType, JSValueRegs(cellGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(cellGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
m_jit.storePtr(cellGPR, JITCompiler::addressFor(node.local()));
noResult(m_compileIndex);
valueSourceReferenceForOperand(node.local()) = ValueSource(CellInRegisterFile);
break;
}
- if (isBooleanPrediction(predictedType)) {
+ if (isBooleanSpeculation(predictedType)) {
SpeculateBooleanOperand boolean(this, node.child1());
m_jit.storePtr(boolean.gpr(), JITCompiler::addressFor(node.local()));
noResult(m_compileIndex);
@@ -2170,7 +2176,7 @@ void SpeculativeJIT::compile(Node& node)
}
case CheckNumber: {
- if (!isNumberPrediction(m_state.forNode(node.child1()).m_type)) {
+ if (!isNumberSpeculation(m_state.forNode(node.child1()).m_type)) {
JSValueOperand op1(this, node.child1());
JITCompiler::Jump isInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, op1.gpr(), GPRInfo::tagTypeNumberRegister);
speculationCheck(
@@ -2370,7 +2376,7 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- if (!at(node.child2()).shouldSpeculateInteger() || !isActionableArrayPrediction(at(node.child1()).prediction())) {
+ if (!at(node.child2()).shouldSpeculateInteger() || !isActionableArraySpeculation(at(node.child1()).prediction())) {
JSValueOperand base(this, node.child1());
JSValueOperand property(this, node.child2());
GPRReg baseGPR = base.gpr();
@@ -2391,7 +2397,7 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- if (at(node.child1()).prediction() == PredictString) {
+ if (at(node.child1()).prediction() == SpecString) {
compileGetByValOnString(node);
if (!m_compileOkay)
return;
@@ -2399,63 +2405,63 @@ void SpeculativeJIT::compile(Node& node)
}
if (at(node.child1()).shouldSpeculateInt8Array()) {
- compileGetByValOnIntTypedArray(m_jit.globalData()->int8ArrayDescriptor(), node, sizeof(int8_t), isInt8ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
+ compileGetByValOnIntTypedArray(m_jit.globalData()->int8ArrayDescriptor(), node, sizeof(int8_t), isInt8ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
if (!m_compileOkay)
return;
break;
}
if (at(node.child1()).shouldSpeculateInt16Array()) {
- compileGetByValOnIntTypedArray(m_jit.globalData()->int16ArrayDescriptor(), node, sizeof(int16_t), isInt16ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
+ compileGetByValOnIntTypedArray(m_jit.globalData()->int16ArrayDescriptor(), node, sizeof(int16_t), isInt16ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
if (!m_compileOkay)
return;
break;
}
if (at(node.child1()).shouldSpeculateInt32Array()) {
- compileGetByValOnIntTypedArray(m_jit.globalData()->int32ArrayDescriptor(), node, sizeof(int32_t), isInt32ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
+ compileGetByValOnIntTypedArray(m_jit.globalData()->int32ArrayDescriptor(), node, sizeof(int32_t), isInt32ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
if (!m_compileOkay)
return;
break;
}
if (at(node.child1()).shouldSpeculateUint8Array()) {
- compileGetByValOnIntTypedArray(m_jit.globalData()->uint8ArrayDescriptor(), node, sizeof(uint8_t), isUint8ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
+ compileGetByValOnIntTypedArray(m_jit.globalData()->uint8ArrayDescriptor(), node, sizeof(uint8_t), isUint8ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
if (!m_compileOkay)
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);
+ compileGetByValOnIntTypedArray(m_jit.globalData()->uint8ClampedArrayDescriptor(), node, sizeof(uint8_t), isUint8ClampedArraySpeculation(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);
+ compileGetByValOnIntTypedArray(m_jit.globalData()->uint16ArrayDescriptor(), node, sizeof(uint16_t), isUint16ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
if (!m_compileOkay)
return;
break;
}
if (at(node.child1()).shouldSpeculateUint32Array()) {
- compileGetByValOnIntTypedArray(m_jit.globalData()->uint32ArrayDescriptor(), node, sizeof(uint32_t), isUint32ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
+ compileGetByValOnIntTypedArray(m_jit.globalData()->uint32ArrayDescriptor(), node, sizeof(uint32_t), isUint32ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
if (!m_compileOkay)
return;
break;
}
if (at(node.child1()).shouldSpeculateFloat32Array()) {
- compileGetByValOnFloatTypedArray(m_jit.globalData()->float32ArrayDescriptor(), node, sizeof(float), isFloat32ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks);
+ compileGetByValOnFloatTypedArray(m_jit.globalData()->float32ArrayDescriptor(), node, sizeof(float), isFloat32ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks);
if (!m_compileOkay)
return;
break;
}
if (at(node.child1()).shouldSpeculateFloat64Array()) {
- compileGetByValOnFloatTypedArray(m_jit.globalData()->float64ArrayDescriptor(), node, sizeof(double), isFloat64ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks);
+ compileGetByValOnFloatTypedArray(m_jit.globalData()->float64ArrayDescriptor(), node, sizeof(double), isFloat64ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks);
if (!m_compileOkay)
return;
break;
@@ -2474,7 +2480,7 @@ void SpeculativeJIT::compile(Node& node)
if (!m_compileOkay)
return;
- if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
+ if (!isArraySpeculation(m_state.forNode(node.child1()).m_type))
speculationCheck(BadType, JSValueRegs(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, JSArray::vectorLengthOffset())));
@@ -2495,7 +2501,7 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- if (!at(node.child2()).shouldSpeculateInteger() || !isActionableMutableArrayPrediction(at(node.child1()).prediction())) {
+ if (!at(node.child2()).shouldSpeculateInteger() || !isActionableMutableArraySpeculation(at(node.child1()).prediction())) {
JSValueOperand arg1(this, node.child1());
JSValueOperand arg2(this, node.child2());
JSValueOperand arg3(this, node.child3());
@@ -2528,7 +2534,7 @@ void SpeculativeJIT::compile(Node& node)
if (!m_compileOkay)
return;
- if (!isArgumentsPrediction(m_state.forNode(node.child1()).m_type)) {
+ if (!isArgumentsSpeculation(m_state.forNode(node.child1()).m_type)) {
speculationCheck(
BadType, JSValueSource::unboxedCell(baseReg), node.child1(),
m_jit.branchPtr(
@@ -2572,61 +2578,61 @@ void SpeculativeJIT::compile(Node& node)
}
if (at(node.child1()).shouldSpeculateInt8Array()) {
- compilePutByValForIntTypedArray(m_jit.globalData()->int8ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(int8_t), isInt8ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
+ compilePutByValForIntTypedArray(m_jit.globalData()->int8ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(int8_t), isInt8ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
if (!m_compileOkay)
return;
break;
}
if (at(node.child1()).shouldSpeculateInt16Array()) {
- compilePutByValForIntTypedArray(m_jit.globalData()->int16ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(int16_t), isInt16ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
+ compilePutByValForIntTypedArray(m_jit.globalData()->int16ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(int16_t), isInt16ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
if (!m_compileOkay)
return;
break;
}
if (at(node.child1()).shouldSpeculateInt32Array()) {
- compilePutByValForIntTypedArray(m_jit.globalData()->int32ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(int32_t), isInt32ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
+ compilePutByValForIntTypedArray(m_jit.globalData()->int32ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(int32_t), isInt32ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
if (!m_compileOkay)
return;
break;
}
if (at(node.child1()).shouldSpeculateUint8Array()) {
- compilePutByValForIntTypedArray(m_jit.globalData()->uint8ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint8_t), isUint8ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
+ compilePutByValForIntTypedArray(m_jit.globalData()->uint8ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint8_t), isUint8ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
if (!m_compileOkay)
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);
+ compilePutByValForIntTypedArray(m_jit.globalData()->uint8ClampedArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint8_t), isUint8ClampedArraySpeculation(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);
+ compilePutByValForIntTypedArray(m_jit.globalData()->uint16ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint16_t), isUint16ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
if (!m_compileOkay)
return;
break;
}
if (at(node.child1()).shouldSpeculateUint32Array()) {
- compilePutByValForIntTypedArray(m_jit.globalData()->uint32ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint32_t), isUint32ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
+ compilePutByValForIntTypedArray(m_jit.globalData()->uint32ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint32_t), isUint32ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
if (!m_compileOkay)
return;
break;
}
if (at(node.child1()).shouldSpeculateFloat32Array()) {
- compilePutByValForFloatTypedArray(m_jit.globalData()->float32ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(float), isFloat32ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks);
+ compilePutByValForFloatTypedArray(m_jit.globalData()->float32ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(float), isFloat32ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks);
if (!m_compileOkay)
return;
break;
}
if (at(node.child1()).shouldSpeculateFloat64Array()) {
- compilePutByValForFloatTypedArray(m_jit.globalData()->float64ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(double), isFloat64ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks);
+ compilePutByValForFloatTypedArray(m_jit.globalData()->float64ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(double), isFloat64ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks);
if (!m_compileOkay)
return;
break;
@@ -2650,7 +2656,7 @@ void SpeculativeJIT::compile(Node& node)
// Check that base is an array, and that property is contained within m_vector (< m_vectorLength).
// If we have predicted the base to be type array, we can skip the check.
- if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
+ if (!isArraySpeculation(m_state.forNode(node.child1()).m_type))
speculationCheck(BadType, JSValueRegs(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
base.use();
@@ -2695,7 +2701,7 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- ASSERT(isActionableMutableArrayPrediction(at(node.child1()).prediction()));
+ ASSERT(isActionableMutableArraySpeculation(at(node.child1()).prediction()));
ASSERT(at(node.child2()).shouldSpeculateInteger());
SpeculateCellOperand base(this, node.child1());
@@ -2847,7 +2853,7 @@ void SpeculativeJIT::compile(Node& node)
writeBarrier(baseGPR, valueGPR, node.child2(), WriteBarrierForPropertyAccess, storageGPR, storageLengthGPR);
- if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
+ if (!isArraySpeculation(m_state.forNode(node.child1()).m_type))
speculationCheck(BadType, JSValueRegs(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), storageGPR);
@@ -2885,7 +2891,7 @@ void SpeculativeJIT::compile(Node& node)
GPRReg storageGPR = storage.gpr();
GPRReg storageLengthGPR = storageLength.gpr();
- if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
+ if (!isArraySpeculation(m_state.forNode(node.child1()).m_type))
speculationCheck(BadType, JSValueRegs(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), storageGPR);
@@ -3012,7 +3018,7 @@ void SpeculativeJIT::compile(Node& node)
op1.use();
- if (!(m_state.forNode(node.child1()).m_type & ~(PredictNumber | PredictBoolean)))
+ if (!(m_state.forNode(node.child1()).m_type & ~(SpecNumber | SpecBoolean)))
m_jit.move(op1GPR, resultGPR);
else {
MacroAssembler::Jump alreadyPrimitive = m_jit.branchTestPtr(MacroAssembler::NonZero, op1GPR, GPRInfo::tagMaskRegister);
@@ -3106,7 +3112,7 @@ void SpeculativeJIT::compile(Node& node)
}
case ConvertThis: {
- if (isObjectPrediction(m_state.forNode(node.child1()).m_type)) {
+ if (isObjectSpeculation(m_state.forNode(node.child1()).m_type)) {
SpeculateCellOperand thisValue(this, node.child1());
GPRTemporary result(this, thisValue);
m_jit.move(thisValue.gpr(), result.gpr());
@@ -3114,13 +3120,13 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- if (isOtherPrediction(at(node.child1()).prediction())) {
+ if (isOtherSpeculation(at(node.child1()).prediction())) {
JSValueOperand thisValue(this, node.child1());
GPRTemporary scratch(this, thisValue);
GPRReg thisValueGPR = thisValue.gpr();
GPRReg scratchGPR = scratch.gpr();
- if (!isOtherPrediction(m_state.forNode(node.child1()).m_type)) {
+ if (!isOtherSpeculation(m_state.forNode(node.child1()).m_type)) {
m_jit.move(thisValueGPR, scratchGPR);
m_jit.andPtr(MacroAssembler::TrustedImm32(~TagBitUndefined), scratchGPR);
speculationCheck(BadType, JSValueRegs(thisValueGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, scratchGPR, MacroAssembler::TrustedImmPtr(reinterpret_cast<void*>(ValueNull))));
@@ -3131,13 +3137,13 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- if (isObjectPrediction(at(node.child1()).prediction())) {
+ if (isObjectSpeculation(at(node.child1()).prediction())) {
SpeculateCellOperand thisValue(this, node.child1());
GPRTemporary result(this, thisValue);
GPRReg thisValueGPR = thisValue.gpr();
GPRReg resultGPR = result.gpr();
- if (!isObjectPrediction(m_state.forNode(node.child1()).m_type))
+ if (!isObjectSpeculation(m_state.forNode(node.child1()).m_type))
speculationCheck(BadType, JSValueRegs(thisValueGPR), node.child1(), m_jit.branchPtr(JITCompiler::Equal, JITCompiler::Address(thisValueGPR, JSCell::classInfoOffset()), JITCompiler::TrustedImmPtr(&JSString::s_info)));
m_jit.move(thisValueGPR, resultGPR);
@@ -3259,7 +3265,7 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- if (isCellPrediction(at(node.child1()).prediction())) {
+ if (isCellSpeculation(at(node.child1()).prediction())) {
SpeculateCellOperand base(this, node.child1());
GPRTemporary result(this, base);
@@ -3309,7 +3315,7 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- if (isCellPrediction(at(node.child1()).prediction())) {
+ if (isCellSpeculation(at(node.child1()).prediction())) {
SpeculateCellOperand base(this, node.child1());
GPRReg baseGPR = base.gpr();
@@ -3356,7 +3362,7 @@ void SpeculativeJIT::compile(Node& node)
GPRReg baseGPR = base.gpr();
GPRReg resultGPR = result.gpr();
- if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
+ if (!isArraySpeculation(m_state.forNode(node.child1()).m_type))
speculationCheck(BadType, JSValueRegs(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), resultGPR);
@@ -3380,7 +3386,7 @@ void SpeculativeJIT::compile(Node& node)
GPRReg baseGPR = base.gpr();
GPRReg resultGPR = result.gpr();
- if (!isStringPrediction(m_state.forNode(node.child1()).m_type))
+ if (!isStringSpeculation(m_state.forNode(node.child1()).m_type))
speculationCheck(BadType, JSValueRegs(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSString::s_info)));
m_jit.load32(MacroAssembler::Address(baseGPR, JSString::offsetOfLength()), resultGPR);
@@ -3390,39 +3396,39 @@ void SpeculativeJIT::compile(Node& node)
}
case GetInt8ArrayLength: {
- compileGetTypedArrayLength(m_jit.globalData()->int8ArrayDescriptor(), node, !isInt8ArrayPrediction(m_state.forNode(node.child1()).m_type));
+ compileGetTypedArrayLength(m_jit.globalData()->int8ArrayDescriptor(), node, !isInt8ArraySpeculation(m_state.forNode(node.child1()).m_type));
break;
}
case GetInt16ArrayLength: {
- compileGetTypedArrayLength(m_jit.globalData()->int16ArrayDescriptor(), node, !isInt16ArrayPrediction(m_state.forNode(node.child1()).m_type));
+ compileGetTypedArrayLength(m_jit.globalData()->int16ArrayDescriptor(), node, !isInt16ArraySpeculation(m_state.forNode(node.child1()).m_type));
break;
}
case GetInt32ArrayLength: {
- compileGetTypedArrayLength(m_jit.globalData()->int32ArrayDescriptor(), node, !isInt32ArrayPrediction(m_state.forNode(node.child1()).m_type));
+ compileGetTypedArrayLength(m_jit.globalData()->int32ArrayDescriptor(), node, !isInt32ArraySpeculation(m_state.forNode(node.child1()).m_type));
break;
}
case GetUint8ArrayLength: {
- compileGetTypedArrayLength(m_jit.globalData()->uint8ArrayDescriptor(), node, !isUint8ArrayPrediction(m_state.forNode(node.child1()).m_type));
+ compileGetTypedArrayLength(m_jit.globalData()->uint8ArrayDescriptor(), node, !isUint8ArraySpeculation(m_state.forNode(node.child1()).m_type));
break;
}
case GetUint8ClampedArrayLength: {
- compileGetTypedArrayLength(m_jit.globalData()->uint8ClampedArrayDescriptor(), node, !isUint8ClampedArrayPrediction(m_state.forNode(node.child1()).m_type));
+ compileGetTypedArrayLength(m_jit.globalData()->uint8ClampedArrayDescriptor(), node, !isUint8ClampedArraySpeculation(m_state.forNode(node.child1()).m_type));
break;
}
case GetUint16ArrayLength: {
- compileGetTypedArrayLength(m_jit.globalData()->uint16ArrayDescriptor(), node, !isUint16ArrayPrediction(m_state.forNode(node.child1()).m_type));
+ compileGetTypedArrayLength(m_jit.globalData()->uint16ArrayDescriptor(), node, !isUint16ArraySpeculation(m_state.forNode(node.child1()).m_type));
break;
}
case GetUint32ArrayLength: {
- compileGetTypedArrayLength(m_jit.globalData()->uint32ArrayDescriptor(), node, !isUint32ArrayPrediction(m_state.forNode(node.child1()).m_type));
+ compileGetTypedArrayLength(m_jit.globalData()->uint32ArrayDescriptor(), node, !isUint32ArraySpeculation(m_state.forNode(node.child1()).m_type));
break;
}
case GetFloat32ArrayLength: {
- compileGetTypedArrayLength(m_jit.globalData()->float32ArrayDescriptor(), node, !isFloat32ArrayPrediction(m_state.forNode(node.child1()).m_type));
+ compileGetTypedArrayLength(m_jit.globalData()->float32ArrayDescriptor(), node, !isFloat32ArraySpeculation(m_state.forNode(node.child1()).m_type));
break;
}
case GetFloat64ArrayLength: {
- compileGetTypedArrayLength(m_jit.globalData()->float64ArrayDescriptor(), node, !isFloat64ArrayPrediction(m_state.forNode(node.child1()).m_type));
+ compileGetTypedArrayLength(m_jit.globalData()->float64ArrayDescriptor(), node, !isFloat64ArraySpeculation(m_state.forNode(node.child1()).m_type));
break;
}
case CheckFunction: {
@@ -3434,7 +3440,7 @@ void SpeculativeJIT::compile(Node& node)
case CheckStructure: {
AbstractValue& value = m_state.forNode(node.child1());
if (value.m_structure.isSubsetOf(node.structureSet())
- && isCellPrediction(value.m_type)) {
+ && isCellSpeculation(value.m_type)) {
noResult(m_compileIndex);
break;
}
@@ -3464,7 +3470,23 @@ void SpeculativeJIT::compile(Node& node)
break;
}
+ case StructureTransitionWatchpoint: {
+ m_jit.addWeakReference(node.structure());
+ node.structure()->addTransitionWatchpoint(speculationWatchpoint());
+
+#if !ASSERT_DISABLED
+ SpeculateCellOperand op1(this, node.child1());
+ JITCompiler::Jump isOK = m_jit.branchPtr(JITCompiler::Equal, JITCompiler::Address(op1.gpr(), JSCell::structureOffset()), TrustedImmPtr(node.structure()));
+ m_jit.breakpoint();
+ isOK.link(&m_jit);
+#endif
+
+ noResult(m_compileIndex);
+ break;
+ }
+
case PhantomPutStructure: {
+ ASSERT(node.structureTransitionData().previousStructure->transitionWatchpointSetHasBeenInvalidated());
m_jit.addWeakReferenceTransition(
node.codeOrigin.codeOriginOwner(),
node.structureTransitionData().previousStructure,
@@ -3474,6 +3496,8 @@ void SpeculativeJIT::compile(Node& node)
}
case PutStructure: {
+ ASSERT(node.structureTransitionData().previousStructure->transitionWatchpointSetHasBeenInvalidated());
+
SpeculateCellOperand base(this, node.child1());
GPRReg baseGPR = base.gpr();
@@ -3587,9 +3611,7 @@ void SpeculativeJIT::compile(Node& node)
case GetGlobalVar: {
GPRTemporary result(this);
- JSVariableObject* globalObject = m_jit.globalObjectFor(node.codeOrigin);
- m_jit.loadPtr(globalObject->addressOfRegisters(), result.gpr());
- m_jit.loadPtr(JITCompiler::addressForGlobalVar(result.gpr(), node.varNumber()), result.gpr());
+ m_jit.loadPtr(node.registerPointer(), result.gpr());
jsValueResult(result.gpr(), m_compileIndex);
break;
@@ -3597,22 +3619,65 @@ void SpeculativeJIT::compile(Node& node)
case PutGlobalVar: {
JSValueOperand value(this, node.child1());
- GPRTemporary globalObject(this);
- GPRTemporary scratch(this);
- GPRReg globalObjectReg = globalObject.gpr();
- GPRReg scratchReg = scratch.gpr();
-
- m_jit.move(MacroAssembler::TrustedImmPtr(m_jit.globalObjectFor(node.codeOrigin)), globalObjectReg);
+ if (Heap::isWriteBarrierEnabled()) {
+ GPRTemporary scratch(this);
+ GPRReg scratchReg = scratch.gpr();
+
+ writeBarrier(m_jit.globalObjectFor(node.codeOrigin), value.gpr(), node.child1(), WriteBarrierForVariableAccess, scratchReg);
+ }
+
+ m_jit.storePtr(value.gpr(), node.registerPointer());
- writeBarrier(m_jit.globalObjectFor(node.codeOrigin), value.gpr(), node.child1(), WriteBarrierForVariableAccess, scratchReg);
+ noResult(m_compileIndex);
+ break;
+ }
- m_jit.loadPtr(MacroAssembler::Address(globalObjectReg, JSVariableObject::offsetOfRegisters()), scratchReg);
- m_jit.storePtr(value.gpr(), JITCompiler::addressForGlobalVar(scratchReg, node.varNumber()));
+ case PutGlobalVarCheck: {
+ JSValueOperand value(this, node.child1());
+
+ WatchpointSet* watchpointSet =
+ m_jit.globalObjectFor(node.codeOrigin)->symbolTable().get(
+ identifier(node.identifierNumberForCheck())->impl()).watchpointSet();
+ addSlowPathGenerator(
+ slowPathCall(
+ m_jit.branchTest8(
+ JITCompiler::NonZero,
+ JITCompiler::AbsoluteAddress(watchpointSet->addressOfIsWatched())),
+ this, operationNotifyGlobalVarWrite, NoResult, watchpointSet));
+
+ if (Heap::isWriteBarrierEnabled()) {
+ GPRTemporary scratch(this);
+ GPRReg scratchReg = scratch.gpr();
+
+ writeBarrier(m_jit.globalObjectFor(node.codeOrigin), value.gpr(), node.child1(), WriteBarrierForVariableAccess, scratchReg);
+ }
+
+ m_jit.storePtr(value.gpr(), node.registerPointer());
noResult(m_compileIndex);
break;
}
+
+ case GlobalVarWatchpoint: {
+ m_jit.globalObjectFor(node.codeOrigin)->symbolTable().get(
+ identifier(node.identifierNumberForCheck())->impl()).addWatchpoint(
+ speculationWatchpoint());
+
+#if DFG_ENABLE(JIT_ASSERT)
+ GPRTemporary scratch(this);
+ GPRReg scratchGPR = scratch.gpr();
+ m_jit.loadPtr(node.registerPointer(), scratchGPR);
+ JITCompiler::Jump ok = m_jit.branchPtr(
+ JITCompiler::Equal, scratchGPR,
+ TrustedImmPtr(bitwise_cast<void*>(JSValue::encode(node.registerPointer()->get()))));
+ m_jit.breakpoint();
+ ok.link(&m_jit);
+#endif
+
+ noResult(m_compileIndex);
+ break;
+ }
case CheckHasInstance: {
SpeculateCellOperand base(this, node.child1());
@@ -3880,7 +3945,7 @@ void SpeculativeJIT::compile(Node& node)
GPRTemporary result(this);
GPRReg resultGPR = result.gpr();
- if (!isEmptyPrediction(
+ if (!isEmptySpeculation(
m_state.variables().operand(
m_jit.graph().argumentsRegisterFor(node.codeOrigin)).m_type)) {
speculationCheck(
@@ -3939,7 +4004,7 @@ void SpeculativeJIT::compile(Node& node)
GPRReg indexGPR = index.gpr();
GPRReg resultGPR = result.gpr();
- if (!isEmptyPrediction(
+ if (!isEmptySpeculation(
m_state.variables().operand(
m_jit.graph().argumentsRegisterFor(node.codeOrigin)).m_type)) {
speculationCheck(
@@ -4021,27 +4086,35 @@ void SpeculativeJIT::compile(Node& node)
: 0) + CallFrame::argumentOffsetIncludingThis(0)) * sizeof(Register)),
resultGPR);
- addSlowPathGenerator(
- slowPathCall(
- slowPath, this, operationGetArgumentByVal, resultGPR,
- m_jit.argumentsRegisterFor(node.codeOrigin),
- indexGPR));
+ if (node.codeOrigin.inlineCallFrame) {
+ addSlowPathGenerator(
+ slowPathCall(
+ slowPath, this, operationGetInlinedArgumentByVal, resultGPR,
+ m_jit.argumentsRegisterFor(node.codeOrigin),
+ node.codeOrigin.inlineCallFrame,
+ indexGPR));
+ } else {
+ addSlowPathGenerator(
+ slowPathCall(
+ slowPath, this, operationGetArgumentByVal, resultGPR,
+ m_jit.argumentsRegisterFor(node.codeOrigin),
+ indexGPR));
+ }
jsValueResult(resultGPR, m_compileIndex);
break;
}
case CheckArgumentsNotCreated: {
- if (!isEmptyPrediction(
- m_state.variables().operand(
- m_jit.graph().argumentsRegisterFor(node.codeOrigin)).m_type)) {
- speculationCheck(
- ArgumentsEscaped, JSValueRegs(), NoNode,
- m_jit.branchTestPtr(
- JITCompiler::NonZero,
- JITCompiler::addressFor(
- m_jit.argumentsRegisterFor(node.codeOrigin))));
- }
+ ASSERT(!isEmptySpeculation(
+ m_state.variables().operand(
+ m_jit.graph().argumentsRegisterFor(node.codeOrigin)).m_type));
+ speculationCheck(
+ ArgumentsEscaped, JSValueRegs(), NoNode,
+ m_jit.branchTestPtr(
+ JITCompiler::NonZero,
+ JITCompiler::addressFor(
+ m_jit.argumentsRegisterFor(node.codeOrigin))));
noResult(m_compileIndex);
break;
}
diff --git a/Source/JavaScriptCore/dfg/DFGThunks.cpp b/Source/JavaScriptCore/dfg/DFGThunks.cpp
index 1ed46c11f..08ca6eaa1 100644
--- a/Source/JavaScriptCore/dfg/DFGThunks.cpp
+++ b/Source/JavaScriptCore/dfg/DFGThunks.cpp
@@ -79,7 +79,7 @@ MacroAssemblerCodeRef osrExitGenerationThunkGenerator(JSGlobalData* globalData)
patchBuffer.link(functionCall, compileOSRExit);
- return patchBuffer.finalizeCode();
+ return FINALIZE_CODE(patchBuffer, ("DFG OSR exit generation thunk"));
}
} } // namespace JSC::DFG
diff --git a/Source/JavaScriptCore/dfg/DFGVariableAccessData.h b/Source/JavaScriptCore/dfg/DFGVariableAccessData.h
index 3dfd94d01..382907d27 100644
--- a/Source/JavaScriptCore/dfg/DFGVariableAccessData.h
+++ b/Source/JavaScriptCore/dfg/DFGVariableAccessData.h
@@ -29,7 +29,7 @@
#include "DFGDoubleFormatState.h"
#include "DFGNodeFlags.h"
#include "Operands.h"
-#include "PredictedType.h"
+#include "SpeculatedType.h"
#include "VirtualRegister.h"
#include <wtf/Platform.h>
#include <wtf/UnionFind.h>
@@ -43,8 +43,8 @@ public:
VariableAccessData()
: m_local(static_cast<VirtualRegister>(std::numeric_limits<int>::min()))
- , m_prediction(PredictNone)
- , m_argumentAwarePrediction(PredictNone)
+ , m_prediction(SpecNone)
+ , m_argumentAwarePrediction(SpecNone)
, m_flags(0)
, m_doubleFormatState(EmptyDoubleFormatState)
, m_isCaptured(false)
@@ -55,8 +55,8 @@ public:
VariableAccessData(VirtualRegister local, bool isCaptured)
: m_local(local)
- , m_prediction(PredictNone)
- , m_argumentAwarePrediction(PredictNone)
+ , m_prediction(SpecNone)
+ , m_argumentAwarePrediction(SpecNone)
, m_flags(0)
, m_doubleFormatState(EmptyDoubleFormatState)
, m_isCaptured(isCaptured)
@@ -104,33 +104,33 @@ public:
return m_isArgumentsAlias;
}
- bool predict(PredictedType prediction)
+ bool predict(SpeculatedType prediction)
{
VariableAccessData* self = find();
- bool result = mergePrediction(self->m_prediction, prediction);
+ bool result = mergeSpeculation(self->m_prediction, prediction);
if (result)
- mergePrediction(m_argumentAwarePrediction, m_prediction);
+ mergeSpeculation(m_argumentAwarePrediction, m_prediction);
return result;
}
- PredictedType nonUnifiedPrediction()
+ SpeculatedType nonUnifiedPrediction()
{
return m_prediction;
}
- PredictedType prediction()
+ SpeculatedType prediction()
{
return find()->m_prediction;
}
- PredictedType argumentAwarePrediction()
+ SpeculatedType argumentAwarePrediction()
{
return find()->m_argumentAwarePrediction;
}
- bool mergeArgumentAwarePrediction(PredictedType prediction)
+ bool mergeArgumentAwarePrediction(SpeculatedType prediction)
{
- return mergePrediction(find()->m_argumentAwarePrediction, prediction);
+ return mergeSpeculation(find()->m_argumentAwarePrediction, prediction);
}
void clearVotes()
@@ -161,12 +161,12 @@ public:
// If the variable is not a number prediction, then this doesn't
// make any sense.
- if (!isNumberPrediction(prediction()))
+ if (!isNumberSpeculation(prediction()))
return false;
// If the variable is predicted to hold only doubles, then it's a
// no-brainer: it should be formatted as a double.
- if (isDoublePrediction(prediction()))
+ if (isDoubleSpeculation(prediction()))
return true;
// If the variable is known to be used as an integer, then be safe -
@@ -225,7 +225,7 @@ public:
if (m_doubleFormatState != UsingDoubleFormat)
return false;
- return mergePrediction(m_prediction, PredictDouble);
+ return mergeSpeculation(m_prediction, SpecDouble);
}
NodeFlags flags() const { return m_flags; }
@@ -246,8 +246,8 @@ private:
// usage for variable access nodes do be significant.
VirtualRegister m_local;
- PredictedType m_prediction;
- PredictedType m_argumentAwarePrediction;
+ SpeculatedType m_prediction;
+ SpeculatedType m_argumentAwarePrediction;
NodeFlags m_flags;
float m_votes[2];
diff --git a/Source/JavaScriptCore/disassembler/Disassembler.h b/Source/JavaScriptCore/disassembler/Disassembler.h
new file mode 100644
index 000000000..7d7400ac8
--- /dev/null
+++ b/Source/JavaScriptCore/disassembler/Disassembler.h
@@ -0,0 +1,49 @@
+/*
+ * 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 Disassembler_h
+#define Disassembler_h
+
+#include <stdio.h>
+#include <wtf/Platform.h>
+#include <wtf/StdLibExtras.h>
+
+namespace JSC {
+
+class MacroAssemblerCodePtr;
+
+#if ENABLE(DISASSEMBLER)
+bool tryToDisassemble(const MacroAssemblerCodePtr&, size_t, const char* prefix, FILE* out);
+#else
+inline bool tryToDisassemble(const MacroAssemblerCodePtr&, size_t, const char*, FILE*)
+{
+ return false;
+}
+#endif
+
+} // namespace JSC
+
+#endif // Disassembler_h
+
diff --git a/Source/JavaScriptCore/disassembler/UDis86Disassembler.cpp b/Source/JavaScriptCore/disassembler/UDis86Disassembler.cpp
new file mode 100644
index 000000000..b6baed4a2
--- /dev/null
+++ b/Source/JavaScriptCore/disassembler/UDis86Disassembler.cpp
@@ -0,0 +1,63 @@
+/*
+ * 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 "Disassembler.h"
+
+#if USE(UDIS86)
+
+#include "MacroAssemblerCodeRef.h"
+#include "udis86.h"
+
+namespace JSC {
+
+bool tryToDisassemble(const MacroAssemblerCodePtr& codePtr, size_t size, const char* prefix, FILE* out)
+{
+ ud_t disassembler;
+ ud_init(&disassembler);
+ ud_set_input_buffer(&disassembler, static_cast<unsigned char*>(codePtr.executableAddress()), size);
+#if CPU(X86_64)
+ ud_set_mode(&disassembler, 64);
+#else
+ ud_set_mode(&disassembler, 32);
+#endif
+ ud_set_pc(&disassembler, bitwise_cast<uintptr_t>(codePtr.executableAddress()));
+ ud_set_syntax(&disassembler, UD_SYN_ATT);
+
+ uint64_t currentPC = disassembler.pc;
+ while (ud_disassemble(&disassembler)) {
+ char pcString[20];
+ snprintf(pcString, sizeof(pcString), "0x%lx", static_cast<unsigned long>(currentPC));
+ fprintf(out, "%s%16s: %s\n", prefix, pcString, ud_insn_asm(&disassembler));
+ currentPC = disassembler.pc;
+ }
+
+ return true;
+}
+
+} // namespace JSC
+
+#endif // USE(UDIS86)
+
diff --git a/Source/JavaScriptCore/disassembler/udis86/differences.txt b/Source/JavaScriptCore/disassembler/udis86/differences.txt
new file mode 100644
index 000000000..3ef51efcf
--- /dev/null
+++ b/Source/JavaScriptCore/disassembler/udis86/differences.txt
@@ -0,0 +1,22 @@
+This documents the differences between the stock version of udis86 and the one found
+here:
+
+- All files not named "udis86" were prefixed with "udis86".
+
+- assert() has been changed to ASSERT()
+
+- Mass rename of udis86_input.h inp_ prefixed functions and macros to ud_inp_ to
+ avoid namespace pollution.
+
+- Removal of KERNEL checks.
+
+- Added #include of udis86_extern.h in udis86_decode.c.
+
+- Removed s_ie__pause and s_ie__nop from udis86_decode.c, since they weren't used.
+
+- Made udis86_syn.h use WTF_ATTRIBUTE_PRINTF. This required making a bunch of little
+ fixes to make the compiler's format string warnings go away.
+
+- Made the code in udis86_syn.h use vsnprintf() instead of vsprintf().
+
+- Fixed udis86_syn-att.c's jump destination printing to work correctly in 64-bit mode.
diff --git a/Source/JavaScriptCore/disassembler/udis86/itab.py b/Source/JavaScriptCore/disassembler/udis86/itab.py
new file mode 100644
index 000000000..27fa9b3f3
--- /dev/null
+++ b/Source/JavaScriptCore/disassembler/udis86/itab.py
@@ -0,0 +1,354 @@
+# udis86 - scripts/itab.py
+#
+# Copyright (c) 2009 Vivek Thampi
+# 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 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 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 A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+
+import sys
+
+sys.path.append( '../scripts' );
+
+import ud_optable
+import ud_opcode
+
+class UdItabGenerator( ud_opcode.UdOpcodeTables ):
+
+ OperandDict = {
+ "Ap" : [ "OP_A" , "SZ_P" ],
+ "E" : [ "OP_E" , "SZ_NA" ],
+ "Eb" : [ "OP_E" , "SZ_B" ],
+ "Ew" : [ "OP_E" , "SZ_W" ],
+ "Ev" : [ "OP_E" , "SZ_V" ],
+ "Ed" : [ "OP_E" , "SZ_D" ],
+ "Eq" : [ "OP_E" , "SZ_Q" ],
+ "Ez" : [ "OP_E" , "SZ_Z" ],
+ "Ex" : [ "OP_E" , "SZ_MDQ" ],
+ "Ep" : [ "OP_E" , "SZ_P" ],
+ "G" : [ "OP_G" , "SZ_NA" ],
+ "Gb" : [ "OP_G" , "SZ_B" ],
+ "Gw" : [ "OP_G" , "SZ_W" ],
+ "Gv" : [ "OP_G" , "SZ_V" ],
+ "Gy" : [ "OP_G" , "SZ_MDQ" ],
+ "Gy" : [ "OP_G" , "SZ_MDQ" ],
+ "Gd" : [ "OP_G" , "SZ_D" ],
+ "Gq" : [ "OP_G" , "SZ_Q" ],
+ "Gx" : [ "OP_G" , "SZ_MDQ" ],
+ "Gz" : [ "OP_G" , "SZ_Z" ],
+ "M" : [ "OP_M" , "SZ_NA" ],
+ "Mb" : [ "OP_M" , "SZ_B" ],
+ "Mw" : [ "OP_M" , "SZ_W" ],
+ "Ms" : [ "OP_M" , "SZ_W" ],
+ "Md" : [ "OP_M" , "SZ_D" ],
+ "Mq" : [ "OP_M" , "SZ_Q" ],
+ "Mt" : [ "OP_M" , "SZ_T" ],
+ "Mo" : [ "OP_M" , "SZ_O" ],
+ "MwRv" : [ "OP_MR" , "SZ_WV" ],
+ "MdRy" : [ "OP_MR" , "SZ_DY" ],
+ "MbRv" : [ "OP_MR" , "SZ_BV" ],
+ "I1" : [ "OP_I1" , "SZ_NA" ],
+ "I3" : [ "OP_I3" , "SZ_NA" ],
+ "Ib" : [ "OP_I" , "SZ_B" ],
+ "Isb" : [ "OP_I" , "SZ_SB" ],
+ "Iw" : [ "OP_I" , "SZ_W" ],
+ "Iv" : [ "OP_I" , "SZ_V" ],
+ "Iz" : [ "OP_I" , "SZ_Z" ],
+ "Jv" : [ "OP_J" , "SZ_V" ],
+ "Jz" : [ "OP_J" , "SZ_Z" ],
+ "Jb" : [ "OP_J" , "SZ_B" ],
+ "R" : [ "OP_R" , "SZ_RDQ" ],
+ "C" : [ "OP_C" , "SZ_NA" ],
+ "D" : [ "OP_D" , "SZ_NA" ],
+ "S" : [ "OP_S" , "SZ_NA" ],
+ "Ob" : [ "OP_O" , "SZ_B" ],
+ "Ow" : [ "OP_O" , "SZ_W" ],
+ "Ov" : [ "OP_O" , "SZ_V" ],
+ "V" : [ "OP_V" , "SZ_O" ],
+ "W" : [ "OP_W" , "SZ_O" ],
+ "Wsd" : [ "OP_W" , "SZ_O" ],
+ "Wss" : [ "OP_W" , "SZ_O" ],
+ "P" : [ "OP_P" , "SZ_Q" ],
+ "Q" : [ "OP_Q" , "SZ_Q" ],
+ "VR" : [ "OP_VR" , "SZ_O" ],
+ "PR" : [ "OP_PR" , "SZ_Q" ],
+ "AL" : [ "OP_AL" , "SZ_NA" ],
+ "CL" : [ "OP_CL" , "SZ_NA" ],
+ "DL" : [ "OP_DL" , "SZ_NA" ],
+ "BL" : [ "OP_BL" , "SZ_NA" ],
+ "AH" : [ "OP_AH" , "SZ_NA" ],
+ "CH" : [ "OP_CH" , "SZ_NA" ],
+ "DH" : [ "OP_DH" , "SZ_NA" ],
+ "BH" : [ "OP_BH" , "SZ_NA" ],
+ "AX" : [ "OP_AX" , "SZ_NA" ],
+ "CX" : [ "OP_CX" , "SZ_NA" ],
+ "DX" : [ "OP_DX" , "SZ_NA" ],
+ "BX" : [ "OP_BX" , "SZ_NA" ],
+ "SI" : [ "OP_SI" , "SZ_NA" ],
+ "DI" : [ "OP_DI" , "SZ_NA" ],
+ "SP" : [ "OP_SP" , "SZ_NA" ],
+ "BP" : [ "OP_BP" , "SZ_NA" ],
+ "eAX" : [ "OP_eAX" , "SZ_NA" ],
+ "eCX" : [ "OP_eCX" , "SZ_NA" ],
+ "eDX" : [ "OP_eDX" , "SZ_NA" ],
+ "eBX" : [ "OP_eBX" , "SZ_NA" ],
+ "eSI" : [ "OP_eSI" , "SZ_NA" ],
+ "eDI" : [ "OP_eDI" , "SZ_NA" ],
+ "eSP" : [ "OP_eSP" , "SZ_NA" ],
+ "eBP" : [ "OP_eBP" , "SZ_NA" ],
+ "rAX" : [ "OP_rAX" , "SZ_NA" ],
+ "rCX" : [ "OP_rCX" , "SZ_NA" ],
+ "rBX" : [ "OP_rBX" , "SZ_NA" ],
+ "rDX" : [ "OP_rDX" , "SZ_NA" ],
+ "rSI" : [ "OP_rSI" , "SZ_NA" ],
+ "rDI" : [ "OP_rDI" , "SZ_NA" ],
+ "rSP" : [ "OP_rSP" , "SZ_NA" ],
+ "rBP" : [ "OP_rBP" , "SZ_NA" ],
+ "ES" : [ "OP_ES" , "SZ_NA" ],
+ "CS" : [ "OP_CS" , "SZ_NA" ],
+ "DS" : [ "OP_DS" , "SZ_NA" ],
+ "SS" : [ "OP_SS" , "SZ_NA" ],
+ "GS" : [ "OP_GS" , "SZ_NA" ],
+ "FS" : [ "OP_FS" , "SZ_NA" ],
+ "ST0" : [ "OP_ST0" , "SZ_NA" ],
+ "ST1" : [ "OP_ST1" , "SZ_NA" ],
+ "ST2" : [ "OP_ST2" , "SZ_NA" ],
+ "ST3" : [ "OP_ST3" , "SZ_NA" ],
+ "ST4" : [ "OP_ST4" , "SZ_NA" ],
+ "ST5" : [ "OP_ST5" , "SZ_NA" ],
+ "ST6" : [ "OP_ST6" , "SZ_NA" ],
+ "ST7" : [ "OP_ST7" , "SZ_NA" ],
+ "NONE" : [ "OP_NONE" , "SZ_NA" ],
+ "ALr8b" : [ "OP_ALr8b" , "SZ_NA" ],
+ "CLr9b" : [ "OP_CLr9b" , "SZ_NA" ],
+ "DLr10b" : [ "OP_DLr10b" , "SZ_NA" ],
+ "BLr11b" : [ "OP_BLr11b" , "SZ_NA" ],
+ "AHr12b" : [ "OP_AHr12b" , "SZ_NA" ],
+ "CHr13b" : [ "OP_CHr13b" , "SZ_NA" ],
+ "DHr14b" : [ "OP_DHr14b" , "SZ_NA" ],
+ "BHr15b" : [ "OP_BHr15b" , "SZ_NA" ],
+ "rAXr8" : [ "OP_rAXr8" , "SZ_NA" ],
+ "rCXr9" : [ "OP_rCXr9" , "SZ_NA" ],
+ "rDXr10" : [ "OP_rDXr10" , "SZ_NA" ],
+ "rBXr11" : [ "OP_rBXr11" , "SZ_NA" ],
+ "rSPr12" : [ "OP_rSPr12" , "SZ_NA" ],
+ "rBPr13" : [ "OP_rBPr13" , "SZ_NA" ],
+ "rSIr14" : [ "OP_rSIr14" , "SZ_NA" ],
+ "rDIr15" : [ "OP_rDIr15" , "SZ_NA" ],
+ "jWP" : [ "OP_J" , "SZ_WP" ],
+ "jDP" : [ "OP_J" , "SZ_DP" ],
+
+ }
+
+ #
+ # opcode prefix dictionary
+ #
+ PrefixDict = {
+ "aso" : "P_aso",
+ "oso" : "P_oso",
+ "rexw" : "P_rexw",
+ "rexb" : "P_rexb",
+ "rexx" : "P_rexx",
+ "rexr" : "P_rexr",
+ "seg" : "P_seg",
+ "inv64" : "P_inv64",
+ "def64" : "P_def64",
+ "depM" : "P_depM",
+ "cast1" : "P_c1",
+ "cast2" : "P_c2",
+ "cast3" : "P_c3",
+ "cast" : "P_cast",
+ "sext" : "P_sext"
+ }
+
+ InvalidEntryIdx = 0
+ InvalidEntry = { 'type' : 'invalid',
+ 'mnemonic' : 'invalid',
+ 'operands' : '',
+ 'prefixes' : '',
+ 'meta' : '' }
+
+ Itab = [] # instruction table
+ ItabIdx = 1 # instruction table index
+ GtabIdx = 0 # group table index
+ GtabMeta = []
+
+ ItabLookup = {}
+
+ MnemonicAliases = ( "invalid", "3dnow", "none", "db", "pause" )
+
+ def __init__( self ):
+ # first itab entry (0) is Invalid
+ self.Itab.append( self.InvalidEntry )
+ self.MnemonicsTable.extend( self.MnemonicAliases )
+
+ def toGroupId( self, id ):
+ return 0x8000 | id
+
+ def genLookupTable( self, table, scope = '' ):
+ idxArray = [ ]
+ ( tabIdx, self.GtabIdx ) = ( self.GtabIdx, self.GtabIdx + 1 )
+ self.GtabMeta.append( { 'type' : table[ 'type' ], 'meta' : table[ 'meta' ] } )
+
+ for _idx in range( self.sizeOfTable( table[ 'type' ] ) ):
+ idx = "%02x" % _idx
+
+ e = self.InvalidEntry
+ i = self.InvalidEntryIdx
+
+ if idx in table[ 'entries' ].keys():
+ e = table[ 'entries' ][ idx ]
+
+ # leaf node (insn)
+ if e[ 'type' ] == 'insn':
+ ( i, self.ItabIdx ) = ( self.ItabIdx, self.ItabIdx + 1 )
+ self.Itab.append( e )
+ elif e[ 'type' ] != 'invalid':
+ i = self.genLookupTable( e, 'static' )
+
+ idxArray.append( i )
+
+ name = "ud_itab__%s" % tabIdx
+ self.ItabLookup[ tabIdx ] = name
+
+ self.ItabC.write( "\n" );
+ if len( scope ):
+ self.ItabC.write( scope + ' ' )
+ self.ItabC.write( "const uint16_t %s[] = {\n" % name )
+ for i in range( len( idxArray ) ):
+ if i > 0 and i % 4 == 0:
+ self.ItabC.write( "\n" )
+ if ( i%4 == 0 ):
+ self.ItabC.write( " /* %2x */" % i)
+ if idxArray[ i ] >= 0x8000:
+ self.ItabC.write( "%12s," % ("GROUP(%d)" % ( ~0x8000 & idxArray[ i ] )))
+ else:
+ self.ItabC.write( "%12d," % ( idxArray[ i ] ))
+ self.ItabC.write( "\n" )
+ self.ItabC.write( "};\n" )
+
+ return self.toGroupId( tabIdx )
+
+ def genLookupTableList( self ):
+ self.ItabC.write( "\n\n" );
+ self.ItabC.write( "struct ud_lookup_table_list_entry ud_lookup_table_list[] = {\n" )
+ for i in range( len( self.GtabMeta ) ):
+ f0 = self.ItabLookup[ i ] + ","
+ f1 = ( self.nameOfTable( self.GtabMeta[ i ][ 'type' ] ) ) + ","
+ f2 = "\"%s\"" % self.GtabMeta[ i ][ 'meta' ]
+ self.ItabC.write( " /* %03d */ { %s %s %s },\n" % ( i, f0, f1, f2 ) )
+ self.ItabC.write( "};" )
+
+ def genInsnTable( self ):
+ self.ItabC.write( "struct ud_itab_entry ud_itab[] = {\n" );
+ idx = 0
+ for e in self.Itab:
+ opr_c = [ "O_NONE", "O_NONE", "O_NONE" ]
+ pfx_c = []
+ opr = e[ 'operands' ]
+ for i in range(len(opr)):
+ if not (opr[i] in self.OperandDict.keys()):
+ print "error: invalid operand declaration: %s\n" % opr[i]
+ opr_c[i] = "O_" + opr[i]
+ opr = "%s %s %s" % (opr_c[0] + ",", opr_c[1] + ",", opr_c[2])
+
+ for p in e['prefixes']:
+ if not ( p in self.PrefixDict.keys() ):
+ print "error: invalid prefix specification: %s \n" % pfx
+ pfx_c.append( self.PrefixDict[p] )
+ if len(e['prefixes']) == 0:
+ pfx_c.append( "P_none" )
+ pfx = "|".join( pfx_c )
+
+ self.ItabC.write( " /* %04d */ { UD_I%s %s, %s },\n" \
+ % ( idx, e[ 'mnemonic' ] + ',', opr, pfx ) )
+ idx += 1
+ self.ItabC.write( "};\n" )
+
+ self.ItabC.write( "\n\n" );
+ self.ItabC.write( "const char * ud_mnemonics_str[] = {\n" )
+ self.ItabC.write( ",\n ".join( [ "\"%s\"" % m for m in self.MnemonicsTable ] ) )
+ self.ItabC.write( "\n};\n" )
+
+
+ def genItabH( self ):
+ self.ItabH = open( "udis86_itab.h", "w" )
+
+ # Generate Table Type Enumeration
+ self.ItabH.write( "#ifndef UD_ITAB_H\n" )
+ self.ItabH.write( "#define UD_ITAB_H\n\n" )
+
+ # table type enumeration
+ self.ItabH.write( "/* ud_table_type -- lookup table types (see lookup.c) */\n" )
+ self.ItabH.write( "enum ud_table_type {\n " )
+ enum = [ self.TableInfo[ k ][ 'name' ] for k in self.TableInfo.keys() ]
+ self.ItabH.write( ",\n ".join( enum ) )
+ self.ItabH.write( "\n};\n\n" );
+
+ # mnemonic enumeration
+ self.ItabH.write( "/* ud_mnemonic -- mnemonic constants */\n" )
+ enum = "enum ud_mnemonic_code {\n "
+ enum += ",\n ".join( [ "UD_I%s" % m for m in self.MnemonicsTable ] )
+ enum += "\n} UD_ATTR_PACKED;\n"
+ self.ItabH.write( enum )
+ self.ItabH.write( "\n" )
+
+ self.ItabH.write("\n/* itab entry operand definitions */\n");
+ operands = self.OperandDict.keys()
+ operands.sort()
+ for o in operands:
+ self.ItabH.write("#define O_%-7s { %-12s %-8s }\n" %
+ (o, self.OperandDict[o][0] + ",", self.OperandDict[o][1]));
+ self.ItabH.write("\n\n");
+
+ self.ItabH.write( "extern const char * ud_mnemonics_str[];\n" )
+
+ self.ItabH.write( "#define GROUP(n) (0x8000 | (n))" )
+
+ self.ItabH.write( "\n#endif /* UD_ITAB_H */\n" )
+
+ self.ItabH.close()
+
+
+ def genItabC( self ):
+ self.ItabC = open( "udis86_itab.c", "w" )
+ self.ItabC.write( "/* itab.c -- generated by itab.py, do no edit" )
+ self.ItabC.write( " */\n" );
+ self.ItabC.write( "#include \"udis86_decode.h\"\n\n" );
+
+ self.genLookupTable( self.OpcodeTable0 )
+ self.genLookupTableList()
+ self.genInsnTable()
+
+ self.ItabC.close()
+
+ def genItab( self ):
+ self.genItabC()
+ self.genItabH()
+
+def main():
+ generator = UdItabGenerator()
+ optableXmlParser = ud_optable.UdOptableXmlParser()
+ optableXmlParser.parse( sys.argv[ 1 ], generator.addInsnDef )
+
+ generator.genItab()
+
+if __name__ == '__main__':
+ main()
diff --git a/Source/JavaScriptCore/disassembler/udis86/optable.xml b/Source/JavaScriptCore/disassembler/udis86/optable.xml
new file mode 100644
index 000000000..14b4ac593
--- /dev/null
+++ b/Source/JavaScriptCore/disassembler/udis86/optable.xml
@@ -0,0 +1,8959 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="optable.xsl" type="text/xsl"?>
+<x86optable>
+
+ <instruction>
+ <mnemonic>aaa</mnemonic>
+ <def>
+ <opc>37</opc>
+ <mode>inv64</mode>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>aad</mnemonic>
+ <def>
+ <opc>d5</opc>
+ <opr>Ib</opr>
+ <mode>inv64</mode>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>aam</mnemonic>
+ <def>
+ <opc>d4</opc>
+ <opr>Ib</opr>
+ <mode>inv64</mode>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>aas</mnemonic>
+ <def>
+ <opc>3f</opc>
+ <mode>inv64</mode>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>adc</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>10</opc>
+ <opr>Eb Gb</opr>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>11</opc>
+ <opr>Ev Gv</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>12</opc>
+ <opr>Gb Eb</opr>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>13</opc>
+ <opr>Gv Ev</opr>
+ </def>
+ <def>
+ <opc>14</opc>
+ <opr>AL Ib</opr>
+ </def>
+ <def>
+ <pfx>oso rexw</pfx>
+ <opc>15</opc>
+ <opr>rAX Iz</opr>
+ <syn>sext</syn>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>80 /reg=2</opc>
+ <opr>Eb Ib</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>82 /reg=2</opc>
+ <opr>Eb Ib</opr>
+ <mode>inv64</mode>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>81 /reg=2</opc>
+ <opr>Ev Iz</opr>
+ <syn>sext</syn>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>83 /reg=2</opc>
+ <opr>Ev Ib</opr>
+ <syn>sext</syn>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>add</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>00</opc>
+ <opr>Eb Gb</opr>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>01</opc>
+ <opr>Ev Gv</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>02</opc>
+ <opr>Gb Eb</opr>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>03</opc>
+ <opr>Gv Ev</opr>
+ </def>
+ <def>
+ <opc>04</opc>
+ <opr>AL Ib</opr>
+ </def>
+ <def>
+ <pfx>oso rexw</pfx>
+ <opc>05</opc>
+ <opr>rAX Iz</opr>
+ <syn>sext</syn>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>80 /reg=0</opc>
+ <opr>Eb Ib</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>82 /reg=0</opc>
+ <opr>Eb Ib</opr>
+ <mode>inv64</mode>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>81 /reg=0</opc>
+ <opr>Ev Iz</opr>
+ <syn>sext</syn>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>83 /reg=0</opc>
+ <opr>Ev Ib</opr>
+ <syn>sext</syn>
+ </def>
+ </instruction>
+
+ <!--
+ SSE2
+ -->
+
+ <instruction>
+ <mnemonic>addpd</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 58</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>addps</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 58</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>addsd</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>ssef2 0f 58</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>addss</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>ssef3 0f 58</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>and</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>20</opc>
+ <opr>Eb Gb</opr>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>21</opc>
+ <opr>Ev Gv</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>22</opc>
+ <opr>Gb Eb</opr>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>23</opc>
+ <opr>Gv Ev</opr>
+ </def>
+ <def>
+ <opc>24</opc>
+ <opr>AL Ib</opr>
+ </def>
+ <def>
+ <pfx>oso rexw</pfx>
+ <opc>25</opc>
+ <opr>rAX Iz</opr>
+ <syn>sext</syn>
+ </def>
+ <def>
+ <pfx>aso rexw rexr rexx rexb</pfx>
+ <opc>80 /reg=4</opc>
+ <opr>Eb Ib</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>82 /reg=4</opc>
+ <opr>Eb Ib</opr>
+ <mode>inv64</mode>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>81 /reg=4</opc>
+ <opr>Ev Iz</opr>
+ <syn>sext</syn>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>83 /reg=4</opc>
+ <opr>Ev Ib</opr>
+ <syn>sext</syn>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>andpd</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 54</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>andps</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 54</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>andnpd</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 55</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>andnps</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 55</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>arpl</mnemonic>
+ <def>
+ <pfx>aso</pfx>
+ <opc>63 /m=16</opc>
+ <opr>Ew Gw</opr>
+ <mode>inv64</mode>
+ </def>
+ <def>
+ <pfx>aso</pfx>
+ <opc>63 /m=32</opc>
+ <opr>Ew Gw</opr>
+ <mode>inv64</mode>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>movsxd</mnemonic>
+ <def>
+ <pfx>aso oso rexw rexx rexr rexb</pfx>
+ <opc>63 /m=64</opc>
+ <opr>Gv Ed</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>bound</mnemonic>
+ <def>
+ <pfx>aso oso</pfx>
+ <opc>62</opc>
+ <opr>Gv M</opr>
+ <mode>inv64</mode>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>bsf</mnemonic>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>0f bc</opc>
+ <opr>Gv Ev</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>bsr</mnemonic>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>0f bd</opc>
+ <opr>Gv Ev</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>bswap</mnemonic>
+ <def>
+ <pfx>oso rexw rexb</pfx>
+ <opc>0f c8</opc>
+ <opr>rAXr8</opr>
+ </def>
+ <def>
+ <pfx>oso rexw rexb</pfx>
+ <opc>0f c9</opc>
+ <opr>rCXr9</opr>
+ </def>
+ <def>
+ <pfx>oso rexw rexb</pfx>
+ <opc>0f ca</opc>
+ <opr>rDXr10</opr>
+ </def>
+ <def>
+ <pfx>oso rexw rexb</pfx>
+ <opc>0f cb</opc>
+ <opr>rBXr11</opr>
+ </def>
+ <def>
+ <pfx>oso rexw rexb</pfx>
+ <opc>0f cc</opc>
+ <opr>rSPr12</opr>
+ </def>
+ <def>
+ <pfx>oso rexw rexb</pfx>
+ <opc>0f cd</opc>
+ <opr>rBPr13</opr>
+ </def>
+ <def>
+ <pfx>oso rexw rexb</pfx>
+ <opc>0f ce</opc>
+ <opr>rSIr14</opr>
+ </def>
+ <def>
+ <pfx>oso rexw rexb</pfx>
+ <opc>0f cf</opc>
+ <opr>rDIr15</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>bt</mnemonic>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>0f ba /reg=4</opc>
+ <opr>Ev Ib</opr>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>0f a3</opc>
+ <opr>Ev Gv</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>btc</mnemonic>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>0f bb</opc>
+ <opr>Ev Gv</opr>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>0f ba /reg=7</opc>
+ <opr>Ev Ib</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>btr</mnemonic>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>0f b3</opc>
+ <opr>Ev Gv</opr>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>0f ba /reg=6</opc>
+ <opr>Ev Ib</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>bts</mnemonic>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>0f ab</opc>
+ <opr>Ev Gv</opr>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>0f ba /reg=5</opc>
+ <opr>Ev Ib</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>call</mnemonic>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>ff /reg=2</opc>
+ <opr>Ev</opr>
+ <mode>def64</mode>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>ff /reg=3</opc>
+ <opr>Ep</opr>
+ </def>
+ <def>
+ <pfx>oso</pfx>
+ <opc>e8</opc>
+ <opr>Jz</opr>
+ <mode>def64</mode>
+ </def>
+ <def>
+ <pfx>oso</pfx>
+ <opc>9a</opc>
+ <opr>Ap</opr>
+ <mode>inv64</mode>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>cbw</mnemonic>
+ <def>
+ <pfx>oso rexw</pfx>
+ <opc>98 /o=16</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>cwde</mnemonic>
+ <def>
+ <pfx>oso rexw</pfx>
+ <opc>98 /o=32</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>cdqe</mnemonic>
+ <def>
+ <pfx>oso rexw</pfx>
+ <opc>98 /o=64</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>clc</mnemonic>
+ <def>
+ <opc>f8</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>cld</mnemonic>
+ <def>
+ <opc>fc</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>clflush</mnemonic>
+ <def>
+ <pfx>aso rexw rexr rexx rexb</pfx>
+ <opc>0f ae /reg=7 /mod=!11</opc>
+ <opr>M</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>clgi</mnemonic>
+ <vendor>amd</vendor>
+ <def>
+ <opc>0f 01 /reg=3 /mod=11 /rm=5</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>cli</mnemonic>
+ <def>
+ <opc>fa</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>clts</mnemonic>
+ <def>
+ <opc>0f 06</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>cmc</mnemonic>
+ <def>
+ <opc>f5</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>cmovo</mnemonic>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>0f 40</opc>
+ <opr>Gv Ev</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>cmovno</mnemonic>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>0f 41</opc>
+ <opr>Gv Ev</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>cmovb</mnemonic>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>0f 42</opc>
+ <opr>Gv Ev</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>cmovae</mnemonic>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>0f 43</opc>
+ <opr>Gv Ev</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>cmovz</mnemonic>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>0f 44</opc>
+ <opr>Gv Ev</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>cmovnz</mnemonic>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>0f 45</opc>
+ <opr>Gv Ev</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>cmovbe</mnemonic>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>0f 46</opc>
+ <opr>Gv Ev</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>cmova</mnemonic>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>0f 47</opc>
+ <opr>Gv Ev</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>cmovs</mnemonic>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>0f 48</opc>
+ <opr>Gv Ev</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>cmovns</mnemonic>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>0f 49</opc>
+ <opr>Gv Ev</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>cmovp</mnemonic>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>0f 4a</opc>
+ <opr>Gv Ev</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>cmovnp</mnemonic>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>0f 4b</opc>
+ <opr>Gv Ev</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>cmovl</mnemonic>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>0f 4c</opc>
+ <opr>Gv Ev</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>cmovge</mnemonic>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>0f 4d</opc>
+ <opr>Gv Ev</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>cmovle</mnemonic>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>0f 4e</opc>
+ <opr>Gv Ev</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>cmovg</mnemonic>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>0f 4f</opc>
+ <opr>Gv Ev</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>cmp</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>38</opc>
+ <opr>Eb Gb</opr>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>39</opc>
+ <opr>Ev Gv</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>3a</opc>
+ <opr>Gb Eb</opr>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>3b</opc>
+ <opr>Gv Ev</opr>
+ </def>
+ <def>
+ <opc>3c</opc>
+ <opr>AL Ib</opr>
+ </def>
+ <def>
+ <pfx>oso rexw</pfx>
+ <opc>3d</opc>
+ <opr>rAX Iz</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>80 /reg=7</opc>
+ <opr>Eb Ib</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>82 /reg=7</opc>
+ <opr>Eb Ib</opr>
+ <mode>inv64</mode>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>81 /reg=7</opc>
+ <opr>Ev Iz</opr>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>83 /reg=7</opc>
+ <opr>Ev Ib</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>cmppd</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f c2</opc>
+ <opr>V W Ib</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>cmpps</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f c2</opc>
+ <opr>V W Ib</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>cmpsb</mnemonic>
+ <def>
+ <opc>a6</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>cmpsw</mnemonic>
+ <def>
+ <pfx>oso rexw</pfx>
+ <opc>a7 /o=16</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>cmpsd</mnemonic>
+ <def>
+ <pfx>oso rexw</pfx>
+ <opc>a7 /o=32</opc>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>ssef2 0f c2</opc>
+ <opr>V W Ib</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>cmpsq</mnemonic>
+ <def>
+ <pfx>oso rexw</pfx>
+ <opc>a7 /o=64</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>cmpss</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>ssef3 0f c2</opc>
+ <opr>V W Ib</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>cmpxchg</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f b0</opc>
+ <opr>Eb Gb</opr>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>0f b1</opc>
+ <opr>Ev Gv</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>cmpxchg8b</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f c7 /reg=1</opc>
+ <opr>M</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>comisd</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 2f</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>comiss</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 2f</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>cpuid</mnemonic>
+ <def>
+ <opc>0f a2</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>cvtdq2pd</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>ssef3 0f e6</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>cvtdq2ps</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 5b</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>cvtpd2dq</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>ssef2 0f e6</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>cvtpd2pi</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 2d</opc>
+ <opr>P W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>cvtpd2ps</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 5a</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>cvtpi2ps</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 2a</opc>
+ <opr>V Q</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>cvtpi2pd</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 2a</opc>
+ <opr>V Q</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>cvtps2dq</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 5b</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>cvtps2pi</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 2d</opc>
+ <opr>P W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>cvtps2pd</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 5a</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>cvtsd2si</mnemonic>
+ <def>
+ <pfx>aso rexw rexr rexx rexb</pfx>
+ <opc>ssef2 0f 2d</opc>
+ <opr>Gy W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>cvtsd2ss</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>ssef2 0f 5a</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>cvtsi2ss</mnemonic>
+ <def>
+ <pfx>aso rexw rexr rexx rexb</pfx>
+ <opc>ssef3 0f 2a</opc>
+ <opr>V Ex</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>cvtss2si</mnemonic>
+ <def>
+ <pfx>aso rexw rexr rexx rexb</pfx>
+ <opc>ssef3 0f 2d</opc>
+ <opr>Gy W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>cvtss2sd</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>ssef3 0f 5a</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>cvttpd2pi</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 2c</opc>
+ <opr>P W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>cvttpd2dq</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f e6</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>cvttps2dq</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>ssef3 0f 5b</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>cvttps2pi</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 2c</opc>
+ <opr>P W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>cvttsd2si</mnemonic>
+ <def>
+ <pfx>aso rexw rexr rexx rexb</pfx>
+ <opc>ssef2 0f 2c</opc>
+ <opr>Gy Wsd</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>cvtsi2sd</mnemonic>
+ <def>
+ <pfx>aso rexw rexr rexx rexb</pfx>
+ <opc>ssef2 0f 2a</opc>
+ <opr>V Ex</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>cvttss2si</mnemonic>
+ <def>
+ <pfx>aso rexw rexr rexx rexb</pfx>
+ <opc>ssef3 0f 2c</opc>
+ <opr>Gy Wsd</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>cwd</mnemonic>
+ <def>
+ <pfx>oso rexw</pfx>
+ <opc>99 /o=16</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>cdq</mnemonic>
+ <def>
+ <pfx>oso rexw</pfx>
+ <opc>99 /o=32</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>cqo</mnemonic>
+ <def>
+ <pfx>oso rexw</pfx>
+ <opc>99 /o=64</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>daa</mnemonic>
+ <def>
+ <opc>27</opc>
+ <mode>inv64</mode>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>das</mnemonic>
+ <def>
+ <opc>2f</opc>
+ <mode>inv64</mode>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>dec</mnemonic>
+ <def>
+ <pfx>oso</pfx>
+ <opc>48</opc>
+ <opr>eAX</opr>
+ </def>
+ <def>
+ <pfx>oso</pfx>
+ <opc>49</opc>
+ <opr>eCX</opr>
+ </def>
+ <def>
+ <pfx>oso</pfx>
+ <opc>4a</opc>
+ <opr>eDX</opr>
+ </def>
+ <def>
+ <pfx>oso</pfx>
+ <opc>4b</opc>
+ <opr>eBX</opr>
+ </def>
+ <def>
+ <pfx>oso</pfx>
+ <opc>4c</opc>
+ <opr>eSP</opr>
+ </def>
+ <def>
+ <pfx>oso</pfx>
+ <opc>4d</opc>
+ <opr>eBP</opr>
+ </def>
+ <def>
+ <pfx>oso</pfx>
+ <opc>4e</opc>
+ <opr>eSI</opr>
+ </def>
+ <def>
+ <pfx>oso</pfx>
+ <opc>4f</opc>
+ <opr>eDI</opr>
+ </def>
+ <def>
+ <pfx>aso rexw rexr rexx rexb</pfx>
+ <opc>fe /reg=1</opc>
+ <opr>Eb</opr>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>ff /reg=1</opc>
+ <opr>Ev</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>div</mnemonic>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>f7 /reg=6</opc>
+ <opr>Ev</opr>
+ </def>
+ <def>
+ <pfx>aso rexw rexr rexx rexb</pfx>
+ <opc>f6 /reg=6</opc>
+ <opr>Eb</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>divpd</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 5e</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>divps</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 5e</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>divsd</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>ssef2 0f 5e</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>divss</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>ssef3 0f 5e</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>emms</mnemonic>
+ <def>
+ <opc>0f 77</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>enter</mnemonic>
+ <def>
+ <opc>c8</opc>
+ <opr>Iw Ib</opr>
+ <mode>def64 depM</mode>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>f2xm1</mnemonic>
+ <class>X87</class>
+ <def>
+ <opc>d9 /mod=11 /x87=30</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fabs</mnemonic>
+ <class>X87</class>
+ <def>
+ <opc>d9 /mod=11 /x87=21</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fadd</mnemonic>
+ <class>X87</class>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>dc /mod=!11 /reg=0</opc>
+ <opr>Mq</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>d8 /mod=!11 /reg=0</opc>
+ <opr>Md</opr>
+ </def>
+ <def>
+ <opc>dc /mod=11 /x87=00</opc>
+ <opr>ST0 ST0</opr>
+ </def>
+ <def>
+ <opc>dc /mod=11 /x87=01</opc>
+ <opr>ST1 ST0</opr>
+ </def>
+ <def>
+ <opc>dc /mod=11 /x87=02</opc>
+ <opr>ST2 ST0</opr>
+ </def>
+ <def>
+ <opc>dc /mod=11 /x87=03</opc>
+ <opr>ST3 ST0</opr>
+ </def>
+ <def>
+ <opc>dc /mod=11 /x87=04</opc>
+ <opr>ST4 ST0</opr>
+ </def>
+ <def>
+ <opc>dc /mod=11 /x87=05</opc>
+ <opr>ST5 ST0</opr>
+ </def>
+ <def>
+ <opc>dc /mod=11 /x87=06</opc>
+ <opr>ST6 ST0</opr>
+ </def>
+ <def>
+ <opc>dc /mod=11 /x87=07</opc>
+ <opr>ST7 ST0</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=00</opc>
+ <opr>ST0 ST0</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=01</opc>
+ <opr>ST0 ST1</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=02</opc>
+ <opr>ST0 ST2</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=03</opc>
+ <opr>ST0 ST3</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=04</opc>
+ <opr>ST0 ST4</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=05</opc>
+ <opr>ST0 ST5</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=06</opc>
+ <opr>ST0 ST6</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=07</opc>
+ <opr>ST0 ST7</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>faddp</mnemonic>
+ <class>X87</class>
+ <def>
+ <opc>de /mod=11 /x87=00</opc>
+ <opr>ST0 ST0</opr>
+ </def>
+ <def>
+ <opc>de /mod=11 /x87=01</opc>
+ <opr>ST1 ST0</opr>
+ </def>
+ <def>
+ <opc>de /mod=11 /x87=02</opc>
+ <opr>ST2 ST0</opr>
+ </def>
+ <def>
+ <opc>de /mod=11 /x87=03</opc>
+ <opr>ST3 ST0</opr>
+ </def>
+ <def>
+ <opc>de /mod=11 /x87=04</opc>
+ <opr>ST4 ST0</opr>
+ </def>
+ <def>
+ <opc>de /mod=11 /x87=05</opc>
+ <opr>ST5 ST0</opr>
+ </def>
+ <def>
+ <opc>de /mod=11 /x87=06</opc>
+ <opr>ST6 ST0</opr>
+ </def>
+ <def>
+ <opc>de /mod=11 /x87=07</opc>
+ <opr>ST7 ST0</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fbld</mnemonic>
+ <class>X87</class>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>df /mod=!11 /reg=4</opc>
+ <opr>Mt</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fbstp</mnemonic>
+ <class>X87</class>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>df /mod=!11 /reg=6</opc>
+ <opr>Mt</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fchs</mnemonic>
+ <class>X87</class>
+ <def>
+ <opc>d9 /mod=11 /x87=20</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fclex</mnemonic>
+ <class>X87</class>
+ <def>
+ <opc>db /mod=11 /x87=22</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fcmovb</mnemonic>
+ <class>X87</class>
+ <def>
+ <opc>da /mod=11 /x87=00</opc>
+ <opr>ST0 ST0</opr>
+ </def>
+ <def>
+ <opc>da /mod=11 /x87=01</opc>
+ <opr>ST0 ST1</opr>
+ </def>
+ <def>
+ <opc>da /mod=11 /x87=02</opc>
+ <opr>ST0 ST2</opr>
+ </def>
+ <def>
+ <opc>da /mod=11 /x87=03</opc>
+ <opr>ST0 ST3</opr>
+ </def>
+ <def>
+ <opc>da /mod=11 /x87=04</opc>
+ <opr>ST0 ST4</opr>
+ </def>
+ <def>
+ <opc>da /mod=11 /x87=05</opc>
+ <opr>ST0 ST5</opr>
+ </def>
+ <def>
+ <opc>da /mod=11 /x87=06</opc>
+ <opr>ST0 ST6</opr>
+ </def>
+ <def>
+ <opc>da /mod=11 /x87=07</opc>
+ <opr>ST0 ST7</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fcmove</mnemonic>
+ <class>X87</class>
+ <def>
+ <opc>da /mod=11 /x87=08</opc>
+ <opr>ST0 ST0</opr>
+ </def>
+ <def>
+ <opc>da /mod=11 /x87=09</opc>
+ <opr>ST0 ST1</opr>
+ </def>
+ <def>
+ <opc>da /mod=11 /x87=0a</opc>
+ <opr>ST0 ST2</opr>
+ </def>
+ <def>
+ <opc>da /mod=11 /x87=0b</opc>
+ <opr>ST0 ST3</opr>
+ </def>
+ <def>
+ <opc>da /mod=11 /x87=0c</opc>
+ <opr>ST0 ST4</opr>
+ </def>
+ <def>
+ <opc>da /mod=11 /x87=0d</opc>
+ <opr>ST0 ST5</opr>
+ </def>
+ <def>
+ <opc>da /mod=11 /x87=0e</opc>
+ <opr>ST0 ST6</opr>
+ </def>
+ <def>
+ <opc>da /mod=11 /x87=0f</opc>
+ <opr>ST0 ST7</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fcmovbe</mnemonic>
+ <class>X87</class>
+ <def>
+ <opc>da /mod=11 /x87=10</opc>
+ <opr>ST0 ST0</opr>
+ </def>
+ <def>
+ <opc>da /mod=11 /x87=11</opc>
+ <opr>ST0 ST1</opr>
+ </def>
+ <def>
+ <opc>da /mod=11 /x87=12</opc>
+ <opr>ST0 ST2</opr>
+ </def>
+ <def>
+ <opc>da /mod=11 /x87=13</opc>
+ <opr>ST0 ST3</opr>
+ </def>
+ <def>
+ <opc>da /mod=11 /x87=14</opc>
+ <opr>ST0 ST4</opr>
+ </def>
+ <def>
+ <opc>da /mod=11 /x87=15</opc>
+ <opr>ST0 ST5</opr>
+ </def>
+ <def>
+ <opc>da /mod=11 /x87=16</opc>
+ <opr>ST0 ST6</opr>
+ </def>
+ <def>
+ <opc>da /mod=11 /x87=17</opc>
+ <opr>ST0 ST7</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fcmovu</mnemonic>
+ <class>X87</class>
+ <def>
+ <opc>da /mod=11 /x87=18</opc>
+ <opr>ST0 ST0</opr>
+ </def>
+ <def>
+ <opc>da /mod=11 /x87=19</opc>
+ <opr>ST0 ST1</opr>
+ </def>
+ <def>
+ <opc>da /mod=11 /x87=1a</opc>
+ <opr>ST0 ST2</opr>
+ </def>
+ <def>
+ <opc>da /mod=11 /x87=1b</opc>
+ <opr>ST0 ST3</opr>
+ </def>
+ <def>
+ <opc>da /mod=11 /x87=1c</opc>
+ <opr>ST0 ST4</opr>
+ </def>
+ <def>
+ <opc>da /mod=11 /x87=1d</opc>
+ <opr>ST0 ST5</opr>
+ </def>
+ <def>
+ <opc>da /mod=11 /x87=1e</opc>
+ <opr>ST0 ST6</opr>
+ </def>
+ <def>
+ <opc>da /mod=11 /x87=1f</opc>
+ <opr>ST0 ST7</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fcmovnb</mnemonic>
+ <class>X87</class>
+ <def>
+ <opc>db /mod=11 /x87=00</opc>
+ <opr>ST0 ST0</opr>
+ </def>
+ <def>
+ <opc>db /mod=11 /x87=01</opc>
+ <opr>ST0 ST1</opr>
+ </def>
+ <def>
+ <opc>db /mod=11 /x87=02</opc>
+ <opr>ST0 ST2</opr>
+ </def>
+ <def>
+ <opc>db /mod=11 /x87=03</opc>
+ <opr>ST0 ST3</opr>
+ </def>
+ <def>
+ <opc>db /mod=11 /x87=04</opc>
+ <opr>ST0 ST4</opr>
+ </def>
+ <def>
+ <opc>db /mod=11 /x87=05</opc>
+ <opr>ST0 ST5</opr>
+ </def>
+ <def>
+ <opc>db /mod=11 /x87=06</opc>
+ <opr>ST0 ST6</opr>
+ </def>
+ <def>
+ <opc>db /mod=11 /x87=07</opc>
+ <opr>ST0 ST7</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fcmovne</mnemonic>
+ <class>X87</class>
+ <def>
+ <opc>db /mod=11 /x87=08</opc>
+ <opr>ST0 ST0</opr>
+ </def>
+ <def>
+ <opc>db /mod=11 /x87=09</opc>
+ <opr>ST0 ST1</opr>
+ </def>
+ <def>
+ <opc>db /mod=11 /x87=0a</opc>
+ <opr>ST0 ST2</opr>
+ </def>
+ <def>
+ <opc>db /mod=11 /x87=0b</opc>
+ <opr>ST0 ST3</opr>
+ </def>
+ <def>
+ <opc>db /mod=11 /x87=0c</opc>
+ <opr>ST0 ST4</opr>
+ </def>
+ <def>
+ <opc>db /mod=11 /x87=0d</opc>
+ <opr>ST0 ST5</opr>
+ </def>
+ <def>
+ <opc>db /mod=11 /x87=0e</opc>
+ <opr>ST0 ST6</opr>
+ </def>
+ <def>
+ <opc>db /mod=11 /x87=0f</opc>
+ <opr>ST0 ST7</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fcmovnbe</mnemonic>
+ <class>X87</class>
+ <def>
+ <opc>db /mod=11 /x87=10</opc>
+ <opr>ST0 ST0</opr>
+ </def>
+ <def>
+ <opc>db /mod=11 /x87=11</opc>
+ <opr>ST0 ST1</opr>
+ </def>
+ <def>
+ <opc>db /mod=11 /x87=12</opc>
+ <opr>ST0 ST2</opr>
+ </def>
+ <def>
+ <opc>db /mod=11 /x87=13</opc>
+ <opr>ST0 ST3</opr>
+ </def>
+ <def>
+ <opc>db /mod=11 /x87=14</opc>
+ <opr>ST0 ST4</opr>
+ </def>
+ <def>
+ <opc>db /mod=11 /x87=15</opc>
+ <opr>ST0 ST5</opr>
+ </def>
+ <def>
+ <opc>db /mod=11 /x87=16</opc>
+ <opr>ST0 ST6</opr>
+ </def>
+ <def>
+ <opc>db /mod=11 /x87=17</opc>
+ <opr>ST0 ST7</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fcmovnu</mnemonic>
+ <class>X87</class>
+ <def>
+ <opc>db /mod=11 /x87=18</opc>
+ <opr>ST0 ST0</opr>
+ </def>
+ <def>
+ <opc>db /mod=11 /x87=19</opc>
+ <opr>ST0 ST1</opr>
+ </def>
+ <def>
+ <opc>db /mod=11 /x87=1a</opc>
+ <opr>ST0 ST2</opr>
+ </def>
+ <def>
+ <opc>db /mod=11 /x87=1b</opc>
+ <opr>ST0 ST3</opr>
+ </def>
+ <def>
+ <opc>db /mod=11 /x87=1c</opc>
+ <opr>ST0 ST4</opr>
+ </def>
+ <def>
+ <opc>db /mod=11 /x87=1d</opc>
+ <opr>ST0 ST5</opr>
+ </def>
+ <def>
+ <opc>db /mod=11 /x87=1e</opc>
+ <opr>ST0 ST6</opr>
+ </def>
+ <def>
+ <opc>db /mod=11 /x87=1f</opc>
+ <opr>ST0 ST7</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fucomi</mnemonic>
+ <class>X87</class>
+ <def>
+ <opc>db /mod=11 /x87=28</opc>
+ <opr>ST0 ST0</opr>
+ </def>
+ <def>
+ <opc>db /mod=11 /x87=29</opc>
+ <opr>ST0 ST1</opr>
+ </def>
+ <def>
+ <opc>db /mod=11 /x87=2a</opc>
+ <opr>ST0 ST2</opr>
+ </def>
+ <def>
+ <opc>db /mod=11 /x87=2b</opc>
+ <opr>ST0 ST3</opr>
+ </def>
+ <def>
+ <opc>db /mod=11 /x87=2c</opc>
+ <opr>ST0 ST4</opr>
+ </def>
+ <def>
+ <opc>db /mod=11 /x87=2d</opc>
+ <opr>ST0 ST5</opr>
+ </def>
+ <def>
+ <opc>db /mod=11 /x87=2e</opc>
+ <opr>ST0 ST6</opr>
+ </def>
+ <def>
+ <opc>db /mod=11 /x87=2f</opc>
+ <opr>ST0 ST7</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fcom</mnemonic>
+ <class>X87</class>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>d8 /mod=!11 /reg=2</opc>
+ <opr>Md</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>dc /mod=!11 /reg=2</opc>
+ <opr>Mq</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=10</opc>
+ <opr>ST0 ST0</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=11</opc>
+ <opr>ST0 ST1</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=12</opc>
+ <opr>ST0 ST2</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=13</opc>
+ <opr>ST0 ST3</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=14</opc>
+ <opr>ST0 ST4</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=15</opc>
+ <opr>ST0 ST5</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=16</opc>
+ <opr>ST0 ST6</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=17</opc>
+ <opr>ST0 ST7</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fcom2</mnemonic>
+ <class>X87 UNDOC</class>
+ <def>
+ <opc>dc /mod=11 /x87=10</opc>
+ <opr>ST0</opr>
+ </def>
+ <def>
+ <opc>dc /mod=11 /x87=11</opc>
+ <opr>ST1</opr>
+ </def>
+ <def>
+ <opc>dc /mod=11 /x87=12</opc>
+ <opr>ST2</opr>
+ </def>
+ <def>
+ <opc>dc /mod=11 /x87=13</opc>
+ <opr>ST3</opr>
+ </def>
+ <def>
+ <opc>dc /mod=11 /x87=14</opc>
+ <opr>ST4</opr>
+ </def>
+ <def>
+ <opc>dc /mod=11 /x87=15</opc>
+ <opr>ST5</opr>
+ </def>
+ <def>
+ <opc>dc /mod=11 /x87=16</opc>
+ <opr>ST6</opr>
+ </def>
+ <def>
+ <opc>dc /mod=11 /x87=17</opc>
+ <opr>ST7</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fcomp3</mnemonic>
+ <class>X87 UNDOC</class>
+ <def>
+ <opc>dc /mod=11 /x87=18</opc>
+ <opr>ST0</opr>
+ </def>
+ <def>
+ <opc>dc /mod=11 /x87=19</opc>
+ <opr>ST1</opr>
+ </def>
+ <def>
+ <opc>dc /mod=11 /x87=1a</opc>
+ <opr>ST2</opr>
+ </def>
+ <def>
+ <opc>dc /mod=11 /x87=1b</opc>
+ <opr>ST3</opr>
+ </def>
+ <def>
+ <opc>dc /mod=11 /x87=1c</opc>
+ <opr>ST4</opr>
+ </def>
+ <def>
+ <opc>dc /mod=11 /x87=1d</opc>
+ <opr>ST5</opr>
+ </def>
+ <def>
+ <opc>dc /mod=11 /x87=1e</opc>
+ <opr>ST6</opr>
+ </def>
+ <def>
+ <opc>dc /mod=11 /x87=1f</opc>
+ <opr>ST7</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fcomi</mnemonic>
+ <class>X87</class>
+ <def>
+ <opc>db /mod=11 /x87=30</opc>
+ <opr>ST0 ST0</opr>
+ </def>
+ <def>
+ <opc>db /mod=11 /x87=31</opc>
+ <opr>ST0 ST1</opr>
+ </def>
+ <def>
+ <opc>db /mod=11 /x87=32</opc>
+ <opr>ST0 ST2</opr>
+ </def>
+ <def>
+ <opc>db /mod=11 /x87=33</opc>
+ <opr>ST0 ST3</opr>
+ </def>
+ <def>
+ <opc>db /mod=11 /x87=34</opc>
+ <opr>ST0 ST4</opr>
+ </def>
+ <def>
+ <opc>db /mod=11 /x87=35</opc>
+ <opr>ST0 ST5</opr>
+ </def>
+ <def>
+ <opc>db /mod=11 /x87=36</opc>
+ <opr>ST0 ST6</opr>
+ </def>
+ <def>
+ <opc>db /mod=11 /x87=37</opc>
+ <opr>ST0 ST7</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fucomip</mnemonic>
+ <class>X87</class>
+ <def>
+ <opc>df /mod=11 /x87=28</opc>
+ <opr>ST0 ST0</opr>
+ </def>
+ <def>
+ <opc>df /mod=11 /x87=29</opc>
+ <opr>ST0 ST1</opr>
+ </def>
+ <def>
+ <opc>df /mod=11 /x87=2a</opc>
+ <opr>ST0 ST2</opr>
+ </def>
+ <def>
+ <opc>df /mod=11 /x87=2b</opc>
+ <opr>ST0 ST3</opr>
+ </def>
+ <def>
+ <opc>df /mod=11 /x87=2c</opc>
+ <opr>ST0 ST4</opr>
+ </def>
+ <def>
+ <opc>df /mod=11 /x87=2d</opc>
+ <opr>ST0 ST5</opr>
+ </def>
+ <def>
+ <opc>df /mod=11 /x87=2e</opc>
+ <opr>ST0 ST6</opr>
+ </def>
+ <def>
+ <opc>df /mod=11 /x87=2f</opc>
+ <opr>ST0 ST7</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fcomip</mnemonic>
+ <class>X87</class>
+ <def>
+ <opc>df /mod=11 /x87=30</opc>
+ <opr>ST0 ST0</opr>
+ </def>
+ <def>
+ <opc>df /mod=11 /x87=31</opc>
+ <opr>ST0 ST1</opr>
+ </def>
+ <def>
+ <opc>df /mod=11 /x87=32</opc>
+ <opr>ST0 ST2</opr>
+ </def>
+ <def>
+ <opc>df /mod=11 /x87=33</opc>
+ <opr>ST0 ST3</opr>
+ </def>
+ <def>
+ <opc>df /mod=11 /x87=34</opc>
+ <opr>ST0 ST4</opr>
+ </def>
+ <def>
+ <opc>df /mod=11 /x87=35</opc>
+ <opr>ST0 ST5</opr>
+ </def>
+ <def>
+ <opc>df /mod=11 /x87=36</opc>
+ <opr>ST0 ST6</opr>
+ </def>
+ <def>
+ <opc>df /mod=11 /x87=37</opc>
+ <opr>ST0 ST7</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fcomp</mnemonic>
+ <class>X87</class>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>d8 /mod=!11 /reg=3</opc>
+ <opr>Md</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>dc /mod=!11 /reg=3</opc>
+ <opr>Mq</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=18</opc>
+ <opr>ST0 ST0</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=19</opc>
+ <opr>ST0 ST1</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=1a</opc>
+ <opr>ST0 ST2</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=1b</opc>
+ <opr>ST0 ST3</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=1c</opc>
+ <opr>ST0 ST4</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=1d</opc>
+ <opr>ST0 ST5</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=1e</opc>
+ <opr>ST0 ST6</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=1f</opc>
+ <opr>ST0 ST7</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fcomp5</mnemonic>
+ <class>X87 UNDOC</class>
+ <def>
+ <opc>de /mod=11 /x87=10</opc>
+ <opr>ST0</opr>
+ </def>
+ <def>
+ <opc>de /mod=11 /x87=11</opc>
+ <opr>ST1</opr>
+ </def>
+ <def>
+ <opc>de /mod=11 /x87=12</opc>
+ <opr>ST2</opr>
+ </def>
+ <def>
+ <opc>de /mod=11 /x87=13</opc>
+ <opr>ST3</opr>
+ </def>
+ <def>
+ <opc>de /mod=11 /x87=14</opc>
+ <opr>ST4</opr>
+ </def>
+ <def>
+ <opc>de /mod=11 /x87=15</opc>
+ <opr>ST5</opr>
+ </def>
+ <def>
+ <opc>de /mod=11 /x87=16</opc>
+ <opr>ST6</opr>
+ </def>
+ <def>
+ <opc>de /mod=11 /x87=17</opc>
+ <opr>ST7</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fcompp</mnemonic>
+ <class>X87</class>
+ <def>
+ <opc>de /mod=11 /x87=19</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fcos</mnemonic>
+ <class>X87</class>
+ <def>
+ <opc>d9 /mod=11 /x87=3f</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fdecstp</mnemonic>
+ <class>X87</class>
+ <def>
+ <opc>d9 /mod=11 /x87=36</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fdiv</mnemonic>
+ <class>X87</class>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>dc /mod=!11 /reg=6</opc>
+ <opr>Mq</opr>
+ </def>
+ <def>
+ <opc>dc /mod=11 /x87=38</opc>
+ <opr>ST0 ST0</opr>
+ </def>
+ <def>
+ <opc>dc /mod=11 /x87=39</opc>
+ <opr>ST1 ST0</opr>
+ </def>
+ <def>
+ <opc>dc /mod=11 /x87=3a</opc>
+ <opr>ST2 ST0</opr>
+ </def>
+ <def>
+ <opc>dc /mod=11 /x87=3b</opc>
+ <opr>ST3 ST0</opr>
+ </def>
+ <def>
+ <opc>dc /mod=11 /x87=3c</opc>
+ <opr>ST4 ST0</opr>
+ </def>
+ <def>
+ <opc>dc /mod=11 /x87=3d</opc>
+ <opr>ST5 ST0</opr>
+ </def>
+ <def>
+ <opc>dc /mod=11 /x87=3e</opc>
+ <opr>ST6 ST0</opr>
+ </def>
+ <def>
+ <opc>dc /mod=11 /x87=3f</opc>
+ <opr>ST7 ST0</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>d8 /mod=!11 /reg=6</opc>
+ <opr>Md</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=30</opc>
+ <opr>ST0 ST0</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=31</opc>
+ <opr>ST0 ST1</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=32</opc>
+ <opr>ST0 ST2</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=33</opc>
+ <opr>ST0 ST3</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=34</opc>
+ <opr>ST0 ST4</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=35</opc>
+ <opr>ST0 ST5</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=36</opc>
+ <opr>ST0 ST6</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=37</opc>
+ <opr>ST0 ST7</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fdivp</mnemonic>
+ <class>X87</class>
+ <def>
+ <opc>de /mod=11 /x87=38</opc>
+ <opr>ST0 ST0</opr>
+ </def>
+ <def>
+ <opc>de /mod=11 /x87=39</opc>
+ <opr>ST1 ST0</opr>
+ </def>
+ <def>
+ <opc>de /mod=11 /x87=3a</opc>
+ <opr>ST2 ST0</opr>
+ </def>
+ <def>
+ <opc>de /mod=11 /x87=3b</opc>
+ <opr>ST3 ST0</opr>
+ </def>
+ <def>
+ <opc>de /mod=11 /x87=3c</opc>
+ <opr>ST4 ST0</opr>
+ </def>
+ <def>
+ <opc>de /mod=11 /x87=3d</opc>
+ <opr>ST5 ST0</opr>
+ </def>
+ <def>
+ <opc>de /mod=11 /x87=3e</opc>
+ <opr>ST6 ST0</opr>
+ </def>
+ <def>
+ <opc>de /mod=11 /x87=3f</opc>
+ <opr>ST7 ST0</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fdivr</mnemonic>
+ <class>X87</class>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>dc /mod=!11 /reg=7</opc>
+ <opr>Mq</opr>
+ </def>
+ <def>
+ <opc>dc /mod=11 /x87=30</opc>
+ <opr>ST0 ST0</opr>
+ </def>
+ <def>
+ <opc>dc /mod=11 /x87=31</opc>
+ <opr>ST1 ST0</opr>
+ </def>
+ <def>
+ <opc>dc /mod=11 /x87=32</opc>
+ <opr>ST2 ST0</opr>
+ </def>
+ <def>
+ <opc>dc /mod=11 /x87=33</opc>
+ <opr>ST3 ST0</opr>
+ </def>
+ <def>
+ <opc>dc /mod=11 /x87=34</opc>
+ <opr>ST4 ST0</opr>
+ </def>
+ <def>
+ <opc>dc /mod=11 /x87=35</opc>
+ <opr>ST5 ST0</opr>
+ </def>
+ <def>
+ <opc>dc /mod=11 /x87=36</opc>
+ <opr>ST6 ST0</opr>
+ </def>
+ <def>
+ <opc>dc /mod=11 /x87=37</opc>
+ <opr>ST7 ST0</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>d8 /mod=!11 /reg=7</opc>
+ <opr>Md</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=38</opc>
+ <opr>ST0 ST0</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=39</opc>
+ <opr>ST0 ST1</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=3a</opc>
+ <opr>ST0 ST2</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=3b</opc>
+ <opr>ST0 ST3</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=3c</opc>
+ <opr>ST0 ST4</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=3d</opc>
+ <opr>ST0 ST5</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=3e</opc>
+ <opr>ST0 ST6</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=3f</opc>
+ <opr>ST0 ST7</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fdivrp</mnemonic>
+ <class>X87</class>
+ <def>
+ <opc>de /mod=11 /x87=30</opc>
+ <opr>ST0 ST0</opr>
+ </def>
+ <def>
+ <opc>de /mod=11 /x87=31</opc>
+ <opr>ST1 ST0</opr>
+ </def>
+ <def>
+ <opc>de /mod=11 /x87=32</opc>
+ <opr>ST2 ST0</opr>
+ </def>
+ <def>
+ <opc>de /mod=11 /x87=33</opc>
+ <opr>ST3 ST0</opr>
+ </def>
+ <def>
+ <opc>de /mod=11 /x87=34</opc>
+ <opr>ST4 ST0</opr>
+ </def>
+ <def>
+ <opc>de /mod=11 /x87=35</opc>
+ <opr>ST5 ST0</opr>
+ </def>
+ <def>
+ <opc>de /mod=11 /x87=36</opc>
+ <opr>ST6 ST0</opr>
+ </def>
+ <def>
+ <opc>de /mod=11 /x87=37</opc>
+ <opr>ST7 ST0</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>femms</mnemonic>
+ <def>
+ <opc>0f 0e</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>ffree</mnemonic>
+ <class>X87</class>
+ <def>
+ <opc>dd /mod=11 /x87=00</opc>
+ <opr>ST0</opr>
+ </def>
+ <def>
+ <opc>dd /mod=11 /x87=01</opc>
+ <opr>ST1</opr>
+ </def>
+ <def>
+ <opc>dd /mod=11 /x87=02</opc>
+ <opr>ST2</opr>
+ </def>
+ <def>
+ <opc>dd /mod=11 /x87=03</opc>
+ <opr>ST3</opr>
+ </def>
+ <def>
+ <opc>dd /mod=11 /x87=04</opc>
+ <opr>ST4</opr>
+ </def>
+ <def>
+ <opc>dd /mod=11 /x87=05</opc>
+ <opr>ST5</opr>
+ </def>
+ <def>
+ <opc>dd /mod=11 /x87=06</opc>
+ <opr>ST6</opr>
+ </def>
+ <def>
+ <opc>dd /mod=11 /x87=07</opc>
+ <opr>ST7</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>ffreep</mnemonic>
+ <class>X87</class>
+ <def>
+ <opc>df /mod=11 /x87=00</opc>
+ <opr>ST0</opr>
+ </def>
+ <def>
+ <opc>df /mod=11 /x87=01</opc>
+ <opr>ST1</opr>
+ </def>
+ <def>
+ <opc>df /mod=11 /x87=02</opc>
+ <opr>ST2</opr>
+ </def>
+ <def>
+ <opc>df /mod=11 /x87=03</opc>
+ <opr>ST3</opr>
+ </def>
+ <def>
+ <opc>df /mod=11 /x87=04</opc>
+ <opr>ST4</opr>
+ </def>
+ <def>
+ <opc>df /mod=11 /x87=05</opc>
+ <opr>ST5</opr>
+ </def>
+ <def>
+ <opc>df /mod=11 /x87=06</opc>
+ <opr>ST6</opr>
+ </def>
+ <def>
+ <opc>df /mod=11 /x87=07</opc>
+ <opr>ST7</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>ficom</mnemonic>
+ <class>X87</class>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>de /mod=!11 /reg=2</opc>
+ <opr>Mw</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>da /mod=!11 /reg=2</opc>
+ <opr>Md</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>ficomp</mnemonic>
+ <class>X87</class>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>de /mod=!11 /reg=3</opc>
+ <opr>Mw</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>da /mod=!11 /reg=3</opc>
+ <opr>Md</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fild</mnemonic>
+ <class>X87</class>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>df /mod=!11 /reg=0</opc>
+ <opr>Mw</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>df /mod=!11 /reg=5</opc>
+ <opr>Mq</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>db /mod=!11 /reg=0</opc>
+ <opr>Md</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fncstp</mnemonic>
+ <class>X87</class>
+ <def>
+ <opc>d9 /mod=11 /x87=37</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fninit</mnemonic>
+ <class>X87</class>
+ <def>
+ <opc>db /mod=11 /x87=23</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fiadd</mnemonic>
+ <class>X87</class>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>da /mod=!11 /reg=0</opc>
+ <opr>Md</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>de /mod=!11 /reg=0</opc>
+ <opr>Mw</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fidivr</mnemonic>
+ <class>X87</class>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>da /mod=!11 /reg=7</opc>
+ <opr>Md</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>de /mod=!11 /reg=7</opc>
+ <opr>Mw</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fidiv</mnemonic>
+ <class>X87</class>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>da /mod=!11 /reg=6</opc>
+ <opr>Md</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>de /mod=!11 /reg=6</opc>
+ <opr>Mw</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fisub</mnemonic>
+ <class>X87</class>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>da /mod=!11 /reg=4</opc>
+ <opr>Md</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>de /mod=!11 /reg=4</opc>
+ <opr>Mw</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fisubr</mnemonic>
+ <class>X87</class>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>da /mod=!11 /reg=5</opc>
+ <opr>Md</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>de /mod=!11 /reg=5</opc>
+ <opr>Mw</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fist</mnemonic>
+ <class>X87</class>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>df /mod=!11 /reg=2</opc>
+ <opr>Mw</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>db /mod=!11 /reg=2</opc>
+ <opr>Md</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fistp</mnemonic>
+ <class>X87</class>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>df /mod=!11 /reg=3</opc>
+ <opr>Mw</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>df /mod=!11 /reg=7</opc>
+ <opr>Mq</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>db /mod=!11 /reg=3</opc>
+ <opr>Md</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fisttp</mnemonic>
+ <class>X87</class>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>db /mod=!11 /reg=1</opc>
+ <opr>Md</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>dd /mod=!11 /reg=1</opc>
+ <opr>Mq</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>df /mod=!11 /reg=1</opc>
+ <opr>Mw</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fld</mnemonic>
+ <class>X87</class>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>db /mod=!11 /reg=5</opc>
+ <opr>Mt</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>dd /mod=!11 /reg=0</opc>
+ <opr>Mq</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>d9 /mod=!11 /reg=0</opc>
+ <opr>Md</opr>
+ </def>
+ <def>
+ <opc>d9 /mod=11 /x87=00</opc>
+ <opr>ST0</opr>
+ </def>
+ <def>
+ <opc>d9 /mod=11 /x87=01</opc>
+ <opr>ST1</opr>
+ </def>
+ <def>
+ <opc>d9 /mod=11 /x87=02</opc>
+ <opr>ST2</opr>
+ </def>
+ <def>
+ <opc>d9 /mod=11 /x87=03</opc>
+ <opr>ST3</opr>
+ </def>
+ <def>
+ <opc>d9 /mod=11 /x87=04</opc>
+ <opr>ST4</opr>
+ </def>
+ <def>
+ <opc>d9 /mod=11 /x87=05</opc>
+ <opr>ST5</opr>
+ </def>
+ <def>
+ <opc>d9 /mod=11 /x87=06</opc>
+ <opr>ST6</opr>
+ </def>
+ <def>
+ <opc>d9 /mod=11 /x87=07</opc>
+ <opr>ST7</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fld1</mnemonic>
+ <class>X87</class>
+ <def>
+ <opc>d9 /mod=11 /x87=28</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fldl2t</mnemonic>
+ <class>X87</class>
+ <def>
+ <opc>d9 /mod=11 /x87=29</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fldl2e</mnemonic>
+ <class>X87</class>
+ <def>
+ <opc>d9 /mod=11 /x87=2a</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fldlpi</mnemonic>
+ <class>X87</class>
+ <def>
+ <opc>d9 /mod=11 /x87=2b</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fldlg2</mnemonic>
+ <class>X87</class>
+ <def>
+ <opc>d9 /mod=11 /x87=2c</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fldln2</mnemonic>
+ <class>X87</class>
+ <def>
+ <opc>d9 /mod=11 /x87=2d</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fldz</mnemonic>
+ <class>X87</class>
+ <def>
+ <opc>d9 /mod=11 /x87=2e</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fldcw</mnemonic>
+ <class>X87</class>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>d9 /mod=!11 /reg=5</opc>
+ <opr>Mw</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fldenv</mnemonic>
+ <class>X87</class>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>d9 /mod=!11 /reg=4</opc>
+ <opr>M</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fmul</mnemonic>
+ <class>X87</class>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>dc /mod=!11 /reg=1</opc>
+ <opr>Mq</opr>
+ </def>
+ <def>
+ <opc>dc /mod=11 /x87=08</opc>
+ <opr>ST0 ST0</opr>
+ </def>
+ <def>
+ <opc>dc /mod=11 /x87=09</opc>
+ <opr>ST1 ST0</opr>
+ </def>
+ <def>
+ <opc>dc /mod=11 /x87=0a</opc>
+ <opr>ST2 ST0</opr>
+ </def>
+ <def>
+ <opc>dc /mod=11 /x87=0b</opc>
+ <opr>ST3 ST0</opr>
+ </def>
+ <def>
+ <opc>dc /mod=11 /x87=0c</opc>
+ <opr>ST4 ST0</opr>
+ </def>
+ <def>
+ <opc>dc /mod=11 /x87=0d</opc>
+ <opr>ST5 ST0</opr>
+ </def>
+ <def>
+ <opc>dc /mod=11 /x87=0e</opc>
+ <opr>ST6 ST0</opr>
+ </def>
+ <def>
+ <opc>dc /mod=11 /x87=0f</opc>
+ <opr>ST7 ST0</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>d8 /mod=!11 /reg=1</opc>
+ <opr>Md</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=08</opc>
+ <opr>ST0 ST0</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=09</opc>
+ <opr>ST0 ST1</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=0a</opc>
+ <opr>ST0 ST2</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=0b</opc>
+ <opr>ST0 ST3</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=0c</opc>
+ <opr>ST0 ST4</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=0d</opc>
+ <opr>ST0 ST5</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=0e</opc>
+ <opr>ST0 ST6</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=0f</opc>
+ <opr>ST0 ST7</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fmulp</mnemonic>
+ <class>X87</class>
+ <def>
+ <opc>de /mod=11 /x87=08</opc>
+ <opr>ST0 ST0</opr>
+ </def>
+ <def>
+ <opc>de /mod=11 /x87=09</opc>
+ <opr>ST1 ST0</opr>
+ </def>
+ <def>
+ <opc>de /mod=11 /x87=0a</opc>
+ <opr>ST2 ST0</opr>
+ </def>
+ <def>
+ <opc>de /mod=11 /x87=0b</opc>
+ <opr>ST3 ST0</opr>
+ </def>
+ <def>
+ <opc>de /mod=11 /x87=0c</opc>
+ <opr>ST4 ST0</opr>
+ </def>
+ <def>
+ <opc>de /mod=11 /x87=0d</opc>
+ <opr>ST5 ST0</opr>
+ </def>
+ <def>
+ <opc>de /mod=11 /x87=0e</opc>
+ <opr>ST6 ST0</opr>
+ </def>
+ <def>
+ <opc>de /mod=11 /x87=0f</opc>
+ <opr>ST7 ST0</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fimul</mnemonic>
+ <class>X87</class>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>da /mod=!11 /reg=1</opc>
+ <opr>Md</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>de /mod=!11 /reg=1</opc>
+ <opr>Mw</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fnop</mnemonic>
+ <class>X87</class>
+ <def>
+ <opc>d9 /mod=11 /x87=10</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fpatan</mnemonic>
+ <class>X87</class>
+ <def>
+ <opc>d9 /mod=11 /x87=33</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fprem</mnemonic>
+ <class>X87</class>
+ <def>
+ <opc>d9 /mod=11 /x87=38</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fprem1</mnemonic>
+ <class>X87</class>
+ <def>
+ <opc>d9 /mod=11 /x87=35</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fptan</mnemonic>
+ <class>X87</class>
+ <def>
+ <opc>d9 /mod=11 /x87=32</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>frndint</mnemonic>
+ <class>X87</class>
+ <def>
+ <opc>d9 /mod=11 /x87=3c</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>frstor</mnemonic>
+ <class>X87</class>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>dd /mod=!11 /reg=4</opc>
+ <opr>M</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fnsave</mnemonic>
+ <class>X87</class>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>dd /mod=!11 /reg=6</opc>
+ <opr>M</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fscale</mnemonic>
+ <class>X87</class>
+ <def>
+ <opc>d9 /mod=11 /x87=3d</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fsin</mnemonic>
+ <class>X87</class>
+ <def>
+ <opc>d9 /mod=11 /x87=3e</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fsincos</mnemonic>
+ <class>X87</class>
+ <def>
+ <opc>d9 /mod=11 /x87=3b</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fsqrt</mnemonic>
+ <class>X87</class>
+ <def>
+ <opc>d9 /mod=11 /x87=3a</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fstp</mnemonic>
+ <class>X87</class>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>db /mod=!11 /reg=7</opc>
+ <opr>Mt</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>dd /mod=!11 /reg=3</opc>
+ <opr>Mq</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>d9 /mod=!11 /reg=3</opc>
+ <opr>Md</opr>
+ </def>
+ <def>
+ <opc>dd /mod=11 /x87=18</opc>
+ <opr>ST0</opr>
+ </def>
+ <def>
+ <opc>dd /mod=11 /x87=19</opc>
+ <opr>ST1</opr>
+ </def>
+ <def>
+ <opc>dd /mod=11 /x87=1a</opc>
+ <opr>ST2</opr>
+ </def>
+ <def>
+ <opc>dd /mod=11 /x87=1b</opc>
+ <opr>ST3</opr>
+ </def>
+ <def>
+ <opc>dd /mod=11 /x87=1c</opc>
+ <opr>ST4</opr>
+ </def>
+ <def>
+ <opc>dd /mod=11 /x87=1d</opc>
+ <opr>ST5</opr>
+ </def>
+ <def>
+ <opc>dd /mod=11 /x87=1e</opc>
+ <opr>ST6</opr>
+ </def>
+ <def>
+ <opc>dd /mod=11 /x87=1f</opc>
+ <opr>ST7</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fstp1</mnemonic>
+ <def>
+ <opc>d9 /mod=11 /x87=18</opc>
+ <opr>ST0</opr>
+ </def>
+ <def>
+ <opc>d9 /mod=11 /x87=19</opc>
+ <opr>ST1</opr>
+ </def>
+ <def>
+ <opc>d9 /mod=11 /x87=1a</opc>
+ <opr>ST2</opr>
+ </def>
+ <def>
+ <opc>d9 /mod=11 /x87=1b</opc>
+ <opr>ST3</opr>
+ </def>
+ <def>
+ <opc>d9 /mod=11 /x87=1c</opc>
+ <opr>ST4</opr>
+ </def>
+ <def>
+ <opc>d9 /mod=11 /x87=1d</opc>
+ <opr>ST5</opr>
+ </def>
+ <def>
+ <opc>d9 /mod=11 /x87=1e</opc>
+ <opr>ST6</opr>
+ </def>
+ <def>
+ <opc>d9 /mod=11 /x87=1f</opc>
+ <opr>ST7</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fstp8</mnemonic>
+ <def>
+ <opc>df /mod=11 /x87=10</opc>
+ <opr>ST0</opr>
+ </def>
+ <def>
+ <opc>df /mod=11 /x87=11</opc>
+ <opr>ST1</opr>
+ </def>
+ <def>
+ <opc>df /mod=11 /x87=12</opc>
+ <opr>ST2</opr>
+ </def>
+ <def>
+ <opc>df /mod=11 /x87=13</opc>
+ <opr>ST3</opr>
+ </def>
+ <def>
+ <opc>df /mod=11 /x87=14</opc>
+ <opr>ST4</opr>
+ </def>
+ <def>
+ <opc>df /mod=11 /x87=15</opc>
+ <opr>ST5</opr>
+ </def>
+ <def>
+ <opc>df /mod=11 /x87=16</opc>
+ <opr>ST6</opr>
+ </def>
+ <def>
+ <opc>df /mod=11 /x87=17</opc>
+ <opr>ST7</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fstp9</mnemonic>
+ <def>
+ <opc>df /mod=11 /x87=18</opc>
+ <opr>ST0</opr>
+ </def>
+ <def>
+ <opc>df /mod=11 /x87=19</opc>
+ <opr>ST1</opr>
+ </def>
+ <def>
+ <opc>df /mod=11 /x87=1a</opc>
+ <opr>ST2</opr>
+ </def>
+ <def>
+ <opc>df /mod=11 /x87=1b</opc>
+ <opr>ST3</opr>
+ </def>
+ <def>
+ <opc>df /mod=11 /x87=1c</opc>
+ <opr>ST4</opr>
+ </def>
+ <def>
+ <opc>df /mod=11 /x87=1d</opc>
+ <opr>ST5</opr>
+ </def>
+ <def>
+ <opc>df /mod=11 /x87=1e</opc>
+ <opr>ST6</opr>
+ </def>
+ <def>
+ <opc>df /mod=11 /x87=1f</opc>
+ <opr>ST7</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fst</mnemonic>
+ <class>X87</class>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>d9 /mod=!11 /reg=2</opc>
+ <opr>Md</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>dd /mod=!11 /reg=2</opc>
+ <opr>Mq</opr>
+ </def>
+ <def>
+ <opc>dd /mod=11 /x87=10</opc>
+ <opr>ST0</opr>
+ </def>
+ <def>
+ <opc>dd /mod=11 /x87=11</opc>
+ <opr>ST1</opr>
+ </def>
+ <def>
+ <opc>dd /mod=11 /x87=12</opc>
+ <opr>ST2</opr>
+ </def>
+ <def>
+ <opc>dd /mod=11 /x87=13</opc>
+ <opr>ST3</opr>
+ </def>
+ <def>
+ <opc>dd /mod=11 /x87=14</opc>
+ <opr>ST4</opr>
+ </def>
+ <def>
+ <opc>dd /mod=11 /x87=15</opc>
+ <opr>ST5</opr>
+ </def>
+ <def>
+ <opc>dd /mod=11 /x87=16</opc>
+ <opr>ST6</opr>
+ </def>
+ <def>
+ <opc>dd /mod=11 /x87=17</opc>
+ <opr>ST7</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fnstcw</mnemonic>
+ <class>X87</class>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>d9 /mod=!11 /reg=7</opc>
+ <opr>Mw</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fnstenv</mnemonic>
+ <class>X87</class>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>d9 /mod=!11 /reg=6</opc>
+ <opr>M</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fnstsw</mnemonic>
+ <class>X87</class>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>dd /mod=!11 /reg=7</opc>
+ <opr>Mw</opr>
+ </def>
+ <def>
+ <opc>df /mod=11 /x87=20</opc>
+ <opr>AX</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fsub</mnemonic>
+ <class>X87</class>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>d8 /mod=!11 /reg=4</opc>
+ <opr>Md</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>dc /mod=!11 /reg=4</opc>
+ <opr>Mq</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=20</opc>
+ <opr>ST0 ST0</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=21</opc>
+ <opr>ST0 ST1</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=22</opc>
+ <opr>ST0 ST2</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=23</opc>
+ <opr>ST0 ST3</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=24</opc>
+ <opr>ST0 ST4</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=25</opc>
+ <opr>ST0 ST5</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=26</opc>
+ <opr>ST0 ST6</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=27</opc>
+ <opr>ST0 ST7</opr>
+ </def>
+ <def>
+ <opc>dc /mod=11 /x87=28</opc>
+ <opr>ST0 ST0</opr>
+ </def>
+ <def>
+ <opc>dc /mod=11 /x87=29</opc>
+ <opr>ST1 ST0</opr>
+ </def>
+ <def>
+ <opc>dc /mod=11 /x87=2a</opc>
+ <opr>ST2 ST0</opr>
+ </def>
+ <def>
+ <opc>dc /mod=11 /x87=2b</opc>
+ <opr>ST3 ST0</opr>
+ </def>
+ <def>
+ <opc>dc /mod=11 /x87=2c</opc>
+ <opr>ST4 ST0</opr>
+ </def>
+ <def>
+ <opc>dc /mod=11 /x87=2d</opc>
+ <opr>ST5 ST0</opr>
+ </def>
+ <def>
+ <opc>dc /mod=11 /x87=2e</opc>
+ <opr>ST6 ST0</opr>
+ </def>
+ <def>
+ <opc>dc /mod=11 /x87=2f</opc>
+ <opr>ST7 ST0</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fsubp</mnemonic>
+ <class>X87</class>
+ <def>
+ <opc>de /mod=11 /x87=28</opc>
+ <opr>ST0 ST0</opr>
+ </def>
+ <def>
+ <opc>de /mod=11 /x87=29</opc>
+ <opr>ST1 ST0</opr>
+ </def>
+ <def>
+ <opc>de /mod=11 /x87=2a</opc>
+ <opr>ST2 ST0</opr>
+ </def>
+ <def>
+ <opc>de /mod=11 /x87=2b</opc>
+ <opr>ST3 ST0</opr>
+ </def>
+ <def>
+ <opc>de /mod=11 /x87=2c</opc>
+ <opr>ST4 ST0</opr>
+ </def>
+ <def>
+ <opc>de /mod=11 /x87=2d</opc>
+ <opr>ST5 ST0</opr>
+ </def>
+ <def>
+ <opc>de /mod=11 /x87=2e</opc>
+ <opr>ST6 ST0</opr>
+ </def>
+ <def>
+ <opc>de /mod=11 /x87=2f</opc>
+ <opr>ST7 ST0</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fsubr</mnemonic>
+ <class>X87</class>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>dc /mod=!11 /reg=5</opc>
+ <opr>Mq</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=28</opc>
+ <opr>ST0 ST0</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=29</opc>
+ <opr>ST0 ST1</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=2a</opc>
+ <opr>ST0 ST2</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=2b</opc>
+ <opr>ST0 ST3</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=2c</opc>
+ <opr>ST0 ST4</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=2d</opc>
+ <opr>ST0 ST5</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=2e</opc>
+ <opr>ST0 ST6</opr>
+ </def>
+ <def>
+ <opc>d8 /mod=11 /x87=2f</opc>
+ <opr>ST0 ST7</opr>
+ </def>
+ <def>
+ <opc>dc /mod=11 /x87=20</opc>
+ <opr>ST0 ST0</opr>
+ </def>
+ <def>
+ <opc>dc /mod=11 /x87=21</opc>
+ <opr>ST1 ST0</opr>
+ </def>
+ <def>
+ <opc>dc /mod=11 /x87=22</opc>
+ <opr>ST2 ST0</opr>
+ </def>
+ <def>
+ <opc>dc /mod=11 /x87=23</opc>
+ <opr>ST3 ST0</opr>
+ </def>
+ <def>
+ <opc>dc /mod=11 /x87=24</opc>
+ <opr>ST4 ST0</opr>
+ </def>
+ <def>
+ <opc>dc /mod=11 /x87=25</opc>
+ <opr>ST5 ST0</opr>
+ </def>
+ <def>
+ <opc>dc /mod=11 /x87=26</opc>
+ <opr>ST6 ST0</opr>
+ </def>
+ <def>
+ <opc>dc /mod=11 /x87=27</opc>
+ <opr>ST7 ST0</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>d8 /mod=!11 /reg=5</opc>
+ <opr>Md</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fsubrp</mnemonic>
+ <class>X87</class>
+ <def>
+ <opc>de /mod=11 /x87=20</opc>
+ <opr>ST0 ST0</opr>
+ </def>
+ <def>
+ <opc>de /mod=11 /x87=21</opc>
+ <opr>ST1 ST0</opr>
+ </def>
+ <def>
+ <opc>de /mod=11 /x87=22</opc>
+ <opr>ST2 ST0</opr>
+ </def>
+ <def>
+ <opc>de /mod=11 /x87=23</opc>
+ <opr>ST3 ST0</opr>
+ </def>
+ <def>
+ <opc>de /mod=11 /x87=24</opc>
+ <opr>ST4 ST0</opr>
+ </def>
+ <def>
+ <opc>de /mod=11 /x87=25</opc>
+ <opr>ST5 ST0</opr>
+ </def>
+ <def>
+ <opc>de /mod=11 /x87=26</opc>
+ <opr>ST6 ST0</opr>
+ </def>
+ <def>
+ <opc>de /mod=11 /x87=27</opc>
+ <opr>ST7 ST0</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>ftst</mnemonic>
+ <class>X87</class>
+ <def>
+ <opc>d9 /mod=11 /x87=24</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fucom</mnemonic>
+ <class>X87</class>
+ <def>
+ <opc>dd /mod=11 /x87=20</opc>
+ <opr>ST0</opr>
+ </def>
+ <def>
+ <opc>dd /mod=11 /x87=21</opc>
+ <opr>ST1</opr>
+ </def>
+ <def>
+ <opc>dd /mod=11 /x87=22</opc>
+ <opr>ST2</opr>
+ </def>
+ <def>
+ <opc>dd /mod=11 /x87=23</opc>
+ <opr>ST3</opr>
+ </def>
+ <def>
+ <opc>dd /mod=11 /x87=24</opc>
+ <opr>ST4</opr>
+ </def>
+ <def>
+ <opc>dd /mod=11 /x87=25</opc>
+ <opr>ST5</opr>
+ </def>
+ <def>
+ <opc>dd /mod=11 /x87=26</opc>
+ <opr>ST6</opr>
+ </def>
+ <def>
+ <opc>dd /mod=11 /x87=27</opc>
+ <opr>ST7</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fucomp</mnemonic>
+ <class>X87</class>
+ <def>
+ <opc>dd /mod=11 /x87=28</opc>
+ <opr>ST0</opr>
+ </def>
+ <def>
+ <opc>dd /mod=11 /x87=29</opc>
+ <opr>ST1</opr>
+ </def>
+ <def>
+ <opc>dd /mod=11 /x87=2a</opc>
+ <opr>ST2</opr>
+ </def>
+ <def>
+ <opc>dd /mod=11 /x87=2b</opc>
+ <opr>ST3</opr>
+ </def>
+ <def>
+ <opc>dd /mod=11 /x87=2c</opc>
+ <opr>ST4</opr>
+ </def>
+ <def>
+ <opc>dd /mod=11 /x87=2d</opc>
+ <opr>ST5</opr>
+ </def>
+ <def>
+ <opc>dd /mod=11 /x87=2e</opc>
+ <opr>ST6</opr>
+ </def>
+ <def>
+ <opc>dd /mod=11 /x87=2f</opc>
+ <opr>ST7</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fucompp</mnemonic>
+ <class>X87</class>
+ <def>
+ <opc>da /mod=11 /x87=29</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fxam</mnemonic>
+ <class>X87</class>
+ <def>
+ <opc>d9 /mod=11 /x87=25</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fxch</mnemonic>
+ <class>X87</class>
+ <def>
+ <opc>d9 /mod=11 /x87=08</opc>
+ <opr>ST0 ST0</opr>
+ </def>
+ <def>
+ <opc>d9 /mod=11 /x87=09</opc>
+ <opr>ST0 ST1</opr>
+ </def>
+ <def>
+ <opc>d9 /mod=11 /x87=0a</opc>
+ <opr>ST0 ST2</opr>
+ </def>
+ <def>
+ <opc>d9 /mod=11 /x87=0b</opc>
+ <opr>ST0 ST3</opr>
+ </def>
+ <def>
+ <opc>d9 /mod=11 /x87=0c</opc>
+ <opr>ST0 ST4</opr>
+ </def>
+ <def>
+ <opc>d9 /mod=11 /x87=0d</opc>
+ <opr>ST0 ST5</opr>
+ </def>
+ <def>
+ <opc>d9 /mod=11 /x87=0e</opc>
+ <opr>ST0 ST6</opr>
+ </def>
+ <def>
+ <opc>d9 /mod=11 /x87=0f</opc>
+ <opr>ST0 ST7</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fxch4</mnemonic>
+ <class>X87</class>
+ <def>
+ <opc>dd /mod=11 /x87=08</opc>
+ <opr>ST0</opr>
+ </def>
+ <def>
+ <opc>dd /mod=11 /x87=09</opc>
+ <opr>ST1</opr>
+ </def>
+ <def>
+ <opc>dd /mod=11 /x87=0a</opc>
+ <opr>ST2</opr>
+ </def>
+ <def>
+ <opc>dd /mod=11 /x87=0b</opc>
+ <opr>ST3</opr>
+ </def>
+ <def>
+ <opc>dd /mod=11 /x87=0c</opc>
+ <opr>ST4</opr>
+ </def>
+ <def>
+ <opc>dd /mod=11 /x87=0d</opc>
+ <opr>ST5</opr>
+ </def>
+ <def>
+ <opc>dd /mod=11 /x87=0e</opc>
+ <opr>ST6</opr>
+ </def>
+ <def>
+ <opc>dd /mod=11 /x87=0f</opc>
+ <opr>ST7</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fxch7</mnemonic>
+ <class>X87</class>
+ <def>
+ <opc>df /mod=11 /x87=08</opc>
+ <opr>ST0</opr>
+ </def>
+ <def>
+ <opc>df /mod=11 /x87=09</opc>
+ <opr>ST1</opr>
+ </def>
+ <def>
+ <opc>df /mod=11 /x87=0a</opc>
+ <opr>ST2</opr>
+ </def>
+ <def>
+ <opc>df /mod=11 /x87=0b</opc>
+ <opr>ST3</opr>
+ </def>
+ <def>
+ <opc>df /mod=11 /x87=0c</opc>
+ <opr>ST4</opr>
+ </def>
+ <def>
+ <opc>df /mod=11 /x87=0d</opc>
+ <opr>ST5</opr>
+ </def>
+ <def>
+ <opc>df /mod=11 /x87=0e</opc>
+ <opr>ST6</opr>
+ </def>
+ <def>
+ <opc>df /mod=11 /x87=0f</opc>
+ <opr>ST7</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fxrstor</mnemonic>
+ <def>
+ <pfx>aso rexw rexr rexx rexb</pfx>
+ <opc>0f ae /mod=11 /reg=1</opc>
+ <opr>M</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fxsave</mnemonic>
+ <def>
+ <pfx>aso rexw rexr rexx rexb</pfx>
+ <opc>0f ae /mod=11 /reg=0</opc>
+ <opr>M</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fpxtract</mnemonic>
+ <class>X87</class>
+ <def>
+ <opc>d9 /mod=11 /x87=34</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fyl2x</mnemonic>
+ <class>X87</class>
+ <def>
+ <opc>d9 /mod=11 /x87=31</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>fyl2xp1</mnemonic>
+ <class>X87</class>
+ <def>
+ <opc>d9 /mod=11 /x87=39</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>hlt</mnemonic>
+ <def>
+ <opc>f4</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>idiv</mnemonic>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>f7 /reg=7</opc>
+ <opr>Ev</opr>
+ </def>
+ <def>
+ <pfx>aso rexw rexr rexx rexb</pfx>
+ <opc>f6 /reg=7</opc>
+ <opr>Eb</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>in</mnemonic>
+ <def>
+ <opc>e4</opc>
+ <opr>AL Ib</opr>
+ </def>
+ <def>
+ <pfx>oso</pfx>
+ <opc>e5</opc>
+ <opr>eAX Ib</opr>
+ </def>
+ <def>
+ <opc>ec</opc>
+ <opr>AL DX</opr>
+ </def>
+ <def>
+ <pfx>oso</pfx>
+ <opc>ed</opc>
+ <opr>eAX DX</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>imul</mnemonic>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>0f af</opc>
+ <opr>Gv Ev</opr>
+ </def>
+ <def>
+ <pfx>aso rexw rexr rexx rexb</pfx>
+ <opc>f6 /reg=5</opc>
+ <opr>Eb</opr>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>f7 /reg=5</opc>
+ <opr>Ev</opr>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>69</opc>
+ <opr>Gv Ev Iz</opr>
+ <syn>sext</syn>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>6b</opc>
+ <opr>Gv Ev Ib</opr>
+ <syn>sext</syn>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>inc</mnemonic>
+ <def>
+ <pfx>oso</pfx>
+ <opc>40</opc>
+ <opr>eAX</opr>
+ </def>
+ <def>
+ <pfx>oso</pfx>
+ <opc>41</opc>
+ <opr>eCX</opr>
+ </def>
+ <def>
+ <pfx>oso</pfx>
+ <opc>42</opc>
+ <opr>eDX</opr>
+ </def>
+ <def>
+ <pfx>oso</pfx>
+ <opc>43</opc>
+ <opr>eBX</opr>
+ </def>
+ <def>
+ <pfx>oso</pfx>
+ <opc>44</opc>
+ <opr>eSP</opr>
+ </def>
+ <def>
+ <pfx>oso</pfx>
+ <opc>45</opc>
+ <opr>eBP</opr>
+ </def>
+ <def>
+ <pfx>oso</pfx>
+ <opc>46</opc>
+ <opr>eSI</opr>
+ </def>
+ <def>
+ <pfx>oso</pfx>
+ <opc>47</opc>
+ <opr>eDI</opr>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>ff /reg=0</opc>
+ <opr>Ev</opr>
+ </def>
+ <def>
+ <pfx>aso rexw rexr rexx rexb</pfx>
+ <opc>fe /reg=0</opc>
+ <opr>Eb</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>insb</mnemonic>
+ <def>
+ <opc>6c</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>insw</mnemonic>
+ <def>
+ <pfx>oso</pfx>
+ <opc>6d /o=16</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>insd</mnemonic>
+ <def>
+ <pfx>oso</pfx>
+ <opc>6d /o=32</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>int1</mnemonic>
+ <def>
+ <opc>f1</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>int3</mnemonic>
+ <def>
+ <opc>cc</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>int</mnemonic>
+ <def>
+ <opc>cd</opc>
+ <opr>Ib</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>into</mnemonic>
+ <def>
+ <opc>ce</opc>
+ <mode>inv64</mode>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>invd</mnemonic>
+ <def>
+ <opc>0f 08</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>invept</mnemonic>
+ <vendor>intel</vendor>
+ <def>
+ <opc>sse66 0f 38 80 /m=32</opc>
+ <opr>Gd Mo</opr>
+ </def>
+ <def>
+ <opc>sse66 0f 38 80 /m=64</opc>
+ <opr>Gq Mo</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>invlpg</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 01 /reg=7 /mod=!11</opc>
+ <opr>M</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>invlpga</mnemonic>
+ <vendor>amd</vendor>
+ <def>
+ <opc>0f 01 /reg=3 /mod=11 /rm=7</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>invvpid</mnemonic>
+ <vendor>intel</vendor>
+ <def>
+ <opc>sse66 0f 38 81 /m=32</opc>
+ <opr>Gd Mo</opr>
+ </def>
+ <def>
+ <opc>sse66 0f 38 81 /m=64</opc>
+ <opr>Gq Mo</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>iretw</mnemonic>
+ <def>
+ <pfx>oso rexw</pfx>
+ <opc>cf /o=16</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>iretd</mnemonic>
+ <def>
+ <pfx>oso rexw</pfx>
+ <opc>cf /o=32</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>iretq</mnemonic>
+ <def>
+ <pfx>oso rexw</pfx>
+ <opc>cf /o=64</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>jo</mnemonic>
+ <def>
+ <opc>70</opc>
+ <opr>Jb</opr>
+ </def>
+ <def>
+ <pfx>oso</pfx>
+ <opc>0f 80</opc>
+ <opr>Jz</opr>
+ <mode>def64 depM</mode>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>jno</mnemonic>
+ <def>
+ <opc>71</opc>
+ <opr>Jb</opr>
+ </def>
+ <def>
+ <pfx>oso</pfx>
+ <opc>0f 81</opc>
+ <opr>Jz</opr>
+ <mode>def64 depM</mode>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>jb</mnemonic>
+ <def>
+ <opc>72</opc>
+ <opr>Jb</opr>
+ </def>
+ <def>
+ <pfx>oso</pfx>
+ <opc>0f 82</opc>
+ <opr>Jz</opr>
+ <mode>def64 depM</mode>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>jae</mnemonic>
+ <def>
+ <opc>73</opc>
+ <opr>Jb</opr>
+ </def>
+ <def>
+ <pfx>oso</pfx>
+ <opc>0f 83</opc>
+ <opr>Jz</opr>
+ <mode>def64 depM</mode>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>jz</mnemonic>
+ <def>
+ <opc>74</opc>
+ <opr>Jb</opr>
+ </def>
+ <def>
+ <pfx>oso</pfx>
+ <opc>0f 84</opc>
+ <opr>Jz</opr>
+ <mode>def64 depM</mode>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>jnz</mnemonic>
+ <def>
+ <opc>75</opc>
+ <opr>Jb</opr>
+ </def>
+ <def>
+ <pfx>oso</pfx>
+ <opc>0f 85</opc>
+ <opr>Jz</opr>
+ <mode>def64 depM</mode>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>jbe</mnemonic>
+ <def>
+ <opc>76</opc>
+ <opr>Jb</opr>
+ </def>
+ <def>
+ <pfx>oso</pfx>
+ <opc>0f 86</opc>
+ <opr>Jz</opr>
+ <mode>def64 depM</mode>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>ja</mnemonic>
+ <def>
+ <opc>77</opc>
+ <opr>Jb</opr>
+ </def>
+ <def>
+ <pfx>oso</pfx>
+ <opc>0f 87</opc>
+ <opr>Jz</opr>
+ <mode>def64 depM</mode>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>js</mnemonic>
+ <def>
+ <opc>78</opc>
+ <opr>Jb</opr>
+ </def>
+ <def>
+ <pfx>oso</pfx>
+ <opc>0f 88</opc>
+ <opr>Jz</opr>
+ <mode>def64 depM</mode>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>jns</mnemonic>
+ <def>
+ <opc>79</opc>
+ <opr>Jb</opr>
+ </def>
+ <def>
+ <pfx>oso</pfx>
+ <opc>0f 89</opc>
+ <opr>Jz</opr>
+ <mode>def64 depM</mode>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>jp</mnemonic>
+ <def>
+ <opc>7a</opc>
+ <opr>Jb</opr>
+ </def>
+ <def>
+ <pfx>oso</pfx>
+ <opc>0f 8a</opc>
+ <opr>Jz</opr>
+ <mode>def64 depM</mode>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>jnp</mnemonic>
+ <def>
+ <opc>7b</opc>
+ <opr>Jb</opr>
+ </def>
+ <def>
+ <pfx>oso</pfx>
+ <opc>0f 8b</opc>
+ <opr>Jz</opr>
+ <mode>def64 depM</mode>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>jl</mnemonic>
+ <def>
+ <opc>7c</opc>
+ <opr>Jb</opr>
+ </def>
+ <def>
+ <pfx>oso</pfx>
+ <opc>0f 8c</opc>
+ <opr>Jz</opr>
+ <mode>def64 depM</mode>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>jge</mnemonic>
+ <def>
+ <opc>7d</opc>
+ <opr>Jb</opr>
+ </def>
+ <def>
+ <pfx>oso</pfx>
+ <opc>0f 8d</opc>
+ <opr>Jz</opr>
+ <mode>def64 depM</mode>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>jle</mnemonic>
+ <def>
+ <opc>7e</opc>
+ <opr>Jb</opr>
+ </def>
+ <def>
+ <pfx>oso</pfx>
+ <opc>0f 8e</opc>
+ <opr>Jz</opr>
+ <mode>def64 depM</mode>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>jg</mnemonic>
+ <def>
+ <opc>7f</opc>
+ <opr>Jb</opr>
+ </def>
+ <def>
+ <pfx>oso</pfx>
+ <opc>0f 8f</opc>
+ <opr>Jz</opr>
+ <mode>def64 depM</mode>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>jcxz</mnemonic>
+ <def>
+ <pfx>aso</pfx>
+ <opc>e3 /a=16</opc>
+ <opr>Jb</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>jecxz</mnemonic>
+ <def>
+ <pfx>aso</pfx>
+ <opc>e3 /a=32</opc>
+ <opr>Jb</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>jrcxz</mnemonic>
+ <def>
+ <pfx>aso</pfx>
+ <opc>e3 /a=64</opc>
+ <opr>Jb</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>jmp</mnemonic>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>ff /reg=4</opc>
+ <opr>Ev</opr>
+ <mode>def64 depM</mode>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>ff /reg=5</opc>
+ <opr>Ep</opr>
+ </def>
+ <def>
+ <pfx>oso</pfx>
+ <opc>e9</opc>
+ <opr>Jz</opr>
+ <mode>def64 depM</mode>
+ <syn>cast</syn>
+ </def>
+ <def>
+ <opc>ea</opc>
+ <opr>Ap</opr>
+ <mode>inv64</mode>
+ </def>
+ <def>
+ <opc>eb</opc>
+ <opr>Jb</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>lahf</mnemonic>
+ <def>
+ <opc>9f</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>lar</mnemonic>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>0f 02</opc>
+ <opr>Gv Ew</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>lddqu</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>ssef2 0f f0</opc>
+ <opr>V M</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>ldmxcsr</mnemonic>
+ <def>
+ <pfx>aso rexw rexr rexx rexb</pfx>
+ <opc>0f ae /reg=2 /mod=11</opc>
+ <opr>Md</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>lds</mnemonic>
+ <def>
+ <pfx>aso oso</pfx>
+ <opc>c5</opc>
+ <opr>Gv M</opr>
+ <mode>inv64</mode>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>lea</mnemonic>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>8d</opc>
+ <opr>Gv M</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>les</mnemonic>
+ <def>
+ <pfx>aso oso</pfx>
+ <opc>c4</opc>
+ <opr>Gv M</opr>
+ <mode>inv64</mode>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>lfs</mnemonic>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>0f b4</opc>
+ <opr>Gz M</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>lgs</mnemonic>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>0f b5</opc>
+ <opr>Gz M</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>lidt</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 01 /reg=3 /mod=!11</opc>
+ <opr>M</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>lss</mnemonic>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>0f b2</opc>
+ <opr>Gz M</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>leave</mnemonic>
+ <def>
+ <opc>c9</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>lfence</mnemonic>
+ <def>
+ <opc>0f ae /reg=5 /mod=11 /rm=0</opc>
+ </def>
+ <def>
+ <opc>0f ae /reg=5 /mod=11 /rm=1</opc>
+ </def>
+ <def>
+ <opc>0f ae /reg=5 /mod=11 /rm=2</opc>
+ </def>
+ <def>
+ <opc>0f ae /reg=5 /mod=11 /rm=3</opc>
+ </def>
+ <def>
+ <opc>0f ae /reg=5 /mod=11 /rm=4</opc>
+ </def>
+ <def>
+ <opc>0f ae /reg=5 /mod=11 /rm=5</opc>
+ </def>
+ <def>
+ <opc>0f ae /reg=5 /mod=11 /rm=6</opc>
+ </def>
+ <def>
+ <opc>0f ae /reg=5 /mod=11 /rm=7</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>lgdt</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 01 /reg=2 /mod=!11</opc>
+ <opr>M</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>lldt</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 00 /reg=2</opc>
+ <opr>Ew</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>lmsw</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 01 /reg=6 /mod=!11</opc>
+ <opr>Ew</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>lock</mnemonic>
+ <def>
+ <opc>f0</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>lodsb</mnemonic>
+ <def>
+ <pfx>seg</pfx>
+ <opc>ac</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>lodsw</mnemonic>
+ <def>
+ <pfx>seg oso rexw</pfx>
+ <opc>ad /o=16</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>lodsd</mnemonic>
+ <def>
+ <pfx>seg oso rexw</pfx>
+ <opc>ad /o=32</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>lodsq</mnemonic>
+ <def>
+ <pfx>seg oso rexw</pfx>
+ <opc>ad /o=64</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>loopnz</mnemonic>
+ <def>
+ <opc>e0</opc>
+ <opr>Jb</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>loope</mnemonic>
+ <def>
+ <opc>e1</opc>
+ <opr>Jb</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>loop</mnemonic>
+ <def>
+ <opc>e2</opc>
+ <opr>Jb</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>lsl</mnemonic>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>0f 03</opc>
+ <opr>Gv Ew</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>ltr</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 00 /reg=3</opc>
+ <opr>Ew</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>maskmovq</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f f7</opc>
+ <opr>P PR</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>maxpd</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 5f</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>maxps</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 5f</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>maxsd</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>ssef2 0f 5f</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>maxss</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>ssef3 0f 5f</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>mfence</mnemonic>
+ <def>
+ <opc>0f ae /reg=6 /mod=11 /rm=0</opc>
+ </def>
+ <def>
+ <opc>0f ae /reg=6 /mod=11 /rm=1</opc>
+ </def>
+ <def>
+ <opc>0f ae /reg=6 /mod=11 /rm=2</opc>
+ </def>
+ <def>
+ <opc>0f ae /reg=6 /mod=11 /rm=3</opc>
+ </def>
+ <def>
+ <opc>0f ae /reg=6 /mod=11 /rm=4</opc>
+ </def>
+ <def>
+ <opc>0f ae /reg=6 /mod=11 /rm=5</opc>
+ </def>
+ <def>
+ <opc>0f ae /reg=6 /mod=11 /rm=6</opc>
+ </def>
+ <def>
+ <opc>0f ae /reg=6 /mod=11 /rm=7</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>minpd</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 5d</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>minps</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 5d</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>minsd</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>ssef2 0f 5d</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>minss</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>ssef3 0f 5d</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>monitor</mnemonic>
+ <def>
+ <opc>0f 01 /reg=1 /mod=11 /rm=0</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>montmul</mnemonic>
+ <def>
+ <opc>0f a6 /mod=11 /rm=0 /reg=0</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>mov</mnemonic>
+ <def>
+ <pfx>aso rexw rexr rexx rexb</pfx>
+ <opc>c6 /reg=0</opc>
+ <opr>Eb Ib</opr>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>c7 /reg=0</opc>
+ <opr>Ev Iz</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>88</opc>
+ <opr>Eb Gb</opr>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>89</opc>
+ <opr>Ev Gv</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>8a</opc>
+ <opr>Gb Eb</opr>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>8b</opc>
+ <opr>Gv Ev</opr>
+ </def>
+ <def>
+ <pfx>aso oso rexr rexx rexb</pfx>
+ <opc>8c</opc>
+ <opr>Ev S</opr>
+ </def>
+ <def>
+ <pfx>aso oso rexr rexx rexb</pfx>
+ <opc>8e</opc>
+ <opr>S Ev</opr>
+ </def>
+ <def>
+ <opc>a0</opc>
+ <opr>AL Ob</opr>
+ </def>
+ <def>
+ <pfx>aso oso rexw</pfx>
+ <opc>a1</opc>
+ <opr>rAX Ov</opr>
+ </def>
+ <def>
+ <opc>a2</opc>
+ <opr>Ob AL</opr>
+ </def>
+ <def>
+ <pfx>aso oso rexw</pfx>
+ <opc>a3</opc>
+ <opr>Ov rAX</opr>
+ </def>
+ <def>
+ <pfx>rexb</pfx>
+ <opc>b0</opc>
+ <opr>ALr8b Ib</opr>
+ </def>
+ <def>
+ <pfx>rexb</pfx>
+ <opc>b1</opc>
+ <opr>CLr9b Ib</opr>
+ </def>
+ <def>
+ <pfx>rexb</pfx>
+ <opc>b2</opc>
+ <opr>DLr10b Ib</opr>
+ </def>
+ <def>
+ <pfx>rexb</pfx>
+ <opc>b3</opc>
+ <opr>BLr11b Ib</opr>
+ </def>
+ <def>
+ <pfx>rexb</pfx>
+ <opc>b4</opc>
+ <opr>AHr12b Ib</opr>
+ </def>
+ <def>
+ <pfx>rexb</pfx>
+ <opc>b5</opc>
+ <opr>CHr13b Ib</opr>
+ </def>
+ <def>
+ <pfx>rexb</pfx>
+ <opc>b6</opc>
+ <opr>DHr14b Ib</opr>
+ </def>
+ <def>
+ <pfx>rexb</pfx>
+ <opc>b7</opc>
+ <opr>BHr15b Ib</opr>
+ </def>
+ <def>
+ <pfx>oso rexw rexb</pfx>
+ <opc>b8</opc>
+ <opr>rAXr8 Iv</opr>
+ </def>
+ <def>
+ <pfx>oso rexw rexb</pfx>
+ <opc>b9</opc>
+ <opr>rCXr9 Iv</opr>
+ </def>
+ <def>
+ <pfx>oso rexw rexb</pfx>
+ <opc>ba</opc>
+ <opr>rDXr10 Iv</opr>
+ </def>
+ <def>
+ <pfx>oso rexw rexb</pfx>
+ <opc>bb</opc>
+ <opr>rBXr11 Iv</opr>
+ </def>
+ <def>
+ <pfx>oso rexw rexb</pfx>
+ <opc>bc</opc>
+ <opr>rSPr12 Iv</opr>
+ </def>
+ <def>
+ <pfx>oso rexw rexb</pfx>
+ <opc>bd</opc>
+ <opr>rBPr13 Iv</opr>
+ </def>
+ <def>
+ <pfx>oso rexw rexb</pfx>
+ <opc>be</opc>
+ <opr>rSIr14 Iv</opr>
+ </def>
+ <def>
+ <pfx>oso rexw rexb</pfx>
+ <opc>bf</opc>
+ <opr>rDIr15 Iv</opr>
+ </def>
+ <def>
+ <pfx>rexr</pfx>
+ <opc>0f 20</opc>
+ <opr>R C</opr>
+ </def>
+ <def>
+ <pfx>rexr</pfx>
+ <opc>0f 21</opc>
+ <opr>R D</opr>
+ </def>
+ <def>
+ <pfx>rexr</pfx>
+ <opc>0f 22</opc>
+ <opr>C R</opr>
+ </def>
+ <def>
+ <pfx>rexr</pfx>
+ <opc>0f 23</opc>
+ <opr>D R</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>movapd</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 28</opc>
+ <opr>V W</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 29</opc>
+ <opr>W V</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>movaps</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 28</opc>
+ <opr>V W</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 29</opc>
+ <opr>W V</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>movd</mnemonic>
+ <def>
+ <pfx>aso rexw rexr rexx rexb</pfx>
+ <opc>sse66 0f 6e</opc>
+ <opr>V Ex</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 6e</opc>
+ <opr>P Ex</opr>
+ </def>
+ <def>
+ <pfx>aso rexw rexr rexx rexb</pfx>
+ <opc>sse66 0f 7e</opc>
+ <opr>Ex V</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 7e</opc>
+ <opr>Ex P</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>movhpd</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 16 /mod=!11</opc>
+ <opr>V M</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 17</opc>
+ <opr>M V</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>movhps</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 16 /mod=!11</opc>
+ <opr>V M</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 17</opc>
+ <opr>M V</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>movlhps</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 16 /mod=11</opc>
+ <opr>V VR</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>movlpd</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 12 /mod=!11</opc>
+ <opr>V M</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 13</opc>
+ <opr>M V</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>movlps</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 12 /mod=!11</opc>
+ <opr>V M</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 13</opc>
+ <opr>M V</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>movhlps</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 12 /mod=11</opc>
+ <opr>V VR</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>movmskpd</mnemonic>
+ <def>
+ <pfx>oso rexr rexb</pfx>
+ <opc>sse66 0f 50</opc>
+ <opr>Gd VR</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>movmskps</mnemonic>
+ <def>
+ <pfx>oso rexr rexb</pfx>
+ <opc>0f 50</opc>
+ <opr>Gd VR</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>movntdq</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f e7</opc>
+ <opr>M V</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>movnti</mnemonic>
+ <def>
+ <pfx>aso rexw rexr rexx rexb</pfx>
+ <opc>0f c3</opc>
+ <opr>M Gy</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>movntpd</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 2b</opc>
+ <opr>M V</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>movntps</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 2b</opc>
+ <opr>M V</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>movntq</mnemonic>
+ <def>
+ <opc>0f e7</opc>
+ <opr>M P</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>movq</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 6f</opc>
+ <opr>P Q</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f d6</opc>
+ <opr>W V</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>ssef3 0f 7e</opc>
+ <opr>V W</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 7f</opc>
+ <opr>Q P</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>movsb</mnemonic>
+ <def>
+ <pfx>seg</pfx>
+ <opc>a4</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>movsw</mnemonic>
+ <def>
+ <pfx>seg oso rexw</pfx>
+ <opc>a5 /o=16</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>movsd</mnemonic>
+ <def>
+ <pfx>seg oso rexw</pfx>
+ <opc>a5 /o=32</opc>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>ssef2 0f 10</opc>
+ <opr>V W</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>ssef2 0f 11</opc>
+ <opr>W V</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>movsq</mnemonic>
+ <def>
+ <pfx>seg oso rexw</pfx>
+ <opc>a5 /o=64</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>movss</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>ssef3 0f 10</opc>
+ <opr>V W</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>ssef3 0f 11</opc>
+ <opr>W V</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>movsx</mnemonic>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>0f be</opc>
+ <opr>Gv Eb</opr>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>0f bf</opc>
+ <opr>Gv Ew</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>movupd</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 10</opc>
+ <opr>V W</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 11</opc>
+ <opr>W V</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>movups</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 10</opc>
+ <opr>V W</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 11</opc>
+ <opr>W V</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>movzx</mnemonic>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>0f b6</opc>
+ <opr>Gv Eb</opr>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>0f b7</opc>
+ <opr>Gv Ew</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>mul</mnemonic>
+ <def>
+ <pfx>aso rexw rexr rexx rexb</pfx>
+ <opc>f6 /reg=4</opc>
+ <opr>Eb</opr>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>f7 /reg=4</opc>
+ <opr>Ev</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>mulpd</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 59</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>mulps</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 59</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>mulsd</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>ssef2 0f 59</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>mulss</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>ssef3 0f 59</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>mwait</mnemonic>
+ <def>
+ <opc>0f 01 /reg=1 /mod=11 /rm=1</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>neg</mnemonic>
+ <def>
+ <pfx>aso rexw rexr rexx rexb</pfx>
+ <opc>f6 /reg=3</opc>
+ <opr>Eb</opr>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>f7 /reg=3</opc>
+ <opr>Ev</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>nop</mnemonic>
+ <def>
+ <opc>90</opc>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 19</opc>
+ <opr>M</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 1a</opc>
+ <opr>M</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 1b</opc>
+ <opr>M</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 1c</opc>
+ <opr>M</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 1d</opc>
+ <opr>M</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 1e</opc>
+ <opr>M</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 1f</opc>
+ <opr>M</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>not</mnemonic>
+ <def>
+ <pfx>aso rexw rexr rexx rexb</pfx>
+ <opc>f6 /reg=2</opc>
+ <opr>Eb</opr>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>f7 /reg=2</opc>
+ <opr>Ev</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>or</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>08</opc>
+ <opr>Eb Gb</opr>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>09</opc>
+ <opr>Ev Gv</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0a</opc>
+ <opr>Gb Eb</opr>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>0b</opc>
+ <opr>Gv Ev</opr>
+ </def>
+ <def>
+ <opc>0c</opc>
+ <opr>AL Ib</opr>
+ </def>
+ <def>
+ <pfx>oso rexw</pfx>
+ <opc>0d</opc>
+ <opr>rAX Iz</opr>
+ <syn>sext</syn>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>80 /reg=1</opc>
+ <opr>Eb Ib</opr>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>81 /reg=1</opc>
+ <opr>Ev Iz</opr>
+ <syn>sext</syn>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>82 /reg=1</opc>
+ <opr>Eb Ib</opr>
+ <mode>inv64</mode>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>83 /reg=1</opc>
+ <opr>Ev Ib</opr>
+ <syn>sext</syn>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>orpd</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 56</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>orps</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 56</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>out</mnemonic>
+ <def>
+ <opc>e6</opc>
+ <opr>Ib AL</opr>
+ </def>
+ <def>
+ <pfx>oso</pfx>
+ <opc>e7</opc>
+ <opr>Ib eAX</opr>
+ </def>
+ <def>
+ <opc>ee</opc>
+ <opr>DX AL</opr>
+ </def>
+ <def>
+ <pfx>oso</pfx>
+ <opc>ef</opc>
+ <opr>DX eAX</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>outsb</mnemonic>
+ <def>
+ <opc>6e</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>outsw</mnemonic>
+ <def>
+ <pfx>oso</pfx>
+ <opc>6f /o=16</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>outsd</mnemonic>
+ <def>
+ <pfx>oso</pfx>
+ <opc>6f /o=32</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>outsq</mnemonic>
+ <def>
+ <pfx>oso</pfx>
+ <opc>6f /o=64</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>packsswb</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 63</opc>
+ <opr>V W</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 63</opc>
+ <opr>P Q</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>packssdw</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 6b</opc>
+ <opr>V W</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 6b</opc>
+ <opr>P Q</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>packuswb</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 67</opc>
+ <opr>V W</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 67</opc>
+ <opr>P Q</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>paddb</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f fc</opc>
+ <opr>V W</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f fc</opc>
+ <opr>P Q</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>paddw</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f fd</opc>
+ <opr>P Q</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f fd</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>paddd</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f fe</opc>
+ <opr>P Q</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f fe</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+
+ <instruction>
+ <mnemonic>paddsb</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f ec</opc>
+ <opr>P Q</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f ec</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>paddsw</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f ed</opc>
+ <opr>P Q</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f ed</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>paddusb</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f dc</opc>
+ <opr>P Q</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f dc</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>paddusw</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f dd</opc>
+ <opr>P Q</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f dd</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pand</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f db</opc>
+ <opr>V W</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f db</opc>
+ <opr>P Q</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pandn</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f df</opc>
+ <opr>V W</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f df</opc>
+ <opr>P Q</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pavgb</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f e0</opc>
+ <opr>V W</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f e0</opc>
+ <opr>P Q</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pavgw</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f e3</opc>
+ <opr>V W</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f e3</opc>
+ <opr>P Q</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pcmpeqb</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 74</opc>
+ <opr>P Q</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 74</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pcmpeqw</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 75</opc>
+ <opr>P Q</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 75</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pcmpeqd</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 76</opc>
+ <opr>P Q</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 76</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pcmpgtb</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 64</opc>
+ <opr>V W</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 64</opc>
+ <opr>P Q</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pcmpgtw</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 65</opc>
+ <opr>V W</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 65</opc>
+ <opr>P Q</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pcmpgtd</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 66</opc>
+ <opr>V W</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 66</opc>
+ <opr>P Q</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pextrb</mnemonic>
+ <def>
+ <pfx>aso rexr rexb</pfx>
+ <opc>sse66 0f 3a 14</opc>
+ <opr>MbRv V Ib</opr>
+ <mode>def64</mode>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pextrd</mnemonic>
+ <def>
+ <pfx>aso rexr rexw rexb</pfx>
+ <opc>sse66 0f 3a 16 /o=16</opc>
+ <opr>Ev V Ib</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexw rexb</pfx>
+ <opc>sse66 0f 3a 16 /o=32</opc>
+ <opr>Ev V Ib</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pextrq</mnemonic>
+ <def>
+ <pfx>aso rexr rexw rexb</pfx>
+ <opc>sse66 0f 3a 16 /o=64</opc>
+ <opr>Ev V Ib</opr>
+ <mode>def64</mode>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pextrw</mnemonic>
+ <def>
+ <pfx>aso rexr rexb</pfx>
+ <opc>sse66 0f c5</opc>
+ <opr>Gd VR Ib</opr>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>0f c5</opc>
+ <opr>Gd PR Ib</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pinsrw</mnemonic>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>0f c4</opc>
+ <opr>P Ew Ib</opr>
+ </def>
+ <def>
+ <pfx>aso rexw rexr rexx rexb</pfx>
+ <opc>sse66 0f c4</opc>
+ <opr>V Ew Ib</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pmaddwd</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f f5</opc>
+ <opr>P Q</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f f5</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pmaxsw</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f ee</opc>
+ <opr>V W</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f ee</opc>
+ <opr>P Q</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pmaxub</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f de</opc>
+ <opr>P Q</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f de</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pminsw</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f ea</opc>
+ <opr>V W</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f ea</opc>
+ <opr>P Q</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pminub</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f da</opc>
+ <opr>V W</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f da</opc>
+ <opr>P Q</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pmovmskb</mnemonic>
+ <def>
+ <pfx>rexr rexb</pfx>
+ <opc>sse66 0f d7</opc>
+ <opr>Gd VR</opr>
+ </def>
+ <def>
+ <pfx>oso rexr rexb</pfx>
+ <opc>0f d7</opc>
+ <opr>Gd PR</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pmulhuw</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f e4</opc>
+ <opr>P Q</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f e4</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pmulhw</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f e5</opc>
+ <opr>V W</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f e5</opc>
+ <opr>P Q</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pmullw</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f d5</opc>
+ <opr>P Q</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f d5</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pop</mnemonic>
+ <def>
+ <opc>07</opc>
+ <opr>ES</opr>
+ <mode>inv64</mode>
+ </def>
+ <def>
+ <opc>17</opc>
+ <opr>SS</opr>
+ <mode>inv64</mode>
+ </def>
+ <def>
+ <opc>1f</opc>
+ <opr>DS</opr>
+ <mode>inv64</mode>
+ </def>
+ <def>
+ <opc>0f a9</opc>
+ <opr>GS</opr>
+ </def>
+ <def>
+ <opc>0f a1</opc>
+ <opr>FS</opr>
+ </def>
+ <def>
+ <pfx>oso rexb</pfx>
+ <opc>58</opc>
+ <opr>rAXr8</opr>
+ <mode>def64 depM</mode>
+ </def>
+ <def>
+ <pfx>oso rexb</pfx>
+ <opc>59</opc>
+ <opr>rCXr9</opr>
+ <mode>def64 depM</mode>
+ </def>
+ <def>
+ <pfx>oso rexb</pfx>
+ <opc>5a</opc>
+ <opr>rDXr10</opr>
+ <mode>def64 depM</mode>
+ </def>
+ <def>
+ <pfx>oso rexb</pfx>
+ <opc>5b</opc>
+ <opr>rBXr11</opr>
+ <mode>def64 depM</mode>
+ </def>
+ <def>
+ <pfx>oso rexb</pfx>
+ <opc>5c</opc>
+ <opr>rSPr12</opr>
+ <mode>def64 depM</mode>
+ </def>
+ <def>
+ <pfx>oso rexb</pfx>
+ <opc>5d</opc>
+ <opr>rBPr13</opr>
+ <mode>def64 depM</mode>
+ </def>
+ <def>
+ <pfx>oso rexb</pfx>
+ <opc>5e</opc>
+ <opr>rSIr14</opr>
+ <mode>def64 depM</mode>
+ </def>
+ <def>
+ <pfx>oso rexb</pfx>
+ <opc>5f</opc>
+ <opr>rDIr15</opr>
+ <mode>def64 depM</mode>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>8f /reg=0</opc>
+ <opr>Ev</opr>
+ <mode>def64 depM</mode>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>popa</mnemonic>
+ <def>
+ <pfx>oso</pfx>
+ <opc>61 /o=16</opc>
+ <mode>inv64</mode>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>popad</mnemonic>
+ <def>
+ <pfx>oso</pfx>
+ <opc>61 /o=32</opc>
+ <mode>inv64</mode>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>popfw</mnemonic>
+ <def>
+ <pfx>oso</pfx>
+ <opc>9d /m=32 /o=16</opc>
+ <mode>def64 depM</mode>
+ </def>
+ <def>
+ <pfx>oso</pfx>
+ <opc>9d /m=16 /o=16</opc>
+ <mode>def64 depM</mode>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>popfd</mnemonic>
+ <def>
+ <pfx>oso</pfx>
+ <opc>9d /m=16 /o=32</opc>
+ <mode>def64 depM</mode>
+ </def>
+ <def>
+ <pfx>oso</pfx>
+ <opc>9d /m=32 /o=32</opc>
+ <mode>def64 depM</mode>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>popfq</mnemonic>
+ <def>
+ <pfx>oso</pfx>
+ <opc>9d /m=64 /o=64</opc>
+ <mode>def64 depM</mode>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>por</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f eb</opc>
+ <opr>V W</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f eb</opc>
+ <opr>P Q</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>prefetch</mnemonic>
+ <def>
+ <pfx>aso rexw rexr rexx rexb</pfx>
+ <opc>0f 0d /reg=0</opc>
+ <opr>M</opr>
+ </def>
+ <def>
+ <pfx>aso rexw rexr rexx rexb</pfx>
+ <opc>0f 0d /reg=1</opc>
+ <opr>M</opr>
+ </def>
+ <def>
+ <pfx>aso rexw rexr rexx rexb</pfx>
+ <opc>0f 0d /reg=2</opc>
+ <opr>M</opr>
+ </def>
+ <def>
+ <pfx>aso rexw rexr rexx rexb</pfx>
+ <opc>0f 0d /reg=3</opc>
+ <opr>M</opr>
+ </def>
+ <def>
+ <pfx>aso rexw rexr rexx rexb</pfx>
+ <opc>0f 0d /reg=4</opc>
+ <opr>M</opr>
+ </def>
+ <def>
+ <pfx>aso rexw rexr rexx rexb</pfx>
+ <opc>0f 0d /reg=5</opc>
+ <opr>M</opr>
+ </def>
+ <def>
+ <pfx>aso rexw rexr rexx rexb</pfx>
+ <opc>0f 0d /reg=6</opc>
+ <opr>M</opr>
+ </def>
+ <def>
+ <pfx>aso rexw rexr rexx rexb</pfx>
+ <opc>0f 0d /reg=7</opc>
+ <opr>M</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>prefetchnta</mnemonic>
+ <def>
+ <pfx>aso rexw rexr rexx rexb</pfx>
+ <opc>0f 18 /reg=0</opc>
+ <opr>M</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>prefetcht0</mnemonic>
+ <def>
+ <pfx>aso rexw rexr rexx rexb</pfx>
+ <opc>0f 18 /reg=1</opc>
+ <opr>M</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>prefetcht1</mnemonic>
+ <def>
+ <pfx>aso rexw rexr rexx rexb</pfx>
+ <opc>0f 18 /reg=2</opc>
+ <opr>M</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>prefetcht2</mnemonic>
+ <def>
+ <pfx>aso rexw rexr rexx rexb</pfx>
+ <opc>0f 18 /reg=3</opc>
+ <opr>M</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>psadbw</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f f6</opc>
+ <opr>V W</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f f6</opc>
+ <opr>P Q</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pshufw</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 70</opc>
+ <opr>P Q Ib</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>psllw</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f f1</opc>
+ <opr>V W</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f f1</opc>
+ <opr>P Q</opr>
+ </def>
+ <def>
+ <pfx>rexb</pfx>
+ <opc>sse66 0f 71 /reg=6</opc>
+ <opr>VR Ib</opr>
+ </def>
+ <def>
+ <opc>0f 71 /reg=6</opc>
+ <opr>PR Ib</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pslld</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f f2</opc>
+ <opr>V W</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f f2</opc>
+ <opr>P Q</opr>
+ </def>
+ <def>
+ <pfx>rexb</pfx>
+ <opc>sse66 0f 72 /reg=6</opc>
+ <opr>VR Ib</opr>
+ </def>
+ <def>
+ <opc>0f 72 /reg=6</opc>
+ <opr>PR Ib</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>psllq</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f f3</opc>
+ <opr>V W</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f f3</opc>
+ <opr>P Q</opr>
+ </def>
+ <def>
+ <pfx>rexb</pfx>
+ <opc>sse66 0f 73 /reg=6</opc>
+ <opr>VR Ib</opr>
+ </def>
+ <def>
+ <opc>0f 73 /reg=6</opc>
+ <opr>PR Ib</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>psraw</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f e1</opc>
+ <opr>P Q</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f e1</opc>
+ <opr>V W</opr>
+ </def>
+ <def>
+ <pfx>rexb</pfx>
+ <opc>sse66 0f 71 /reg=4</opc>
+ <opr>VR Ib</opr>
+ </def>
+ <def>
+ <opc>0f 71 /reg=4</opc>
+ <opr>PR Ib</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>psrad</mnemonic>
+ <def>
+ <opc>0f 72 /reg=4</opc>
+ <opr>PR Ib</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f e2</opc>
+ <opr>V W</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f e2</opc>
+ <opr>P Q</opr>
+ </def>
+ <def>
+ <pfx>rexb</pfx>
+ <opc>sse66 0f 72 /reg=4</opc>
+ <opr>VR Ib</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>psrlw</mnemonic>
+ <def>
+ <opc>0f 71 /reg=2</opc>
+ <opr>PR Ib</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f d1</opc>
+ <opr>P Q</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f d1</opc>
+ <opr>V W</opr>
+ </def>
+ <def>
+ <pfx>rexb</pfx>
+ <opc>sse66 0f 71 /reg=2</opc>
+ <opr>VR Ib</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>psrld</mnemonic>
+ <def>
+ <opc>0f 72 /reg=2</opc>
+ <opr>PR Ib</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f d2</opc>
+ <opr>P Q</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f d2</opc>
+ <opr>V W</opr>
+ </def>
+ <def>
+ <pfx>rexb</pfx>
+ <opc>sse66 0f 72 /reg=2</opc>
+ <opr>VR Ib</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>psrlq</mnemonic>
+ <def>
+ <opc>0f 73 /reg=2</opc>
+ <opr>PR Ib</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f d3</opc>
+ <opr>P Q</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f d3</opc>
+ <opr>V W</opr>
+ </def>
+ <def>
+ <pfx>rexb</pfx>
+ <opc>sse66 0f 73 /reg=2</opc>
+ <opr>VR Ib</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>psubb</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f f8</opc>
+ <opr>V W</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f f8</opc>
+ <opr>P Q</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>psubw</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f f9</opc>
+ <opr>V W</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f f9</opc>
+ <opr>P Q</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>psubd</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f fa</opc>
+ <opr>P Q</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f fa</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>psubsb</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f e8</opc>
+ <opr>P Q</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f e8</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>psubsw</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f e9</opc>
+ <opr>P Q</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f e9</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>psubusb</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f d8</opc>
+ <opr>P Q</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f d8</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>psubusw</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f d9</opc>
+ <opr>P Q</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f d9</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>punpckhbw</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 68</opc>
+ <opr>V W</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 68</opc>
+ <opr>P Q</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>punpckhwd</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 69</opc>
+ <opr>V W</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 69</opc>
+ <opr>P Q</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>punpckhdq</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 6a</opc>
+ <opr>V W</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 6a</opc>
+ <opr>P Q</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>punpcklbw</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 60</opc>
+ <opr>V W</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 60</opc>
+ <opr>P Q</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>punpcklwd</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 61</opc>
+ <opr>V W</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 61</opc>
+ <opr>P Q</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>punpckldq</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 62</opc>
+ <opr>V W</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 62</opc>
+ <opr>P Q</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pi2fw</mnemonic>
+ <def>
+ <opc>0f 0f /3dnow=0c</opc>
+ <opr>P Q</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pi2fd</mnemonic>
+ <def>
+ <opc>0f 0f /3dnow=0d</opc>
+ <opr>P Q</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pf2iw</mnemonic>
+ <def>
+ <opc>0f 0f /3dnow=1c</opc>
+ <opr>P Q</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pf2id</mnemonic>
+ <def>
+ <opc>0f 0f /3dnow=1d</opc>
+ <opr>P Q</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pfnacc</mnemonic>
+ <def>
+ <opc>0f 0f /3dnow=8a</opc>
+ <opr>P Q</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pfpnacc</mnemonic>
+ <def>
+ <opc>0f 0f /3dnow=8e</opc>
+ <opr>P Q</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pfcmpge</mnemonic>
+ <def>
+ <opc>0f 0f /3dnow=90</opc>
+ <opr>P Q</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pfmin</mnemonic>
+ <def>
+ <opc>0f 0f /3dnow=94</opc>
+ <opr>P Q</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pfrcp</mnemonic>
+ <def>
+ <opc>0f 0f /3dnow=96</opc>
+ <opr>P Q</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pfrsqrt</mnemonic>
+ <def>
+ <opc>0f 0f /3dnow=97</opc>
+ <opr>P Q</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pfsub</mnemonic>
+ <def>
+ <opc>0f 0f /3dnow=9a</opc>
+ <opr>P Q</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pfadd</mnemonic>
+ <def>
+ <opc>0f 0f /3dnow=9e</opc>
+ <opr>P Q</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pfcmpgt</mnemonic>
+ <def>
+ <opc>0f 0f /3dnow=a0</opc>
+ <opr>P Q</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pfmax</mnemonic>
+ <def>
+ <opc>0f 0f /3dnow=a4</opc>
+ <opr>P Q</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pfrcpit1</mnemonic>
+ <def>
+ <opc>0f 0f /3dnow=a6</opc>
+ <opr>P Q</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pfrsqit1</mnemonic>
+ <def>
+ <opc>0f 0f /3dnow=a7</opc>
+ <opr>P Q</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pfsubr</mnemonic>
+ <def>
+ <opc>0f 0f /3dnow=aa</opc>
+ <opr>P Q</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pfacc</mnemonic>
+ <def>
+ <opc>0f 0f /3dnow=ae</opc>
+ <opr>P Q</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pfcmpeq</mnemonic>
+ <def>
+ <opc>0f 0f /3dnow=b0</opc>
+ <opr>P Q</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pfmul</mnemonic>
+ <def>
+ <opc>0f 0f /3dnow=b4</opc>
+ <opr>P Q</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pfrcpit2</mnemonic>
+ <def>
+ <opc>0f 0f /3dnow=b6</opc>
+ <opr>P Q</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pmulhrw</mnemonic>
+ <def>
+ <opc>0f 0f /3dnow=b7</opc>
+ <opr>P Q</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pswapd</mnemonic>
+ <def>
+ <opc>0f 0f /3dnow=bb</opc>
+ <opr>P Q</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pavgusb</mnemonic>
+ <def>
+ <opc>0f 0f /3dnow=bf</opc>
+ <opr>P Q</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>push</mnemonic>
+ <def>
+ <opc>06</opc>
+ <opr>ES</opr>
+ <mode>inv64</mode>
+ </def>
+ <def>
+ <opc>0e</opc>
+ <opr>CS</opr>
+ <mode>inv64</mode>
+ </def>
+ <def>
+ <opc>16</opc>
+ <opr>SS</opr>
+ <mode>inv64</mode>
+ </def>
+ <def>
+ <opc>1e</opc>
+ <opr>DS</opr>
+ <mode>inv64</mode>
+ </def>
+ <def>
+ <opc>0f a8</opc>
+ <opr>GS</opr>
+ </def>
+ <def>
+ <opc>0f a0</opc>
+ <opr>FS</opr>
+ </def>
+ <def>
+ <pfx>oso rexb</pfx>
+ <opc>50</opc>
+ <opr>rAXr8</opr>
+ <mode>def64 depM</mode>
+ </def>
+ <def>
+ <pfx>oso rexb</pfx>
+ <opc>51</opc>
+ <opr>rCXr9</opr>
+ <mode>def64 depM</mode>
+ </def>
+ <def>
+ <pfx>oso rexb</pfx>
+ <opc>52</opc>
+ <opr>rDXr10</opr>
+ <mode>def64 depM</mode>
+ </def>
+ <def>
+ <pfx>oso rexb</pfx>
+ <opc>53</opc>
+ <opr>rBXr11</opr>
+ <mode>def64 depM</mode>
+ </def>
+ <def>
+ <pfx>oso rexb</pfx>
+ <opc>54</opc>
+ <opr>rSPr12</opr>
+ <mode>def64 depM</mode>
+ </def>
+ <def>
+ <pfx>oso rexb</pfx>
+ <opc>55</opc>
+ <opr>rBPr13</opr>
+ <mode>def64 depM</mode>
+ </def>
+ <def>
+ <pfx>oso rexb</pfx>
+ <opc>56</opc>
+ <opr>rSIr14</opr>
+ <mode>def64 depM</mode>
+ </def>
+ <def>
+ <pfx>oso rexb</pfx>
+ <opc>57</opc>
+ <opr>rDIr15</opr>
+ <mode>def64 depM</mode>
+ </def>
+ <def>
+ <pfx>oso</pfx>
+ <opc>68</opc>
+ <opr>Iz</opr>
+ <syn>cast</syn>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>ff /reg=6</opc>
+ <opr>Ev</opr>
+ <mode>def64</mode>
+ </def>
+ <def>
+ <opc>6a</opc>
+ <opr>Ib</opr>
+ <syn>sext</syn>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pusha</mnemonic>
+ <def>
+ <pfx>oso</pfx>
+ <opc>60 /o=16</opc>
+ <mode>inv64</mode>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pushad</mnemonic>
+ <def>
+ <pfx>oso</pfx>
+ <opc>60 /o=32</opc>
+ <mode>inv64</mode>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pushfw</mnemonic>
+ <def>
+ <pfx>oso</pfx>
+ <opc>9c /m=32 /o=16</opc>
+ <mode>def64</mode>
+ </def>
+ <def>
+ <pfx>oso</pfx>
+ <opc>9c /m=16 /o=16</opc>
+ <mode>def64</mode>
+ </def>
+ <def>
+ <pfx>oso rexw</pfx>
+ <opc>9c /m=64 /o=16</opc>
+ <mode>def64</mode>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pushfd</mnemonic>
+ <def>
+ <pfx>oso</pfx>
+ <opc>9c /m=16 /o=32</opc>
+ <mode>def64</mode>
+ </def>
+ <def>
+ <pfx>oso</pfx>
+ <opc>9c /m=32 /o=32</opc>
+ <mode>def64</mode>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pushfq</mnemonic>
+ <def>
+ <pfx>oso rexw</pfx>
+ <opc>9c /m=64 /o=32</opc>
+ <mode>def64</mode>
+ </def>
+ <def>
+ <pfx>oso rexw</pfx>
+ <opc>9c /m=64 /o=64</opc>
+ <mode>def64</mode>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pxor</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f ef</opc>
+ <opr>V W</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f ef</opc>
+ <opr>P Q</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>rcl</mnemonic>
+ <def>
+ <pfx>aso rexw rexr rexx rexb</pfx>
+ <opc>c0 /reg=2</opc>
+ <opr>Eb Ib</opr>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>c1 /reg=2</opc>
+ <opr>Ev Ib</opr>
+ </def>
+ <def>
+ <pfx>aso rexw rexr rexx rexb</pfx>
+ <opc>d0 /reg=2</opc>
+ <opr>Eb I1</opr>
+ </def>
+ <def>
+ <pfx>aso rexw rexr rexx rexb</pfx>
+ <opc>d2 /reg=2</opc>
+ <opr>Eb CL</opr>
+ <syn>cast</syn>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>d3 /reg=2</opc>
+ <opr>Ev CL</opr>
+ <syn>cast</syn>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>d1 /reg=2</opc>
+ <opr>Ev I1</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>rcr</mnemonic>
+ <def>
+ <pfx>aso rexw rexr rexx rexb</pfx>
+ <opc>d0 /reg=3</opc>
+ <opr>Eb I1</opr>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>c1 /reg=3</opc>
+ <opr>Ev Ib</opr>
+ </def>
+ <def>
+ <pfx>aso rexw rexr rexx rexb</pfx>
+ <opc>c0 /reg=3</opc>
+ <opr>Eb Ib</opr>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>d1 /reg=3</opc>
+ <opr>Ev I1</opr>
+ </def>
+ <def>
+ <pfx>aso rexw rexr rexx rexb</pfx>
+ <opc>d2 /reg=3</opc>
+ <opr>Eb CL</opr>
+ <syn>cast</syn>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>d3 /reg=3</opc>
+ <opr>Ev CL</opr>
+ <syn>cast</syn>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>rol</mnemonic>
+ <def>
+ <pfx>aso rexw rexr rexx rexb</pfx>
+ <opc>c0 /reg=0</opc>
+ <opr>Eb Ib</opr>
+ </def>
+ <def>
+ <pfx>aso rexw rexr rexx rexb</pfx>
+ <opc>d0 /reg=0</opc>
+ <opr>Eb I1</opr>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>d1 /reg=0</opc>
+ <opr>Ev I1</opr>
+ </def>
+ <def>
+ <pfx>aso rexw rexr rexx rexb</pfx>
+ <opc>d2 /reg=0</opc>
+ <opr>Eb CL</opr>
+ <syn>cast</syn>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>d3 /reg=0</opc>
+ <opr>Ev CL</opr>
+ <syn>cast</syn>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>c1 /reg=0</opc>
+ <opr>Ev Ib</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>ror</mnemonic>
+ <def>
+ <pfx>aso rexw rexr rexx rexb</pfx>
+ <opc>d0 /reg=1</opc>
+ <opr>Eb I1</opr>
+ </def>
+ <def>
+ <pfx>aso rexw rexr rexx rexb</pfx>
+ <opc>c0 /reg=1</opc>
+ <opr>Eb Ib</opr>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>c1 /reg=1</opc>
+ <opr>Ev Ib</opr>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>d1 /reg=1</opc>
+ <opr>Ev I1</opr>
+ </def>
+ <def>
+ <pfx>aso rexw rexr rexx rexb</pfx>
+ <opc>d2 /reg=1</opc>
+ <opr>Eb CL</opr>
+ <syn>cast</syn>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>d3 /reg=1</opc>
+ <opr>Ev CL</opr>
+ <syn>cast</syn>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>rcpps</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 53</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>rcpss</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>ssef3 0f 53</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>rdmsr</mnemonic>
+ <def>
+ <opc>0f 32</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>rdpmc</mnemonic>
+ <def>
+ <opc>0f 33</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>rdtsc</mnemonic>
+ <def>
+ <opc>0f 31</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>rdtscp</mnemonic>
+ <vendor>amd</vendor>
+ <def>
+ <opc>0f 01 /reg=7 /mod=11 /rm=1</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>repne</mnemonic>
+ <def>
+ <opc>f2</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>rep</mnemonic>
+ <def>
+ <opc>f3</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>ret</mnemonic>
+ <def>
+ <opc>c2</opc>
+ <opr>Iw</opr>
+ </def>
+ <def>
+ <opc>c3</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>retf</mnemonic>
+ <def>
+ <opc>ca</opc>
+ <opr>Iw</opr>
+ </def>
+ <def>
+ <opc>cb</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>rsm</mnemonic>
+ <def>
+ <opc>0f aa</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>rsqrtps</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 52</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>rsqrtss</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>ssef3 0f 52</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>sahf</mnemonic>
+ <def>
+ <opc>9e</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>sal</mnemonic>
+ </instruction>
+
+ <instruction>
+ <mnemonic>salc</mnemonic>
+ <def>
+ <opc>d6</opc>
+ <mode>inv64</mode>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>sar</mnemonic>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>d1 /reg=7</opc>
+ <opr>Ev I1</opr>
+ </def>
+ <def>
+ <pfx>aso rexw rexr rexx rexb</pfx>
+ <opc>c0 /reg=7</opc>
+ <opr>Eb Ib</opr>
+ </def>
+ <def>
+ <pfx>aso rexw rexr rexx rexb</pfx>
+ <opc>d0 /reg=7</opc>
+ <opr>Eb I1</opr>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>c1 /reg=7</opc>
+ <opr>Ev Ib</opr>
+ </def>
+ <def>
+ <pfx>aso rexw rexr rexx rexb</pfx>
+ <opc>d2 /reg=7</opc>
+ <opr>Eb CL</opr>
+ <syn>cast</syn>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>d3 /reg=7</opc>
+ <opr>Ev CL</opr>
+ <syn>cast</syn>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>shl</mnemonic>
+ <def>
+ <pfx>aso rexw rexr rexx rexb</pfx>
+ <opc>c0 /reg=6</opc>
+ <opr>Eb Ib</opr>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>c1 /reg=6</opc>
+ <opr>Ev Ib</opr>
+ </def>
+ <def>
+ <pfx>aso rexw rexr rexx rexb</pfx>
+ <opc>d0 /reg=6</opc>
+ <opr>Eb I1</opr>
+ </def>
+ <def>
+ <pfx>aso rexw rexr rexx rexb</pfx>
+ <opc>d2 /reg=6</opc>
+ <opr>Eb CL</opr>
+ <syn>cast</syn>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>d3 /reg=6</opc>
+ <opr>Ev CL</opr>
+ <syn>cast</syn>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>c1 /reg=4</opc>
+ <opr>Ev Ib</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>d2 /reg=4</opc>
+ <opr>Eb CL</opr>
+ <syn>cast</syn>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>d1 /reg=4</opc>
+ <opr>Ev I1</opr>
+ </def>
+ <def>
+ <pfx>aso rexw rexr rexx rexb</pfx>
+ <opc>d0 /reg=4</opc>
+ <opr>Eb I1</opr>
+ </def>
+ <def>
+ <pfx>aso rexw rexr rexx rexb</pfx>
+ <opc>c0 /reg=4</opc>
+ <opr>Eb Ib</opr>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>d3 /reg=4</opc>
+ <opr>Ev CL</opr>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>d1 /reg=6</opc>
+ <opr>Ev I1</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>shr</mnemonic>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>c1 /reg=5</opc>
+ <opr>Ev Ib</opr>
+ </def>
+ <def>
+ <pfx>aso rexw rexr rexx rexb</pfx>
+ <opc>d2 /reg=5</opc>
+ <opr>Eb CL</opr>
+ <syn>cast</syn>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>d1 /reg=5</opc>
+ <opr>Ev I1</opr>
+ </def>
+ <def>
+ <pfx>aso rexw rexr rexx rexb</pfx>
+ <opc>d0 /reg=5</opc>
+ <opr>Eb I1</opr>
+ </def>
+ <def>
+ <pfx>aso rexw rexr rexx rexb</pfx>
+ <opc>c0 /reg=5</opc>
+ <opr>Eb Ib</opr>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>d3 /reg=5</opc>
+ <opr>Ev CL</opr>
+ <syn>cast</syn>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>sbb</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>18</opc>
+ <opr>Eb Gb</opr>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>19</opc>
+ <opr>Ev Gv</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>1a</opc>
+ <opr>Gb Eb</opr>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>1b</opc>
+ <opr>Gv Ev</opr>
+ </def>
+ <def>
+ <opc>1c</opc>
+ <opr>AL Ib</opr>
+ </def>
+ <def>
+ <pfx>oso rexw</pfx>
+ <opc>1d</opc>
+ <opr>rAX Iz</opr>
+ <syn>sext</syn>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>80 /reg=3</opc>
+ <opr>Eb Ib</opr>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>81 /reg=3</opc>
+ <opr>Ev Iz</opr>
+ <syn>sext</syn>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>82 /reg=3</opc>
+ <opr>Eb Ib</opr>
+ <mode>inv64</mode>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>83 /reg=3</opc>
+ <opr>Ev Ib</opr>
+ <syn>sext</syn>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>scasb</mnemonic>
+ <def>
+ <opc>ae</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>scasw</mnemonic>
+ <def>
+ <pfx>oso rexw</pfx>
+ <opc>af /o=16</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>scasd</mnemonic>
+ <def>
+ <pfx>oso rexw</pfx>
+ <opc>af /o=32</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>scasq</mnemonic>
+ <def>
+ <pfx>oso rexw</pfx>
+ <opc>af /o=64</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>seto</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 90</opc>
+ <opr>Eb</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>setno</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 91</opc>
+ <opr>Eb</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>setb</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 92</opc>
+ <opr>Eb</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>setnb</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 93</opc>
+ <opr>Eb</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>setz</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 94</opc>
+ <opr>Eb</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>setnz</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 95</opc>
+ <opr>Eb</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>setbe</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 96</opc>
+ <opr>Eb</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>seta</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 97</opc>
+ <opr>Eb</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>sets</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 98</opc>
+ <opr>Eb</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>setns</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 99</opc>
+ <opr>Eb</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>setp</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 9a</opc>
+ <opr>Eb</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>setnp</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 9b</opc>
+ <opr>Eb</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>setl</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 9c</opc>
+ <opr>Eb</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>setge</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 9d</opc>
+ <opr>Eb</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>setle</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 9e</opc>
+ <opr>Eb</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>setg</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 9f</opc>
+ <opr>Eb</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>sfence</mnemonic>
+ <def>
+ <opc>0f ae /reg=7 /mod=11 /rm=0</opc>
+ </def>
+ <def>
+ <opc>0f ae /reg=7 /mod=11 /rm=1</opc>
+ </def>
+ <def>
+ <opc>0f ae /reg=7 /mod=11 /rm=2</opc>
+ </def>
+ <def>
+ <opc>0f ae /reg=7 /mod=11 /rm=3</opc>
+ </def>
+ <def>
+ <opc>0f ae /reg=7 /mod=11 /rm=4</opc>
+ </def>
+ <def>
+ <opc>0f ae /reg=7 /mod=11 /rm=5</opc>
+ </def>
+ <def>
+ <opc>0f ae /reg=7 /mod=11 /rm=6</opc>
+ </def>
+ <def>
+ <opc>0f ae /reg=7 /mod=11 /rm=7</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>sgdt</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 01 /reg=0 /mod=!11</opc>
+ <opr>M</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>shld</mnemonic>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>0f a4</opc>
+ <opr>Ev Gv Ib</opr>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>0f a5</opc>
+ <opr>Ev Gv CL</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>shrd</mnemonic>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>0f ac</opc>
+ <opr>Ev Gv Ib</opr>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>0f ad</opc>
+ <opr>Ev Gv CL</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>shufpd</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f c6</opc>
+ <opr>V W Ib</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>shufps</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f c6</opc>
+ <opr>V W Ib</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>sidt</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 01 /reg=1 /mod=!11</opc>
+ <opr>M</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>sldt</mnemonic>
+ <def>
+ <pfx>aso oso rexr rexx rexb</pfx>
+ <opc>0f 00 /reg=0</opc>
+ <opr>MwRv</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>smsw</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 01 /reg=4 /mod=!11</opc>
+ <opr>M</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>sqrtps</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 51</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>sqrtpd</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 51</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>sqrtsd</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>ssef2 0f 51</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>sqrtss</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>ssef3 0f 51</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>stc</mnemonic>
+ <def>
+ <opc>f9</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>std</mnemonic>
+ <def>
+ <opc>fd</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>stgi</mnemonic>
+ <vendor>amd</vendor>
+ <def>
+ <opc>0f 01 /reg=3 /mod=11 /rm=4</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>sti</mnemonic>
+ <def>
+ <opc>fb</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>skinit</mnemonic>
+ <vendor>amd</vendor>
+ <def>
+ <opc>0f 01 /reg=3 /mod=11 /rm=6</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>stmxcsr</mnemonic>
+ <def>
+ <pfx>aso rexw rexr rexx rexb</pfx>
+ <opc>0f ae /mod=11 /reg=3</opc>
+ <opr>Md</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>stosb</mnemonic>
+ <def>
+ <pfx>seg</pfx>
+ <opc>aa</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>stosw</mnemonic>
+ <def>
+ <pfx>seg oso rexw</pfx>
+ <opc>ab /o=16</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>stosd</mnemonic>
+ <def>
+ <pfx>seg oso rexw</pfx>
+ <opc>ab /o=32</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>stosq</mnemonic>
+ <def>
+ <pfx>seg oso rexw</pfx>
+ <opc>ab /o=64</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>str</mnemonic>
+ <def>
+ <pfx>aso oso rexr rexx rexb</pfx>
+ <opc>0f 00 /reg=1</opc>
+ <opr>Ev</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>sub</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>28</opc>
+ <opr>Eb Gb</opr>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>29</opc>
+ <opr>Ev Gv</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>2a</opc>
+ <opr>Gb Eb</opr>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>2b</opc>
+ <opr>Gv Ev</opr>
+ </def>
+ <def>
+ <opc>2c</opc>
+ <opr>AL Ib</opr>
+ </def>
+ <def>
+ <pfx>oso rexw</pfx>
+ <opc>2d</opc>
+ <opr>rAX Iz</opr>
+ <syn>sext</syn>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>80 /reg=5</opc>
+ <opr>Eb Ib</opr>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>81 /reg=5</opc>
+ <opr>Ev Iz</opr>
+ <syn>sext</syn>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>82 /reg=5</opc>
+ <opr>Eb Ib</opr>
+ <mode>inv64</mode>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>83 /reg=5</opc>
+ <opr>Ev Ib</opr>
+ <syn>sext</syn>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>subpd</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 5c</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>subps</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 5c</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>subsd</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>ssef2 0f 5c</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>subss</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>ssef3 0f 5c</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>swapgs</mnemonic>
+ <def>
+ <opc>0f 01 /reg=7 /mod=11 /rm=0</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>syscall</mnemonic>
+ <def>
+ <opc>0f 05</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>sysenter</mnemonic>
+ <def>
+ <opc>0f 34</opc>
+ <mode>inv64</mode>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>sysexit</mnemonic>
+ <def>
+ <opc>0f 35</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>sysret</mnemonic>
+ <def>
+ <opc>0f 07</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>test</mnemonic>
+ <def>
+ <pfx>aso rexw rexr rexx rexb</pfx>
+ <opc>f6 /reg=0</opc>
+ <opr>Eb Ib</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>84</opc>
+ <opr>Eb Gb</opr>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>85</opc>
+ <opr>Ev Gv</opr>
+ </def>
+ <def>
+ <opc>a8</opc>
+ <opr>AL Ib</opr>
+ </def>
+ <def>
+ <pfx>oso rexw</pfx>
+ <opc>a9</opc>
+ <opr>rAX Iz</opr>
+ <syn>sext</syn>
+ </def>
+ <def>
+ <pfx>aso rexw rexr rexx rexb</pfx>
+ <opc>f6 /reg=1</opc>
+ <opr>Eb Ib</opr>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>f7 /reg=0</opc>
+ <opr>Ev Iz</opr>
+ <syn>sext</syn>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>f7 /reg=1</opc>
+ <opr>Ev Iz</opr>
+ <syn>sext</syn>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>ucomisd</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 2e</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>ucomiss</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 2e</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>ud2</mnemonic>
+ <def>
+ <opc>0f 0b</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>unpckhpd</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 15</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>unpckhps</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 15</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>unpcklps</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 14</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>unpcklpd</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 14</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>verr</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 00 /reg=4</opc>
+ <opr>Ew</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>verw</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 00 /reg=5</opc>
+ <opr>Ew</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>vmcall</mnemonic>
+ <vendor>intel</vendor>
+ <def>
+ <opc>0f 01 /reg=0 /mod=11 /rm=1</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>vmclear</mnemonic>
+ <vendor>intel</vendor>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f c7 /reg=6</opc>
+ <opr>Mq</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>vmxon</mnemonic>
+ <vendor>intel</vendor>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>ssef3 0f c7 /reg=6</opc>
+ <opr>Mq</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>vmptrld</mnemonic>
+ <vendor>intel</vendor>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f c7 /reg=6</opc>
+ <opr>Mq</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>vmptrst</mnemonic>
+ <vendor>intel</vendor>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f c7 /reg=7</opc>
+ <opr>Mq</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>vmlaunch</mnemonic>
+ <vendor>intel</vendor>
+ <def>
+ <opc>0f 01 /reg=0 /mod=11 /rm=2</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>vmresume</mnemonic>
+ <vendor>intel</vendor>
+ <def>
+ <opc>0f 01 /reg=0 /mod=11 /rm=3</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>vmxoff</mnemonic>
+ <vendor>intel</vendor>
+ <def>
+ <opc>0f 01 /reg=0 /mod=11 /rm=4</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>vmread</mnemonic>
+ <vendor>intel</vendor>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 78 /m=16</opc>
+ <opr>Ed Gd</opr>
+ <mode>def64</mode>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 78 /m=32</opc>
+ <opr>Ed Gd</opr>
+ <mode>def64</mode>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 78 /m=64</opc>
+ <opr>Eq Gq</opr>
+ <mode>def64</mode>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>vmwrite</mnemonic>
+ <vendor>intel</vendor>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 79 /m=16</opc>
+ <opr>Gd Ed</opr>
+ <mode>def64</mode>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 79 /m=32</opc>
+ <opr>Gd Ed</opr>
+ <mode>def64</mode>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 79 /m=64</opc>
+ <opr>Gq Eq</opr>
+ <mode>def64</mode>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>vmrun</mnemonic>
+ <vendor>amd</vendor>
+ <def>
+ <opc>0f 01 /reg=3 /mod=11 /rm=0</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>vmmcall</mnemonic>
+ <vendor>amd</vendor>
+ <def>
+ <opc>0f 01 /reg=3 /mod=11 /rm=1</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>vmload</mnemonic>
+ <vendor>amd</vendor>
+ <def>
+ <opc>0f 01 /reg=3 /mod=11 /rm=2</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>vmsave</mnemonic>
+ <vendor>amd</vendor>
+ <def>
+ <opc>0f 01 /reg=3 /mod=11 /rm=3</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>wait</mnemonic>
+ <def>
+ <opc>9b</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>wbinvd</mnemonic>
+ <def>
+ <opc>0f 09</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>wrmsr</mnemonic>
+ <def>
+ <opc>0f 30</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>xadd</mnemonic>
+ <def>
+ <pfx>aso oso rexr rexx rexb</pfx>
+ <opc>0f c0</opc>
+ <opr>Eb Gb</opr>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>0f c1</opc>
+ <opr>Ev Gv</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>xchg</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>86</opc>
+ <opr>Eb Gb</opr>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>87</opc>
+ <opr>Ev Gv</opr>
+ </def>
+ <def>
+ <pfx>oso rexw rexb</pfx>
+ <opc>90</opc>
+ <opr>rAXr8 rAX</opr>
+ </def>
+ <def>
+ <pfx>oso rexw rexb</pfx>
+ <opc>91</opc>
+ <opr>rCXr9 rAX</opr>
+ </def>
+ <def>
+ <pfx>oso rexw rexb</pfx>
+ <opc>92</opc>
+ <opr>rDXr10 rAX</opr>
+ </def>
+ <def>
+ <pfx>oso rexw rexb</pfx>
+ <opc>93</opc>
+ <opr>rBXr11 rAX</opr>
+ </def>
+ <def>
+ <pfx>oso rexw rexb</pfx>
+ <opc>94</opc>
+ <opr>rSPr12 rAX</opr>
+ </def>
+ <def>
+ <pfx>oso rexw rexb</pfx>
+ <opc>95</opc>
+ <opr>rBPr13 rAX</opr>
+ </def>
+ <def>
+ <pfx>oso rexw rexb</pfx>
+ <opc>96</opc>
+ <opr>rSIr14 rAX</opr>
+ </def>
+ <def>
+ <pfx>oso rexw rexb</pfx>
+ <opc>97</opc>
+ <opr>rDIr15 rAX</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>xlatb</mnemonic>
+ <def>
+ <pfx>rexw</pfx>
+ <opc>d7</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>xor</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>30</opc>
+ <opr>Eb Gb</opr>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>31</opc>
+ <opr>Ev Gv</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>32</opc>
+ <opr>Gb Eb</opr>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>33</opc>
+ <opr>Gv Ev</opr>
+ </def>
+ <def>
+ <opc>34</opc>
+ <opr>AL Ib</opr>
+ </def>
+ <def>
+ <pfx>oso rexw</pfx>
+ <opc>35</opc>
+ <opr>rAX Iz</opr>
+ <syn>sext</syn>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>80 /reg=6</opc>
+ <opr>Eb Ib</opr>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>81 /reg=6</opc>
+ <opr>Ev Iz</opr>
+ <syn>sext</syn>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>82 /reg=6</opc>
+ <opr>Eb Ib</opr>
+ <mode>inv64</mode>
+ </def>
+ <def>
+ <pfx>aso oso rexw rexr rexx rexb</pfx>
+ <opc>83 /reg=6</opc>
+ <opr>Ev Ib</opr>
+ <syn>sext</syn>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>xorpd</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 57</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>xorps</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 57</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>xcryptecb</mnemonic>
+ <def>
+ <opc>0f a7 /mod=11 /rm=0 /reg=1</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>xcryptcbc</mnemonic>
+ <def>
+ <opc>0f a7 /mod=11 /rm=0 /reg=2</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>xcryptctr</mnemonic>
+ <def>
+ <opc>0f a7 /mod=11 /rm=0 /reg=3</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>xcryptcfb</mnemonic>
+ <def>
+ <opc>0f a7 /mod=11 /rm=0 /reg=4</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>xcryptofb</mnemonic>
+ <def>
+ <opc>0f a7 /mod=11 /rm=0 /reg=5</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>xsha1</mnemonic>
+ <def>
+ <opc>0f a6 /mod=11 /rm=0 /reg=1</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>xsha256</mnemonic>
+ <def>
+ <opc>0f a6 /mod=11 /rm=0 /reg=2</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>xstore</mnemonic>
+ <def>
+ <opc>0f a7 /mod=11 /rm=0 /reg=0</opc>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>db</mnemonic>
+ </instruction>
+
+ <!--
+ SSE 2
+ -->
+
+ <instruction>
+ <mnemonic>movdqa</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 7f</opc>
+ <opr>W V</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 6f</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>movdq2q</mnemonic>
+ <def>
+ <pfx>aso rexb</pfx>
+ <opc>ssef2 0f d6</opc>
+ <opr>P VR</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>movdqu</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>ssef3 0f 6f</opc>
+ <opr>V W</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>ssef3 0f 7f</opc>
+ <opr>W V</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>movq2dq</mnemonic>
+ <def>
+ <pfx>aso</pfx>
+ <opc>ssef3 0f d6</opc>
+ <opr>V PR</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>paddq</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f d4</opc>
+ <opr>P Q</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f d4</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>psubq</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f fb</opc>
+ <opr>V W</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f fb</opc>
+ <opr>P Q</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pmuludq</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f f4</opc>
+ <opr>P Q</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f f4</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pshufhw</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>ssef3 0f 70</opc>
+ <opr>V W Ib</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pshuflw</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>ssef2 0f 70</opc>
+ <opr>V W Ib</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pshufd</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 70</opc>
+ <opr>V W Ib</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pslldq</mnemonic>
+ <def>
+ <pfx>rexb</pfx>
+ <opc>sse66 0f 73 /reg=7</opc>
+ <opr>VR Ib</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>psrldq</mnemonic>
+ <def>
+ <pfx>rexb</pfx>
+ <opc>sse66 0f 73 /reg=3</opc>
+ <opr>VR Ib</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>punpckhqdq</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 6d</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>punpcklqdq</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 6c</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <!--
+ SSE 3
+ -->
+
+ <instruction>
+ <mnemonic>addsubpd</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f d0</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>addsubps</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>ssef2 0f d0</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>haddpd</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 7c</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>haddps</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>ssef2 0f 7c</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>hsubpd</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 7d</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>hsubps</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>ssef2 0f 7d</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>movddup</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>ssef2 0f 12 /mod=11</opc>
+ <opr>V W</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>ssef2 0f 12 /mod=!11</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>movshdup</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>ssef3 0f 16 /mod=11</opc>
+ <opr>V W</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>ssef3 0f 16 /mod=!11</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>movsldup</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>ssef3 0f 12 /mod=11</opc>
+ <opr>V W</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>ssef3 0f 12 /mod=!11</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <!--
+ SSSE 3
+ -->
+
+ <instruction>
+ <mnemonic>pabsb</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 38 1c</opc>
+ <opr>P Q</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 38 1c</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pabsw</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 38 1d</opc>
+ <opr>P Q</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 38 1d</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pabsd</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 38 1e</opc>
+ <opr>P Q</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 38 1e</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>psignb</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 38 00</opc>
+ <opr>P Q</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 38 00</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>phaddw</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 38 01</opc>
+ <opr>P Q</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 38 01</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>phaddd</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 38 02</opc>
+ <opr>P Q</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 38 02</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>phaddsw</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 38 03</opc>
+ <opr>P Q</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 38 03</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pmaddubsw</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 38 04</opc>
+ <opr>P Q</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 38 04</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>phsubw</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 38 05</opc>
+ <opr>P Q</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 38 05</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>phsubd</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 38 06</opc>
+ <opr>P Q</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 38 06</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>phsubsw</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 38 07</opc>
+ <opr>P Q</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 38 07</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>psignb</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 38 08</opc>
+ <opr>P Q</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 38 08</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>psignd</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 38 0a</opc>
+ <opr>P Q</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 38 0a</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>psignw</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 38 09</opc>
+ <opr>P Q</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 38 09</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pmulhrsw</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 38 0b</opc>
+ <opr>P Q</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 38 0b</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>palignr</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>0f 3a 0f</opc>
+ <opr>P Q Ib</opr>
+ </def>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 3a 0f</opc>
+ <opr>V W Ib</opr>
+ </def>
+ </instruction>
+
+ <!--
+ SSE 4.1
+ -->
+
+ <instruction>
+ <mnemonic>pblendvb</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 38 10</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pmuldq</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 38 28</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pminsb</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 38 38</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pminsd</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 38 39</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pminuw</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 38 3a</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pminud</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 38 3b</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pmaxsb</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 38 3c</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pmaxsd</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 38 3d</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pmaxud</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 38 3f</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pmulld</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 38 40</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>phminposuw</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 38 41</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>roundps</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 3a 08</opc>
+ <opr>V W Ib</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>roundpd</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 3a 09</opc>
+ <opr>V W Ib</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>roundss</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 3a 0a</opc>
+ <opr>V W Ib</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>roundsd</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 3a 0b</opc>
+ <opr>V W Ib</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>blendpd</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 3a 0d</opc>
+ <opr>V W Ib</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>pblendw</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 3a 0e</opc>
+ <opr>V W Ib</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>blendps</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 3a 0c</opc>
+ <opr>V W Ib</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>blendvpd</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 38 15</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>blendvps</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 38 14</opc>
+ <opr>V W</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>dpps</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 3a 40</opc>
+ <opr>V W Ib</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>dppd</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 3a 41</opc>
+ <opr>V W Ib</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>mpsadbw</mnemonic>
+ <def>
+ <pfx>aso rexr rexx rexb</pfx>
+ <opc>sse66 0f 3a 42</opc>
+ <opr>V W Ib</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>extractps</mnemonic>
+ <def>
+ <pfx>aso rexr rexw rexb</pfx>
+ <opc>sse66 0f 3a 17</opc>
+ <opr>MdRy V Ib</opr>
+ </def>
+ </instruction>
+
+ <instruction>
+ <mnemonic>invalid</mnemonic>
+ </instruction>
+
+</x86optable>
diff --git a/Source/JavaScriptCore/disassembler/udis86/ud_opcode.py b/Source/JavaScriptCore/disassembler/udis86/ud_opcode.py
new file mode 100644
index 000000000..f301b5246
--- /dev/null
+++ b/Source/JavaScriptCore/disassembler/udis86/ud_opcode.py
@@ -0,0 +1,235 @@
+# udis86 - scripts/ud_opcode.py
+#
+# Copyright (c) 2009 Vivek Thampi
+# 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 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 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 A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+
+class UdOpcodeTables:
+
+ TableInfo = {
+ 'opctbl' : { 'name' : 'UD_TAB__OPC_TABLE', 'size' : 256 },
+ '/sse' : { 'name' : 'UD_TAB__OPC_SSE', 'size' : 4 },
+ '/reg' : { 'name' : 'UD_TAB__OPC_REG', 'size' : 8 },
+ '/rm' : { 'name' : 'UD_TAB__OPC_RM', 'size' : 8 },
+ '/mod' : { 'name' : 'UD_TAB__OPC_MOD', 'size' : 2 },
+ '/m' : { 'name' : 'UD_TAB__OPC_MODE', 'size' : 3 },
+ '/x87' : { 'name' : 'UD_TAB__OPC_X87', 'size' : 64 },
+ '/a' : { 'name' : 'UD_TAB__OPC_ASIZE', 'size' : 3 },
+ '/o' : { 'name' : 'UD_TAB__OPC_OSIZE', 'size' : 3 },
+ '/3dnow' : { 'name' : 'UD_TAB__OPC_3DNOW', 'size' : 256 },
+ 'vendor' : { 'name' : 'UD_TAB__OPC_VENDOR', 'size' : 3 },
+ }
+
+ OpcodeTable0 = {
+ 'type' : 'opctbl',
+ 'entries' : {},
+ 'meta' : 'table0'
+ }
+
+ OpcExtIndex = {
+
+ # ssef2, ssef3, sse66
+ 'sse': {
+ 'none' : '00',
+ 'f2' : '01',
+ 'f3' : '02',
+ '66' : '03'
+ },
+
+ # /mod=
+ 'mod': {
+ '!11' : '00',
+ '11' : '01'
+ },
+
+ # /m=, /o=, /a=
+ 'mode': {
+ '16' : '00',
+ '32' : '01',
+ '64' : '02'
+ },
+
+ 'vendor' : {
+ 'amd' : '00',
+ 'intel' : '01',
+ 'any' : '02'
+ }
+ }
+
+ InsnTable = []
+ MnemonicsTable = []
+
+ ThreeDNowTable = {}
+
+ def sizeOfTable( self, t ):
+ return self.TableInfo[ t ][ 'size' ]
+
+ def nameOfTable( self, t ):
+ return self.TableInfo[ t ][ 'name' ]
+
+ #
+ # Updates a table entry: If the entry doesn't exist
+ # it will create the entry, otherwise, it will walk
+ # while validating the path.
+ #
+ def updateTable( self, table, index, type, meta ):
+ if not index in table[ 'entries' ]:
+ table[ 'entries' ][ index ] = { 'type' : type, 'entries' : {}, 'meta' : meta }
+ if table[ 'entries' ][ index ][ 'type' ] != type:
+ raise NameError( "error: violation in opcode mapping (overwrite) %s with %s." %
+ ( table[ 'entries' ][ index ][ 'type' ], type) )
+ return table[ 'entries' ][ index ]
+
+ class Insn:
+ """An abstract type representing an instruction in the opcode map.
+ """
+
+ # A mapping of opcode extensions to their representational
+ # values used in the opcode map.
+ OpcExtMap = {
+ '/rm' : lambda v: "%02x" % int(v, 16),
+ '/x87' : lambda v: "%02x" % int(v, 16),
+ '/3dnow' : lambda v: "%02x" % int(v, 16),
+ '/reg' : lambda v: "%02x" % int(v, 16),
+ # modrm.mod
+ # (!11, 11) => (00, 01)
+ '/mod' : lambda v: '00' if v == '!11' else '01',
+ # Mode extensions:
+ # (16, 32, 64) => (00, 01, 02)
+ '/o' : lambda v: "%02x" % (int(v) / 32),
+ '/a' : lambda v: "%02x" % (int(v) / 32),
+ '/m' : lambda v: "%02x" % (int(v) / 32),
+ '/sse' : lambda v: UdOpcodeTables.OpcExtIndex['sse'][v]
+ }
+
+ def __init__(self, prefixes, mnemonic, opcodes, operands, vendor):
+ self.opcodes = opcodes
+ self.prefixes = prefixes
+ self.mnemonic = mnemonic
+ self.operands = operands
+ self.vendor = vendor
+ self.opcext = {}
+
+ ssePrefix = None
+ if self.opcodes[0] in ('ssef2', 'ssef3', 'sse66'):
+ ssePrefix = self.opcodes[0][3:]
+ self.opcodes.pop(0)
+
+ # do some preliminary decoding of the instruction type
+ # 1byte, 2byte or 3byte instruction?
+ self.nByteInsn = 1
+ if self.opcodes[0] == '0f': # 2byte
+ # 2+ byte opcodes are always disambiguated by an
+ # sse prefix, unless it is a 3d now instruction
+ # which is 0f 0f ...
+ if self.opcodes[1] != '0f' and ssePrefix is None:
+ ssePrefix = 'none'
+ if self.opcodes[1] in ('38', '3a'): # 3byte
+ self.nByteInsn = 3
+ else:
+ self.nByteInsn = 2
+
+ # The opcode that indexes into the opcode table.
+ self.opcode = self.opcodes[self.nByteInsn - 1]
+
+ # Record opcode extensions
+ for opcode in self.opcodes[self.nByteInsn:]:
+ arg, val = opcode.split('=')
+ self.opcext[arg] = self.OpcExtMap[arg](val)
+
+ # Record sse extension: the reason sse extension is handled
+ # separately is that historically sse was handled as a first
+ # class opcode, not as an extension. Now that sse is handled
+ # as an extension, we do the manual conversion here, as opposed
+ # to modifying the opcode xml file.
+ if ssePrefix is not None:
+ self.opcext['/sse'] = self.OpcExtMap['/sse'](ssePrefix)
+
+ def parse(self, table, insn):
+ index = insn.opcodes[0];
+ if insn.nByteInsn > 1:
+ assert index == '0f'
+ table = self.updateTable(table, index, 'opctbl', '0f')
+ index = insn.opcodes[1]
+
+ if insn.nByteInsn == 3:
+ table = self.updateTable(table, index, 'opctbl', index)
+ index = insn.opcodes[2]
+
+ # Walk down the tree, create levels as needed, for opcode
+ # extensions. The order is important, and determines how
+ # well the opcode table is packed. Also note, /sse must be
+ # before /o, because /sse may consume operand size prefix
+ # affect the outcome of /o.
+ for ext in ('/mod', '/x87', '/reg', '/rm', '/sse',
+ '/o', '/a', '/m', '/3dnow'):
+ if ext in insn.opcext:
+ table = self.updateTable(table, index, ext, ext)
+ index = insn.opcext[ext]
+
+ # additional table for disambiguating vendor
+ if len(insn.vendor):
+ table = self.updateTable(table, index, 'vendor', insn.vendor)
+ index = self.OpcExtIndex['vendor'][insn.vendor]
+
+ # make leaf node entries
+ leaf = self.updateTable(table, index, 'insn', '')
+
+ leaf['mnemonic'] = insn.mnemonic
+ leaf['prefixes'] = insn.prefixes
+ leaf['operands'] = insn.operands
+
+ # add instruction to linear table of instruction forms
+ self.InsnTable.append({ 'prefixes' : insn.prefixes,
+ 'mnemonic' : insn.mnemonic,
+ 'operands' : insn.operands })
+
+ # add mnemonic to mnemonic table
+ if not insn.mnemonic in self.MnemonicsTable:
+ self.MnemonicsTable.append(insn.mnemonic)
+
+
+ # Adds an instruction definition to the opcode tables
+ def addInsnDef( self, prefixes, mnemonic, opcodes, operands, vendor ):
+ insn = self.Insn(prefixes=prefixes,
+ mnemonic=mnemonic,
+ opcodes=opcodes,
+ operands=operands,
+ vendor=vendor)
+ self.parse(self.OpcodeTable0, insn)
+
+ def print_table( self, table, pfxs ):
+ print "%s |" % pfxs
+ keys = table[ 'entries' ].keys()
+ if ( len( keys ) ):
+ keys.sort()
+ for idx in keys:
+ e = table[ 'entries' ][ idx ]
+ if e[ 'type' ] == 'insn':
+ print "%s |-<%s>" % ( pfxs, idx ),
+ print "%s %s" % ( e[ 'mnemonic' ], ' '.join( e[ 'operands'] ) )
+ else:
+ print "%s |-<%s> %s" % ( pfxs, idx, e['type'] )
+ self.print_table( e, pfxs + ' |' )
+
+ def print_tree( self ):
+ self.print_table( self.OpcodeTable0, '' )
diff --git a/Source/JavaScriptCore/disassembler/udis86/ud_optable.py b/Source/JavaScriptCore/disassembler/udis86/ud_optable.py
new file mode 100644
index 000000000..5b5c55d3b
--- /dev/null
+++ b/Source/JavaScriptCore/disassembler/udis86/ud_optable.py
@@ -0,0 +1,103 @@
+# udis86 - scripts/ud_optable.py (optable.xml parser)
+#
+# Copyright (c) 2009 Vivek Thampi
+# 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 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 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 A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+
+import os
+import sys
+from xml.dom import minidom
+
+class UdOptableXmlParser:
+
+ def parseDef( self, node ):
+ ven = ''
+ pfx = []
+ opc = []
+ opr = []
+ for def_node in node.childNodes:
+ if not def_node.localName:
+ continue
+ if def_node.localName == 'pfx':
+ pfx = def_node.firstChild.data.split();
+ elif def_node.localName == 'opc':
+ opc = def_node.firstChild.data.split();
+ elif def_node.localName == 'opr':
+ opr = def_node.firstChild.data.split();
+ elif def_node.localName == 'mode':
+ pfx.extend( def_node.firstChild.data.split() );
+ elif def_node.localName == 'syn':
+ pfx.extend( def_node.firstChild.data.split() );
+ elif def_node.localName == 'vendor':
+ ven = ( def_node.firstChild.data );
+ else:
+ print "warning: invalid node - %s" % def_node.localName
+ continue
+ return ( pfx, opc, opr, ven )
+
+ def parse( self, xml, fn ):
+ xmlDoc = minidom.parse( xml )
+ self.TlNode = xmlDoc.firstChild
+
+ while self.TlNode and self.TlNode.localName != "x86optable":
+ self.TlNode = self.TlNode.nextSibling
+
+ for insnNode in self.TlNode.childNodes:
+ if not insnNode.localName:
+ continue
+ if insnNode.localName != "instruction":
+ print "warning: invalid insn node - %s" % insnNode.localName
+ continue
+
+ mnemonic = insnNode.getElementsByTagName( 'mnemonic' )[ 0 ].firstChild.data
+ vendor = ''
+
+ for node in insnNode.childNodes:
+ if node.localName == 'vendor':
+ vendor = node.firstChild.data
+ elif node.localName == 'def':
+ ( prefixes, opcodes, operands, local_vendor ) = \
+ self.parseDef( node )
+ if ( len( local_vendor ) ):
+ vendor = local_vendor
+ # callback
+ fn( prefixes, mnemonic, opcodes, operands, vendor )
+
+
+def printFn( pfx, mnm, opc, opr, ven ):
+ print 'def: ',
+ if len( pfx ):
+ print ' '.join( pfx ),
+ print "%s %s %s %s" % \
+ ( mnm, ' '.join( opc ), ' '.join( opr ), ven )
+
+
+def parse( xml, callback ):
+ parser = UdOptableXmlParser()
+ parser.parse( xml, callback )
+
+def main():
+ parser = UdOptableXmlParser()
+ parser.parse( sys.argv[ 1 ], printFn )
+
+if __name__ == "__main__":
+ main()
diff --git a/Source/JavaScriptCore/disassembler/udis86/udis86.c b/Source/JavaScriptCore/disassembler/udis86/udis86.c
new file mode 100644
index 000000000..fbf76707a
--- /dev/null
+++ b/Source/JavaScriptCore/disassembler/udis86/udis86.c
@@ -0,0 +1,183 @@
+/* udis86 - libudis86/udis86.c
+ *
+ * Copyright (c) 2002-2009 Vivek Thampi
+ * 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 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 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 A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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 <wtf/Platform.h>
+
+#if USE(UDIS86)
+
+#include "udis86_input.h"
+#include "udis86_extern.h"
+
+#ifndef __UD_STANDALONE__
+# include <stdlib.h>
+# include <string.h>
+#endif /* __UD_STANDALONE__ */
+
+/* =============================================================================
+ * ud_init() - Initializes ud_t object.
+ * =============================================================================
+ */
+extern void
+ud_init(struct ud* u)
+{
+ memset((void*)u, 0, sizeof(struct ud));
+ ud_set_mode(u, 16);
+ u->mnemonic = UD_Iinvalid;
+ ud_set_pc(u, 0);
+#ifndef __UD_STANDALONE__
+ ud_set_input_file(u, stdin);
+#endif /* __UD_STANDALONE__ */
+}
+
+/* =============================================================================
+ * ud_disassemble() - disassembles one instruction and returns the number of
+ * bytes disassembled. A zero means end of disassembly.
+ * =============================================================================
+ */
+extern unsigned int
+ud_disassemble(struct ud* u)
+{
+ if (ud_input_end(u))
+ return 0;
+
+
+ u->insn_buffer[0] = u->insn_hexcode[0] = 0;
+
+
+ if (ud_decode(u) == 0)
+ return 0;
+ if (u->translator)
+ u->translator(u);
+ return ud_insn_len(u);
+}
+
+/* =============================================================================
+ * ud_set_mode() - Set Disassemly Mode.
+ * =============================================================================
+ */
+extern void
+ud_set_mode(struct ud* u, uint8_t m)
+{
+ switch(m) {
+ case 16:
+ case 32:
+ case 64: u->dis_mode = m ; return;
+ default: u->dis_mode = 16; return;
+ }
+}
+
+/* =============================================================================
+ * ud_set_vendor() - Set vendor.
+ * =============================================================================
+ */
+extern void
+ud_set_vendor(struct ud* u, unsigned v)
+{
+ switch(v) {
+ case UD_VENDOR_INTEL:
+ u->vendor = v;
+ break;
+ case UD_VENDOR_ANY:
+ u->vendor = v;
+ break;
+ default:
+ u->vendor = UD_VENDOR_AMD;
+ }
+}
+
+/* =============================================================================
+ * ud_set_pc() - Sets code origin.
+ * =============================================================================
+ */
+extern void
+ud_set_pc(struct ud* u, uint64_t o)
+{
+ u->pc = o;
+}
+
+/* =============================================================================
+ * ud_set_syntax() - Sets the output syntax.
+ * =============================================================================
+ */
+extern void
+ud_set_syntax(struct ud* u, void (*t)(struct ud*))
+{
+ u->translator = t;
+}
+
+/* =============================================================================
+ * ud_insn() - returns the disassembled instruction
+ * =============================================================================
+ */
+extern char*
+ud_insn_asm(struct ud* u)
+{
+ return u->insn_buffer;
+}
+
+/* =============================================================================
+ * ud_insn_offset() - Returns the offset.
+ * =============================================================================
+ */
+extern uint64_t
+ud_insn_off(struct ud* u)
+{
+ return u->insn_offset;
+}
+
+
+/* =============================================================================
+ * ud_insn_hex() - Returns hex form of disassembled instruction.
+ * =============================================================================
+ */
+extern char*
+ud_insn_hex(struct ud* u)
+{
+ return u->insn_hexcode;
+}
+
+/* =============================================================================
+ * ud_insn_ptr() - Returns code disassembled.
+ * =============================================================================
+ */
+extern uint8_t*
+ud_insn_ptr(struct ud* u)
+{
+ return u->inp_sess;
+}
+
+/* =============================================================================
+ * ud_insn_len() - Returns the count of bytes disassembled.
+ * =============================================================================
+ */
+extern unsigned int
+ud_insn_len(struct ud* u)
+{
+ return u->inp_ctr;
+}
+
+#endif // USE(UDIS86)
diff --git a/Source/JavaScriptCore/disassembler/udis86/udis86.h b/Source/JavaScriptCore/disassembler/udis86/udis86.h
new file mode 100644
index 000000000..baaf495e0
--- /dev/null
+++ b/Source/JavaScriptCore/disassembler/udis86/udis86.h
@@ -0,0 +1,33 @@
+/* udis86 - udis86.h
+ *
+ * Copyright (c) 2002-2009 Vivek Thampi
+ * 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 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 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 A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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 UDIS86_H
+#define UDIS86_H
+
+#include "udis86_types.h"
+#include "udis86_extern.h"
+#include "udis86_itab.h"
+
+#endif
diff --git a/Source/JavaScriptCore/disassembler/udis86/udis86_decode.c b/Source/JavaScriptCore/disassembler/udis86/udis86_decode.c
new file mode 100644
index 000000000..a3fd57665
--- /dev/null
+++ b/Source/JavaScriptCore/disassembler/udis86/udis86_decode.c
@@ -0,0 +1,1142 @@
+/* udis86 - libudis86/decode.c
+ *
+ * Copyright (c) 2002-2009 Vivek Thampi
+ * 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 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 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 A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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 <wtf/Platform.h>
+
+#if USE(UDIS86)
+
+#include "udis86_extern.h"
+#include "udis86_types.h"
+#include "udis86_input.h"
+#include "udis86_decode.h"
+#include <wtf/Assertions.h>
+
+#define dbg(x, n...)
+/* #define dbg printf */
+
+#ifndef __UD_STANDALONE__
+# include <string.h>
+#endif /* __UD_STANDALONE__ */
+
+/* The max number of prefixes to an instruction */
+#define MAX_PREFIXES 15
+
+/* instruction aliases and special cases */
+static struct ud_itab_entry s_ie__invalid =
+ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none };
+
+static int
+decode_ext(struct ud *u, uint16_t ptr);
+
+
+static inline int
+eff_opr_mode(int dis_mode, int rex_w, int pfx_opr)
+{
+ if (dis_mode == 64) {
+ return rex_w ? 64 : (pfx_opr ? 16 : 32);
+ } else if (dis_mode == 32) {
+ return pfx_opr ? 16 : 32;
+ } else {
+ ASSERT(dis_mode == 16);
+ return pfx_opr ? 32 : 16;
+ }
+}
+
+
+static inline int
+eff_adr_mode(int dis_mode, int pfx_adr)
+{
+ if (dis_mode == 64) {
+ return pfx_adr ? 32 : 64;
+ } else if (dis_mode == 32) {
+ return pfx_adr ? 16 : 32;
+ } else {
+ ASSERT(dis_mode == 16);
+ return pfx_adr ? 32 : 16;
+ }
+}
+
+
+/* Looks up mnemonic code in the mnemonic string table
+ * Returns NULL if the mnemonic code is invalid
+ */
+const char * ud_lookup_mnemonic( enum ud_mnemonic_code c )
+{
+ return ud_mnemonics_str[ c ];
+}
+
+
+/*
+ * decode_prefixes
+ *
+ * Extracts instruction prefixes.
+ */
+static int
+decode_prefixes(struct ud *u)
+{
+ unsigned int have_pfx = 1;
+ unsigned int i;
+ uint8_t curr;
+
+ /* if in error state, bail out */
+ if ( u->error )
+ return -1;
+
+ /* keep going as long as there are prefixes available */
+ for ( i = 0; have_pfx ; ++i ) {
+
+ /* Get next byte. */
+ ud_inp_next(u);
+ if ( u->error )
+ return -1;
+ curr = ud_inp_curr( u );
+
+ /* rex prefixes in 64bit mode */
+ if ( u->dis_mode == 64 && ( curr & 0xF0 ) == 0x40 ) {
+ u->pfx_rex = curr;
+ } else {
+ switch ( curr )
+ {
+ case 0x2E :
+ u->pfx_seg = UD_R_CS;
+ u->pfx_rex = 0;
+ break;
+ case 0x36 :
+ u->pfx_seg = UD_R_SS;
+ u->pfx_rex = 0;
+ break;
+ case 0x3E :
+ u->pfx_seg = UD_R_DS;
+ u->pfx_rex = 0;
+ break;
+ case 0x26 :
+ u->pfx_seg = UD_R_ES;
+ u->pfx_rex = 0;
+ break;
+ case 0x64 :
+ u->pfx_seg = UD_R_FS;
+ u->pfx_rex = 0;
+ break;
+ case 0x65 :
+ u->pfx_seg = UD_R_GS;
+ u->pfx_rex = 0;
+ break;
+ case 0x67 : /* adress-size override prefix */
+ u->pfx_adr = 0x67;
+ u->pfx_rex = 0;
+ break;
+ case 0xF0 :
+ u->pfx_lock = 0xF0;
+ u->pfx_rex = 0;
+ break;
+ case 0x66:
+ /* the 0x66 sse prefix is only effective if no other sse prefix
+ * has already been specified.
+ */
+ if ( !u->pfx_insn ) u->pfx_insn = 0x66;
+ u->pfx_opr = 0x66;
+ u->pfx_rex = 0;
+ break;
+ case 0xF2:
+ u->pfx_insn = 0xF2;
+ u->pfx_repne = 0xF2;
+ u->pfx_rex = 0;
+ break;
+ case 0xF3:
+ u->pfx_insn = 0xF3;
+ u->pfx_rep = 0xF3;
+ u->pfx_repe = 0xF3;
+ u->pfx_rex = 0;
+ break;
+ default :
+ /* No more prefixes */
+ have_pfx = 0;
+ break;
+ }
+ }
+
+ /* check if we reached max instruction length */
+ if ( i + 1 == MAX_INSN_LENGTH ) {
+ u->error = 1;
+ break;
+ }
+ }
+
+ /* return status */
+ if ( u->error )
+ return -1;
+
+ /* rewind back one byte in stream, since the above loop
+ * stops with a non-prefix byte.
+ */
+ ud_inp_back(u);
+ return 0;
+}
+
+
+static inline unsigned int modrm( struct ud * u )
+{
+ if ( !u->have_modrm ) {
+ u->modrm = ud_inp_next( u );
+ u->have_modrm = 1;
+ }
+ return u->modrm;
+}
+
+
+static unsigned int resolve_operand_size( const struct ud * u, unsigned int s )
+{
+ switch ( s )
+ {
+ case SZ_V:
+ return ( u->opr_mode );
+ case SZ_Z:
+ return ( u->opr_mode == 16 ) ? 16 : 32;
+ case SZ_P:
+ return ( u->opr_mode == 16 ) ? SZ_WP : SZ_DP;
+ case SZ_MDQ:
+ return ( u->opr_mode == 16 ) ? 32 : u->opr_mode;
+ case SZ_RDQ:
+ return ( u->dis_mode == 64 ) ? 64 : 32;
+ default:
+ return s;
+ }
+}
+
+
+static int resolve_mnemonic( struct ud* u )
+{
+ /* far/near flags */
+ u->br_far = 0;
+ u->br_near = 0;
+ /* readjust operand sizes for call/jmp instrcutions */
+ if ( u->mnemonic == UD_Icall || u->mnemonic == UD_Ijmp ) {
+ /* WP: 16:16 pointer */
+ if ( u->operand[ 0 ].size == SZ_WP ) {
+ u->operand[ 0 ].size = 16;
+ u->br_far = 1;
+ u->br_near= 0;
+ /* DP: 32:32 pointer */
+ } else if ( u->operand[ 0 ].size == SZ_DP ) {
+ u->operand[ 0 ].size = 32;
+ u->br_far = 1;
+ u->br_near= 0;
+ } else {
+ u->br_far = 0;
+ u->br_near= 1;
+ }
+ /* resolve 3dnow weirdness. */
+ } else if ( u->mnemonic == UD_I3dnow ) {
+ u->mnemonic = ud_itab[ u->le->table[ ud_inp_curr( u ) ] ].mnemonic;
+ }
+ /* SWAPGS is only valid in 64bits mode */
+ if ( u->mnemonic == UD_Iswapgs && u->dis_mode != 64 ) {
+ u->error = 1;
+ return -1;
+ }
+
+ if (u->mnemonic == UD_Ixchg) {
+ if ((u->operand[0].type == UD_OP_REG && u->operand[0].base == UD_R_AX &&
+ u->operand[1].type == UD_OP_REG && u->operand[1].base == UD_R_AX) ||
+ (u->operand[0].type == UD_OP_REG && u->operand[0].base == UD_R_EAX &&
+ u->operand[1].type == UD_OP_REG && u->operand[1].base == UD_R_EAX)) {
+ u->operand[0].type = UD_NONE;
+ u->operand[1].type = UD_NONE;
+ u->mnemonic = UD_Inop;
+ }
+ }
+
+ if (u->mnemonic == UD_Inop && u->pfx_rep) {
+ u->pfx_rep = 0;
+ u->mnemonic = UD_Ipause;
+ }
+ return 0;
+}
+
+
+/* -----------------------------------------------------------------------------
+ * decode_a()- Decodes operands of the type seg:offset
+ * -----------------------------------------------------------------------------
+ */
+static void
+decode_a(struct ud* u, struct ud_operand *op)
+{
+ if (u->opr_mode == 16) {
+ /* seg16:off16 */
+ op->type = UD_OP_PTR;
+ op->size = 32;
+ op->lval.ptr.off = ud_inp_uint16(u);
+ op->lval.ptr.seg = ud_inp_uint16(u);
+ } else {
+ /* seg16:off32 */
+ op->type = UD_OP_PTR;
+ op->size = 48;
+ op->lval.ptr.off = ud_inp_uint32(u);
+ op->lval.ptr.seg = ud_inp_uint16(u);
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * decode_gpr() - Returns decoded General Purpose Register
+ * -----------------------------------------------------------------------------
+ */
+static enum ud_type
+decode_gpr(register struct ud* u, unsigned int s, unsigned char rm)
+{
+ s = resolve_operand_size(u, s);
+
+ switch (s) {
+ case 64:
+ return UD_R_RAX + rm;
+ case SZ_DP:
+ case 32:
+ return UD_R_EAX + rm;
+ case SZ_WP:
+ case 16:
+ return UD_R_AX + rm;
+ case 8:
+ if (u->dis_mode == 64 && u->pfx_rex) {
+ if (rm >= 4)
+ return UD_R_SPL + (rm-4);
+ return UD_R_AL + rm;
+ } else return UD_R_AL + rm;
+ default:
+ return 0;
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * resolve_gpr64() - 64bit General Purpose Register-Selection.
+ * -----------------------------------------------------------------------------
+ */
+static enum ud_type
+resolve_gpr64(struct ud* u, enum ud_operand_code gpr_op, enum ud_operand_size * size)
+{
+ if (gpr_op >= OP_rAXr8 && gpr_op <= OP_rDIr15)
+ gpr_op = (gpr_op - OP_rAXr8) | (REX_B(u->pfx_rex) << 3);
+ else gpr_op = (gpr_op - OP_rAX);
+
+ if (u->opr_mode == 16) {
+ *size = 16;
+ return gpr_op + UD_R_AX;
+ }
+ if (u->dis_mode == 32 ||
+ (u->opr_mode == 32 && ! (REX_W(u->pfx_rex) || u->default64))) {
+ *size = 32;
+ return gpr_op + UD_R_EAX;
+ }
+
+ *size = 64;
+ return gpr_op + UD_R_RAX;
+}
+
+/* -----------------------------------------------------------------------------
+ * resolve_gpr32 () - 32bit General Purpose Register-Selection.
+ * -----------------------------------------------------------------------------
+ */
+static enum ud_type
+resolve_gpr32(struct ud* u, enum ud_operand_code gpr_op)
+{
+ gpr_op = gpr_op - OP_eAX;
+
+ if (u->opr_mode == 16)
+ return gpr_op + UD_R_AX;
+
+ return gpr_op + UD_R_EAX;
+}
+
+/* -----------------------------------------------------------------------------
+ * resolve_reg() - Resolves the register type
+ * -----------------------------------------------------------------------------
+ */
+static enum ud_type
+resolve_reg(struct ud* u, unsigned int type, unsigned char i)
+{
+ switch (type) {
+ case T_MMX : return UD_R_MM0 + (i & 7);
+ case T_XMM : return UD_R_XMM0 + i;
+ case T_CRG : return UD_R_CR0 + i;
+ case T_DBG : return UD_R_DR0 + i;
+ case T_SEG : {
+ /*
+ * Only 6 segment registers, anything else is an error.
+ */
+ if ((i & 7) > 5) {
+ u->error = 1;
+ } else {
+ return UD_R_ES + (i & 7);
+ }
+ }
+ case T_NONE:
+ default: return UD_NONE;
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * decode_imm() - Decodes Immediate values.
+ * -----------------------------------------------------------------------------
+ */
+static void
+decode_imm(struct ud* u, unsigned int s, struct ud_operand *op)
+{
+ op->size = resolve_operand_size(u, s);
+ op->type = UD_OP_IMM;
+
+ switch (op->size) {
+ case 8: op->lval.sbyte = ud_inp_uint8(u); break;
+ case 16: op->lval.uword = ud_inp_uint16(u); break;
+ case 32: op->lval.udword = ud_inp_uint32(u); break;
+ case 64: op->lval.uqword = ud_inp_uint64(u); break;
+ default: return;
+ }
+}
+
+
+/*
+ * decode_modrm_reg
+ *
+ * Decodes reg field of mod/rm byte
+ *
+ */
+static void
+decode_modrm_reg(struct ud *u,
+ struct ud_operand *operand,
+ unsigned int type,
+ unsigned int size)
+{
+ uint8_t reg = (REX_R(u->pfx_rex) << 3) | MODRM_REG(modrm(u));
+ operand->type = UD_OP_REG;
+ operand->size = resolve_operand_size(u, size);
+
+ if (type == T_GPR) {
+ operand->base = decode_gpr(u, operand->size, reg);
+ } else {
+ operand->base = resolve_reg(u, type, reg);
+ }
+}
+
+
+/*
+ * decode_modrm_rm
+ *
+ * Decodes rm field of mod/rm byte
+ *
+ */
+static void
+decode_modrm_rm(struct ud *u,
+ struct ud_operand *op,
+ unsigned char type,
+ unsigned int size)
+
+{
+ unsigned char mod, rm, reg;
+
+ /* get mod, r/m and reg fields */
+ mod = MODRM_MOD(modrm(u));
+ rm = (REX_B(u->pfx_rex) << 3) | MODRM_RM(modrm(u));
+ reg = (REX_R(u->pfx_rex) << 3) | MODRM_REG(modrm(u));
+
+ op->size = resolve_operand_size(u, size);
+
+ /*
+ * If mod is 11b, then the modrm.rm specifies a register.
+ *
+ */
+ if (mod == 3) {
+ op->type = UD_OP_REG;
+ if (type == T_GPR) {
+ op->base = decode_gpr(u, op->size, rm);
+ } else {
+ op->base = resolve_reg(u, type, (REX_B(u->pfx_rex) << 3) | (rm & 7));
+ }
+ return;
+ }
+
+
+ /*
+ * !11 => Memory Address
+ */
+ op->type = UD_OP_MEM;
+
+ if (u->adr_mode == 64) {
+ op->base = UD_R_RAX + rm;
+ if (mod == 1) {
+ op->offset = 8;
+ } else if (mod == 2) {
+ op->offset = 32;
+ } else if (mod == 0 && (rm & 7) == 5) {
+ op->base = UD_R_RIP;
+ op->offset = 32;
+ } else {
+ op->offset = 0;
+ }
+ /*
+ * Scale-Index-Base (SIB)
+ */
+ if ((rm & 7) == 4) {
+ ud_inp_next(u);
+
+ op->scale = (1 << SIB_S(ud_inp_curr(u))) & ~1;
+ op->index = UD_R_RAX + (SIB_I(ud_inp_curr(u)) | (REX_X(u->pfx_rex) << 3));
+ op->base = UD_R_RAX + (SIB_B(ud_inp_curr(u)) | (REX_B(u->pfx_rex) << 3));
+
+ /* special conditions for base reference */
+ if (op->index == UD_R_RSP) {
+ op->index = UD_NONE;
+ op->scale = UD_NONE;
+ }
+
+ if (op->base == UD_R_RBP || op->base == UD_R_R13) {
+ if (mod == 0) {
+ op->base = UD_NONE;
+ }
+ if (mod == 1) {
+ op->offset = 8;
+ } else {
+ op->offset = 32;
+ }
+ }
+ }
+ } else if (u->adr_mode == 32) {
+ op->base = UD_R_EAX + rm;
+ if (mod == 1) {
+ op->offset = 8;
+ } else if (mod == 2) {
+ op->offset = 32;
+ } else if (mod == 0 && rm == 5) {
+ op->base = UD_NONE;
+ op->offset = 32;
+ } else {
+ op->offset = 0;
+ }
+
+ /* Scale-Index-Base (SIB) */
+ if ((rm & 7) == 4) {
+ ud_inp_next(u);
+
+ op->scale = (1 << SIB_S(ud_inp_curr(u))) & ~1;
+ op->index = UD_R_EAX + (SIB_I(ud_inp_curr(u)) | (REX_X(u->pfx_rex) << 3));
+ op->base = UD_R_EAX + (SIB_B(ud_inp_curr(u)) | (REX_B(u->pfx_rex) << 3));
+
+ if (op->index == UD_R_ESP) {
+ op->index = UD_NONE;
+ op->scale = UD_NONE;
+ }
+
+ /* special condition for base reference */
+ if (op->base == UD_R_EBP) {
+ if (mod == 0) {
+ op->base = UD_NONE;
+ }
+ if (mod == 1) {
+ op->offset = 8;
+ } else {
+ op->offset = 32;
+ }
+ }
+ }
+ } else {
+ const unsigned int bases[] = { UD_R_BX, UD_R_BX, UD_R_BP, UD_R_BP,
+ UD_R_SI, UD_R_DI, UD_R_BP, UD_R_BX };
+ const unsigned int indices[] = { UD_R_SI, UD_R_DI, UD_R_SI, UD_R_DI,
+ UD_NONE, UD_NONE, UD_NONE, UD_NONE };
+ op->base = bases[rm & 7];
+ op->index = indices[rm & 7];
+ if (mod == 0 && rm == 6) {
+ op->offset= 16;
+ op->base = UD_NONE;
+ } else if (mod == 1) {
+ op->offset = 8;
+ } else if (mod == 2) {
+ op->offset = 16;
+ }
+ }
+
+ /*
+ * extract offset, if any
+ */
+ switch (op->offset) {
+ case 8 : op->lval.ubyte = ud_inp_uint8(u); break;
+ case 16: op->lval.uword = ud_inp_uint16(u); break;
+ case 32: op->lval.udword = ud_inp_uint32(u); break;
+ case 64: op->lval.uqword = ud_inp_uint64(u); break;
+ default: break;
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * decode_o() - Decodes offset
+ * -----------------------------------------------------------------------------
+ */
+static void
+decode_o(struct ud* u, unsigned int s, struct ud_operand *op)
+{
+ switch (u->adr_mode) {
+ case 64:
+ op->offset = 64;
+ op->lval.uqword = ud_inp_uint64(u);
+ break;
+ case 32:
+ op->offset = 32;
+ op->lval.udword = ud_inp_uint32(u);
+ break;
+ case 16:
+ op->offset = 16;
+ op->lval.uword = ud_inp_uint16(u);
+ break;
+ default:
+ return;
+ }
+ op->type = UD_OP_MEM;
+ op->size = resolve_operand_size(u, s);
+}
+
+/* -----------------------------------------------------------------------------
+ * decode_operands() - Disassembles Operands.
+ * -----------------------------------------------------------------------------
+ */
+static int
+decode_operand(struct ud *u,
+ struct ud_operand *operand,
+ enum ud_operand_code type,
+ unsigned int size)
+{
+ switch (type) {
+ case OP_A :
+ decode_a(u, operand);
+ break;
+ case OP_MR:
+ if (MODRM_MOD(modrm(u)) == 3) {
+ decode_modrm_rm(u, operand, T_GPR,
+ size == SZ_DY ? SZ_MDQ : SZ_V);
+ } else if (size == SZ_WV) {
+ decode_modrm_rm( u, operand, T_GPR, SZ_W);
+ } else if (size == SZ_BV) {
+ decode_modrm_rm( u, operand, T_GPR, SZ_B);
+ } else if (size == SZ_DY) {
+ decode_modrm_rm( u, operand, T_GPR, SZ_D);
+ } else {
+ ASSERT(!"unexpected size");
+ }
+ break;
+ case OP_M:
+ if (MODRM_MOD(modrm(u)) == 3) {
+ u->error = 1;
+ }
+ /* intended fall through */
+ case OP_E:
+ decode_modrm_rm(u, operand, T_GPR, size);
+ break;
+ break;
+ case OP_G:
+ decode_modrm_reg(u, operand, T_GPR, size);
+ break;
+ case OP_I:
+ decode_imm(u, size, operand);
+ break;
+ case OP_I1:
+ operand->type = UD_OP_CONST;
+ operand->lval.udword = 1;
+ break;
+ case OP_PR:
+ if (MODRM_MOD(modrm(u)) != 3) {
+ u->error = 1;
+ }
+ decode_modrm_rm(u, operand, T_MMX, size);
+ break;
+ case OP_P:
+ decode_modrm_reg(u, operand, T_MMX, size);
+ break;
+ case OP_VR:
+ if (MODRM_MOD(modrm(u)) != 3) {
+ u->error = 1;
+ }
+ /* intended fall through */
+ case OP_W:
+ decode_modrm_rm(u, operand, T_XMM, size);
+ break;
+ case OP_V:
+ decode_modrm_reg(u, operand, T_XMM, size);
+ break;
+ case OP_S:
+ decode_modrm_reg(u, operand, T_SEG, size);
+ break;
+ case OP_AL:
+ case OP_CL:
+ case OP_DL:
+ case OP_BL:
+ case OP_AH:
+ case OP_CH:
+ case OP_DH:
+ case OP_BH:
+ operand->type = UD_OP_REG;
+ operand->base = UD_R_AL + (type - OP_AL);
+ operand->size = 8;
+ break;
+ case OP_DX:
+ operand->type = UD_OP_REG;
+ operand->base = UD_R_DX;
+ operand->size = 16;
+ break;
+ case OP_O:
+ decode_o(u, size, operand);
+ break;
+ case OP_rAXr8:
+ case OP_rCXr9:
+ case OP_rDXr10:
+ case OP_rBXr11:
+ case OP_rSPr12:
+ case OP_rBPr13:
+ case OP_rSIr14:
+ case OP_rDIr15:
+ case OP_rAX:
+ case OP_rCX:
+ case OP_rDX:
+ case OP_rBX:
+ case OP_rSP:
+ case OP_rBP:
+ case OP_rSI:
+ case OP_rDI:
+ operand->type = UD_OP_REG;
+ operand->base = resolve_gpr64(u, type, &operand->size);
+ break;
+ case OP_ALr8b:
+ case OP_CLr9b:
+ case OP_DLr10b:
+ case OP_BLr11b:
+ case OP_AHr12b:
+ case OP_CHr13b:
+ case OP_DHr14b:
+ case OP_BHr15b: {
+ ud_type_t gpr = (type - OP_ALr8b) + UD_R_AL
+ + (REX_B(u->pfx_rex) << 3);
+ if (UD_R_AH <= gpr && u->pfx_rex) {
+ gpr = gpr + 4;
+ }
+ operand->type = UD_OP_REG;
+ operand->base = gpr;
+ break;
+ }
+ case OP_eAX:
+ case OP_eCX:
+ case OP_eDX:
+ case OP_eBX:
+ case OP_eSP:
+ case OP_eBP:
+ case OP_eSI:
+ case OP_eDI:
+ operand->type = UD_OP_REG;
+ operand->base = resolve_gpr32(u, type);
+ operand->size = u->opr_mode == 16 ? 16 : 32;
+ break;
+ case OP_ES:
+ case OP_CS:
+ case OP_DS:
+ case OP_SS:
+ case OP_FS:
+ case OP_GS:
+ /* in 64bits mode, only fs and gs are allowed */
+ if (u->dis_mode == 64) {
+ if (type != OP_FS && type != OP_GS) {
+ u->error= 1;
+ }
+ }
+ operand->type = UD_OP_REG;
+ operand->base = (type - OP_ES) + UD_R_ES;
+ operand->size = 16;
+ break;
+ case OP_J :
+ decode_imm(u, size, operand);
+ operand->type = UD_OP_JIMM;
+ break ;
+ case OP_Q:
+ decode_modrm_rm(u, operand, T_MMX, size);
+ break;
+ case OP_R :
+ decode_modrm_rm(u, operand, T_GPR, size);
+ break;
+ case OP_C:
+ decode_modrm_reg(u, operand, T_CRG, size);
+ break;
+ case OP_D:
+ decode_modrm_reg(u, operand, T_DBG, size);
+ break;
+ case OP_I3 :
+ operand->type = UD_OP_CONST;
+ operand->lval.sbyte = 3;
+ break;
+ case OP_ST0:
+ case OP_ST1:
+ case OP_ST2:
+ case OP_ST3:
+ case OP_ST4:
+ case OP_ST5:
+ case OP_ST6:
+ case OP_ST7:
+ operand->type = UD_OP_REG;
+ operand->base = (type - OP_ST0) + UD_R_ST0;
+ operand->size = 0;
+ break;
+ case OP_AX:
+ operand->type = UD_OP_REG;
+ operand->base = UD_R_AX;
+ operand->size = 16;
+ break;
+ default :
+ operand->type = UD_NONE;
+ break;
+ }
+ return 0;
+}
+
+
+/*
+ * decode_operands
+ *
+ * Disassemble upto 3 operands of the current instruction being
+ * disassembled. By the end of the function, the operand fields
+ * of the ud structure will have been filled.
+ */
+static int
+decode_operands(struct ud* u)
+{
+ decode_operand(u, &u->operand[0],
+ u->itab_entry->operand1.type,
+ u->itab_entry->operand1.size);
+ decode_operand(u, &u->operand[1],
+ u->itab_entry->operand2.type,
+ u->itab_entry->operand2.size);
+ decode_operand(u, &u->operand[2],
+ u->itab_entry->operand3.type,
+ u->itab_entry->operand3.size);
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * clear_insn() - clear instruction structure
+ * -----------------------------------------------------------------------------
+ */
+static void
+clear_insn(register struct ud* u)
+{
+ u->error = 0;
+ u->pfx_seg = 0;
+ u->pfx_opr = 0;
+ u->pfx_adr = 0;
+ u->pfx_lock = 0;
+ u->pfx_repne = 0;
+ u->pfx_rep = 0;
+ u->pfx_repe = 0;
+ u->pfx_rex = 0;
+ u->pfx_insn = 0;
+ u->mnemonic = UD_Inone;
+ u->itab_entry = NULL;
+ u->have_modrm = 0;
+
+ memset( &u->operand[ 0 ], 0, sizeof( struct ud_operand ) );
+ memset( &u->operand[ 1 ], 0, sizeof( struct ud_operand ) );
+ memset( &u->operand[ 2 ], 0, sizeof( struct ud_operand ) );
+}
+
+static int
+resolve_mode( struct ud* u )
+{
+ /* if in error state, bail out */
+ if ( u->error ) return -1;
+
+ /* propagate prefix effects */
+ if ( u->dis_mode == 64 ) { /* set 64bit-mode flags */
+
+ /* Check validity of instruction m64 */
+ if ( P_INV64( u->itab_entry->prefix ) ) {
+ u->error = 1;
+ return -1;
+ }
+
+ /* effective rex prefix is the effective mask for the
+ * instruction hard-coded in the opcode map.
+ */
+ u->pfx_rex = ( u->pfx_rex & 0x40 ) |
+ ( u->pfx_rex & REX_PFX_MASK( u->itab_entry->prefix ) );
+
+ /* whether this instruction has a default operand size of
+ * 64bit, also hardcoded into the opcode map.
+ */
+ u->default64 = P_DEF64( u->itab_entry->prefix );
+ /* calculate effective operand size */
+ if ( REX_W( u->pfx_rex ) ) {
+ u->opr_mode = 64;
+ } else if ( u->pfx_opr ) {
+ u->opr_mode = 16;
+ } else {
+ /* unless the default opr size of instruction is 64,
+ * the effective operand size in the absence of rex.w
+ * prefix is 32.
+ */
+ u->opr_mode = ( u->default64 ) ? 64 : 32;
+ }
+
+ /* calculate effective address size */
+ u->adr_mode = (u->pfx_adr) ? 32 : 64;
+ } else if ( u->dis_mode == 32 ) { /* set 32bit-mode flags */
+ u->opr_mode = ( u->pfx_opr ) ? 16 : 32;
+ u->adr_mode = ( u->pfx_adr ) ? 16 : 32;
+ } else if ( u->dis_mode == 16 ) { /* set 16bit-mode flags */
+ u->opr_mode = ( u->pfx_opr ) ? 32 : 16;
+ u->adr_mode = ( u->pfx_adr ) ? 32 : 16;
+ }
+
+ /* These flags determine which operand to apply the operand size
+ * cast to.
+ */
+ u->c1 = ( P_C1( u->itab_entry->prefix ) ) ? 1 : 0;
+ u->c2 = ( P_C2( u->itab_entry->prefix ) ) ? 1 : 0;
+ u->c3 = ( P_C3( u->itab_entry->prefix ) ) ? 1 : 0;
+
+ /* set flags for implicit addressing */
+ u->implicit_addr = P_IMPADDR( u->itab_entry->prefix );
+
+ return 0;
+}
+
+static int gen_hex( struct ud *u )
+{
+ unsigned int i;
+ unsigned char *src_ptr = ud_inp_sess( u );
+ char* src_hex;
+
+ /* bail out if in error stat. */
+ if ( u->error ) return -1;
+ /* output buffer pointe */
+ src_hex = ( char* ) u->insn_hexcode;
+ /* for each byte used to decode instruction */
+ for ( i = 0; i < u->inp_ctr; ++i, ++src_ptr) {
+ sprintf( src_hex, "%02x", *src_ptr & 0xFF );
+ src_hex += 2;
+ }
+ return 0;
+}
+
+
+static inline int
+decode_insn(struct ud *u, uint16_t ptr)
+{
+ ASSERT((ptr & 0x8000) == 0);
+ u->itab_entry = &ud_itab[ ptr ];
+ u->mnemonic = u->itab_entry->mnemonic;
+ return (resolve_mode(u) == 0 &&
+ decode_operands(u) == 0 &&
+ resolve_mnemonic(u) == 0) ? 0 : -1;
+}
+
+
+/*
+ * decode_3dnow()
+ *
+ * Decoding 3dnow is a little tricky because of its strange opcode
+ * structure. The final opcode disambiguation depends on the last
+ * byte that comes after the operands have been decoded. Fortunately,
+ * all 3dnow instructions have the same set of operand types. So we
+ * go ahead and decode the instruction by picking an arbitrarily chosen
+ * valid entry in the table, decode the operands, and read the final
+ * byte to resolve the menmonic.
+ */
+static inline int
+decode_3dnow(struct ud* u)
+{
+ uint16_t ptr;
+ ASSERT(u->le->type == UD_TAB__OPC_3DNOW);
+ ASSERT(u->le->table[0xc] != 0);
+ decode_insn(u, u->le->table[0xc]);
+ ud_inp_next(u);
+ if (u->error) {
+ return -1;
+ }
+ ptr = u->le->table[ud_inp_curr(u)];
+ ASSERT((ptr & 0x8000) == 0);
+ u->mnemonic = ud_itab[ptr].mnemonic;
+ return 0;
+}
+
+
+static int
+decode_ssepfx(struct ud *u)
+{
+ uint8_t idx = ((u->pfx_insn & 0xf) + 1) / 2;
+ if (u->le->table[idx] == 0) {
+ idx = 0;
+ }
+ if (idx && u->le->table[idx] != 0) {
+ /*
+ * "Consume" the prefix as a part of the opcode, so it is no
+ * longer exported as an instruction prefix.
+ */
+ switch (u->pfx_insn) {
+ case 0xf2:
+ u->pfx_repne = 0;
+ break;
+ case 0xf3:
+ u->pfx_rep = 0;
+ u->pfx_repe = 0;
+ break;
+ case 0x66:
+ u->pfx_opr = 0;
+ break;
+ }
+ }
+ return decode_ext(u, u->le->table[idx]);
+}
+
+
+/*
+ * decode_ext()
+ *
+ * Decode opcode extensions (if any)
+ */
+static int
+decode_ext(struct ud *u, uint16_t ptr)
+{
+ uint8_t idx = 0;
+ if ((ptr & 0x8000) == 0) {
+ return decode_insn(u, ptr);
+ }
+ u->le = &ud_lookup_table_list[(~0x8000 & ptr)];
+ if (u->le->type == UD_TAB__OPC_3DNOW) {
+ return decode_3dnow(u);
+ }
+
+ switch (u->le->type) {
+ case UD_TAB__OPC_MOD:
+ /* !11 = 0, 11 = 1 */
+ idx = (MODRM_MOD(modrm(u)) + 1) / 4;
+ break;
+ /* disassembly mode/operand size/address size based tables.
+ * 16 = 0,, 32 = 1, 64 = 2
+ */
+ case UD_TAB__OPC_MODE:
+ idx = u->dis_mode / 32;
+ break;
+ case UD_TAB__OPC_OSIZE:
+ idx = eff_opr_mode(u->dis_mode, REX_W(u->pfx_rex), u->pfx_opr) / 32;
+ break;
+ case UD_TAB__OPC_ASIZE:
+ idx = eff_adr_mode(u->dis_mode, u->pfx_adr) / 32;
+ break;
+ case UD_TAB__OPC_X87:
+ idx = modrm(u) - 0xC0;
+ break;
+ case UD_TAB__OPC_VENDOR:
+ if (u->vendor == UD_VENDOR_ANY) {
+ /* choose a valid entry */
+ idx = (u->le->table[idx] != 0) ? 0 : 1;
+ } else if (u->vendor == UD_VENDOR_AMD) {
+ idx = 0;
+ } else {
+ idx = 1;
+ }
+ break;
+ case UD_TAB__OPC_RM:
+ idx = MODRM_RM(modrm(u));
+ break;
+ case UD_TAB__OPC_REG:
+ idx = MODRM_REG(modrm(u));
+ break;
+ case UD_TAB__OPC_SSE:
+ return decode_ssepfx(u);
+ default:
+ ASSERT(!"not reached");
+ break;
+ }
+
+ return decode_ext(u, u->le->table[idx]);
+}
+
+
+static inline int
+decode_opcode(struct ud *u)
+{
+ uint16_t ptr;
+ ASSERT(u->le->type == UD_TAB__OPC_TABLE);
+ ud_inp_next(u);
+ if (u->error) {
+ return -1;
+ }
+ ptr = u->le->table[ud_inp_curr(u)];
+ if (ptr & 0x8000) {
+ u->le = &ud_lookup_table_list[ptr & ~0x8000];
+ if (u->le->type == UD_TAB__OPC_TABLE) {
+ return decode_opcode(u);
+ }
+ }
+ return decode_ext(u, ptr);
+}
+
+
+/* =============================================================================
+ * ud_decode() - Instruction decoder. Returns the number of bytes decoded.
+ * =============================================================================
+ */
+unsigned int
+ud_decode(struct ud *u)
+{
+ ud_inp_start(u);
+ clear_insn(u);
+ u->le = &ud_lookup_table_list[0];
+ u->error = decode_prefixes(u) == -1 ||
+ decode_opcode(u) == -1 ||
+ u->error;
+ /* Handle decode error. */
+ if (u->error) {
+ /* clear out the decode data. */
+ clear_insn(u);
+ /* mark the sequence of bytes as invalid. */
+ u->itab_entry = & s_ie__invalid;
+ u->mnemonic = u->itab_entry->mnemonic;
+ }
+
+ /* maybe this stray segment override byte
+ * should be spewed out?
+ */
+ if ( !P_SEG( u->itab_entry->prefix ) &&
+ u->operand[0].type != UD_OP_MEM &&
+ u->operand[1].type != UD_OP_MEM )
+ u->pfx_seg = 0;
+
+ u->insn_offset = u->pc; /* set offset of instruction */
+ u->insn_fill = 0; /* set translation buffer index to 0 */
+ u->pc += u->inp_ctr; /* move program counter by bytes decoded */
+ gen_hex( u ); /* generate hex code */
+
+ /* return number of bytes disassembled. */
+ return u->inp_ctr;
+}
+
+/*
+vim: set ts=2 sw=2 expandtab
+*/
+
+#endif // USE(UDIS86)
diff --git a/Source/JavaScriptCore/disassembler/udis86/udis86_decode.h b/Source/JavaScriptCore/disassembler/udis86/udis86_decode.h
new file mode 100644
index 000000000..940ed5ad6
--- /dev/null
+++ b/Source/JavaScriptCore/disassembler/udis86/udis86_decode.h
@@ -0,0 +1,258 @@
+/* udis86 - libudis86/decode.h
+ *
+ * Copyright (c) 2002-2009 Vivek Thampi
+ * 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 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 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 A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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 UD_DECODE_H
+#define UD_DECODE_H
+
+#include "udis86_types.h"
+#include "udis86_itab.h"
+
+#define MAX_INSN_LENGTH 15
+
+/* register classes */
+#define T_NONE 0
+#define T_GPR 1
+#define T_MMX 2
+#define T_CRG 3
+#define T_DBG 4
+#define T_SEG 5
+#define T_XMM 6
+
+/* itab prefix bits */
+#define P_none ( 0 )
+#define P_cast ( 1 << 0 )
+#define P_CAST(n) ( ( n >> 0 ) & 1 )
+#define P_c1 ( 1 << 0 )
+#define P_C1(n) ( ( n >> 0 ) & 1 )
+#define P_rexb ( 1 << 1 )
+#define P_REXB(n) ( ( n >> 1 ) & 1 )
+#define P_depM ( 1 << 2 )
+#define P_DEPM(n) ( ( n >> 2 ) & 1 )
+#define P_c3 ( 1 << 3 )
+#define P_C3(n) ( ( n >> 3 ) & 1 )
+#define P_inv64 ( 1 << 4 )
+#define P_INV64(n) ( ( n >> 4 ) & 1 )
+#define P_rexw ( 1 << 5 )
+#define P_REXW(n) ( ( n >> 5 ) & 1 )
+#define P_c2 ( 1 << 6 )
+#define P_C2(n) ( ( n >> 6 ) & 1 )
+#define P_def64 ( 1 << 7 )
+#define P_DEF64(n) ( ( n >> 7 ) & 1 )
+#define P_rexr ( 1 << 8 )
+#define P_REXR(n) ( ( n >> 8 ) & 1 )
+#define P_oso ( 1 << 9 )
+#define P_OSO(n) ( ( n >> 9 ) & 1 )
+#define P_aso ( 1 << 10 )
+#define P_ASO(n) ( ( n >> 10 ) & 1 )
+#define P_rexx ( 1 << 11 )
+#define P_REXX(n) ( ( n >> 11 ) & 1 )
+#define P_ImpAddr ( 1 << 12 )
+#define P_IMPADDR(n) ( ( n >> 12 ) & 1 )
+#define P_seg ( 1 << 13 )
+#define P_SEG(n) ( ( n >> 13 ) & 1 )
+#define P_sext ( 1 << 14 )
+#define P_SEXT(n) ( ( n >> 14 ) & 1 )
+
+/* rex prefix bits */
+#define REX_W(r) ( ( 0xF & ( r ) ) >> 3 )
+#define REX_R(r) ( ( 0x7 & ( r ) ) >> 2 )
+#define REX_X(r) ( ( 0x3 & ( r ) ) >> 1 )
+#define REX_B(r) ( ( 0x1 & ( r ) ) >> 0 )
+#define REX_PFX_MASK(n) ( ( P_REXW(n) << 3 ) | \
+ ( P_REXR(n) << 2 ) | \
+ ( P_REXX(n) << 1 ) | \
+ ( P_REXB(n) << 0 ) )
+
+/* scable-index-base bits */
+#define SIB_S(b) ( ( b ) >> 6 )
+#define SIB_I(b) ( ( ( b ) >> 3 ) & 7 )
+#define SIB_B(b) ( ( b ) & 7 )
+
+/* modrm bits */
+#define MODRM_REG(b) ( ( ( b ) >> 3 ) & 7 )
+#define MODRM_NNN(b) ( ( ( b ) >> 3 ) & 7 )
+#define MODRM_MOD(b) ( ( ( b ) >> 6 ) & 3 )
+#define MODRM_RM(b) ( ( b ) & 7 )
+
+/* operand type constants -- order is important! */
+
+enum ud_operand_code {
+ OP_NONE,
+
+ OP_A, OP_E, OP_M, OP_G,
+ OP_I,
+
+ OP_AL, OP_CL, OP_DL, OP_BL,
+ OP_AH, OP_CH, OP_DH, OP_BH,
+
+ OP_ALr8b, OP_CLr9b, OP_DLr10b, OP_BLr11b,
+ OP_AHr12b, OP_CHr13b, OP_DHr14b, OP_BHr15b,
+
+ OP_AX, OP_CX, OP_DX, OP_BX,
+ OP_SI, OP_DI, OP_SP, OP_BP,
+
+ OP_rAX, OP_rCX, OP_rDX, OP_rBX,
+ OP_rSP, OP_rBP, OP_rSI, OP_rDI,
+
+ OP_rAXr8, OP_rCXr9, OP_rDXr10, OP_rBXr11,
+ OP_rSPr12, OP_rBPr13, OP_rSIr14, OP_rDIr15,
+
+ OP_eAX, OP_eCX, OP_eDX, OP_eBX,
+ OP_eSP, OP_eBP, OP_eSI, OP_eDI,
+
+ OP_ES, OP_CS, OP_SS, OP_DS,
+ OP_FS, OP_GS,
+
+ OP_ST0, OP_ST1, OP_ST2, OP_ST3,
+ OP_ST4, OP_ST5, OP_ST6, OP_ST7,
+
+ OP_J, OP_S, OP_O,
+ OP_I1, OP_I3,
+
+ OP_V, OP_W, OP_Q, OP_P,
+
+ OP_R, OP_C, OP_D, OP_VR, OP_PR,
+
+ OP_MR
+} UD_ATTR_PACKED;
+
+
+/* operand size constants */
+
+enum ud_operand_size {
+ SZ_NA = 0,
+ SZ_Z = 1,
+ SZ_V = 2,
+ SZ_P = 3,
+ SZ_WP = 4,
+ SZ_DP = 5,
+ SZ_MDQ = 6,
+ SZ_RDQ = 7,
+
+ /* the following values are used as is,
+ * and thus hard-coded. changing them
+ * will break internals
+ */
+ SZ_B = 8,
+ SZ_W = 16,
+ SZ_D = 32,
+ SZ_Q = 64,
+ SZ_T = 80,
+ SZ_O = 128,
+
+ SZ_WV = 17,
+ SZ_BV = 18,
+ SZ_DY = 19
+
+} UD_ATTR_PACKED;
+
+
+/* A single operand of an entry in the instruction table.
+ * (internal use only)
+ */
+struct ud_itab_entry_operand
+{
+ enum ud_operand_code type;
+ enum ud_operand_size size;
+};
+
+
+/* A single entry in an instruction table.
+ *(internal use only)
+ */
+struct ud_itab_entry
+{
+ enum ud_mnemonic_code mnemonic;
+ struct ud_itab_entry_operand operand1;
+ struct ud_itab_entry_operand operand2;
+ struct ud_itab_entry_operand operand3;
+ uint32_t prefix;
+};
+
+struct ud_lookup_table_list_entry {
+ const uint16_t *table;
+ enum ud_table_type type;
+ const char *meta;
+};
+
+
+static inline unsigned int sse_pfx_idx( const unsigned int pfx )
+{
+ /* 00 = 0
+ * f2 = 1
+ * f3 = 2
+ * 66 = 3
+ */
+ return ( ( pfx & 0xf ) + 1 ) / 2;
+}
+
+static inline unsigned int mode_idx( const unsigned int mode )
+{
+ /* 16 = 0
+ * 32 = 1
+ * 64 = 2
+ */
+ return ( mode / 32 );
+}
+
+static inline unsigned int modrm_mod_idx( const unsigned int mod )
+{
+ /* !11 = 0
+ * 11 = 1
+ */
+ return ( mod + 1 ) / 4;
+}
+
+static inline unsigned int vendor_idx( const unsigned int vendor )
+{
+ switch ( vendor ) {
+ case UD_VENDOR_AMD: return 0;
+ case UD_VENDOR_INTEL: return 1;
+ case UD_VENDOR_ANY: return 2;
+ default: return 2;
+ }
+}
+
+static inline unsigned int is_group_ptr( uint16_t ptr )
+{
+ return ( 0x8000 & ptr );
+}
+
+static inline unsigned int group_idx( uint16_t ptr )
+{
+ return ( ~0x8000 & ptr );
+}
+
+
+extern struct ud_itab_entry ud_itab[];
+extern struct ud_lookup_table_list_entry ud_lookup_table_list[];
+
+#endif /* UD_DECODE_H */
+
+/* vim:cindent
+ * vim:expandtab
+ * vim:ts=4
+ * vim:sw=4
+ */
diff --git a/Source/JavaScriptCore/disassembler/udis86/udis86_extern.h b/Source/JavaScriptCore/disassembler/udis86/udis86_extern.h
new file mode 100644
index 000000000..8e87721e8
--- /dev/null
+++ b/Source/JavaScriptCore/disassembler/udis86/udis86_extern.h
@@ -0,0 +1,88 @@
+/* udis86 - libudis86/extern.h
+ *
+ * Copyright (c) 2002-2009 Vivek Thampi
+ * 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 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 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 A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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 UD_EXTERN_H
+#define UD_EXTERN_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "udis86_types.h"
+
+/* ============================= PUBLIC API ================================= */
+
+extern void ud_init(struct ud*);
+
+extern void ud_set_mode(struct ud*, uint8_t);
+
+extern void ud_set_pc(struct ud*, uint64_t);
+
+extern void ud_set_input_hook(struct ud*, int (*)(struct ud*));
+
+extern void ud_set_input_buffer(struct ud*, uint8_t*, size_t);
+
+#ifndef __UD_STANDALONE__
+extern void ud_set_input_file(struct ud*, FILE*);
+#endif /* __UD_STANDALONE__ */
+
+extern void ud_set_vendor(struct ud*, unsigned);
+
+extern void ud_set_syntax(struct ud*, void (*)(struct ud*));
+
+extern void ud_input_skip(struct ud*, size_t);
+
+extern int ud_input_end(struct ud*);
+
+extern unsigned int ud_decode(struct ud*);
+
+extern unsigned int ud_disassemble(struct ud*);
+
+extern void ud_translate_intel(struct ud*);
+
+extern void ud_translate_att(struct ud*);
+
+extern char* ud_insn_asm(struct ud* u);
+
+extern uint8_t* ud_insn_ptr(struct ud* u);
+
+extern uint64_t ud_insn_off(struct ud*);
+
+extern char* ud_insn_hex(struct ud*);
+
+extern unsigned int ud_insn_len(struct ud* u);
+
+extern const char* ud_lookup_mnemonic(enum ud_mnemonic_code c);
+
+extern void ud_set_user_opaque_data(struct ud*, void*);
+
+extern void *ud_get_user_opaque_data(struct ud*);
+
+/* ========================================================================== */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/Source/JavaScriptCore/disassembler/udis86/udis86_input.c b/Source/JavaScriptCore/disassembler/udis86/udis86_input.c
new file mode 100644
index 000000000..76c6cccf3
--- /dev/null
+++ b/Source/JavaScriptCore/disassembler/udis86/udis86_input.c
@@ -0,0 +1,263 @@
+/* udis86 - libudis86/input.c
+ *
+ * Copyright (c) 2002-2009 Vivek Thampi
+ * 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 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 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 A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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 <wtf/Platform.h>
+
+#if USE(UDIS86)
+
+#include "udis86_extern.h"
+#include "udis86_types.h"
+#include "udis86_input.h"
+
+/* -----------------------------------------------------------------------------
+ * inp_buff_hook() - Hook for buffered inputs.
+ * -----------------------------------------------------------------------------
+ */
+static int
+inp_buff_hook(struct ud* u)
+{
+ if (u->inp_buff < u->inp_buff_end)
+ return *u->inp_buff++;
+ else return -1;
+}
+
+#ifndef __UD_STANDALONE__
+/* -----------------------------------------------------------------------------
+ * inp_file_hook() - Hook for FILE inputs.
+ * -----------------------------------------------------------------------------
+ */
+static int
+inp_file_hook(struct ud* u)
+{
+ return fgetc(u->inp_file);
+}
+#endif /* __UD_STANDALONE__*/
+
+/* =============================================================================
+ * ud_inp_set_hook() - Sets input hook.
+ * =============================================================================
+ */
+extern void
+ud_set_input_hook(register struct ud* u, int (*hook)(struct ud*))
+{
+ u->inp_hook = hook;
+ ud_inp_init(u);
+}
+
+extern void
+ud_set_user_opaque_data( struct ud * u, void * opaque )
+{
+ u->user_opaque_data = opaque;
+}
+
+extern void *
+ud_get_user_opaque_data( struct ud * u )
+{
+ return u->user_opaque_data;
+}
+
+/* =============================================================================
+ * ud_inp_set_buffer() - Set buffer as input.
+ * =============================================================================
+ */
+extern void
+ud_set_input_buffer(register struct ud* u, uint8_t* buf, size_t len)
+{
+ u->inp_hook = inp_buff_hook;
+ u->inp_buff = buf;
+ u->inp_buff_end = buf + len;
+ ud_inp_init(u);
+}
+
+#ifndef __UD_STANDALONE__
+/* =============================================================================
+ * ud_input_set_file() - Set buffer as input.
+ * =============================================================================
+ */
+extern void
+ud_set_input_file(register struct ud* u, FILE* f)
+{
+ u->inp_hook = inp_file_hook;
+ u->inp_file = f;
+ ud_inp_init(u);
+}
+#endif /* __UD_STANDALONE__ */
+
+/* =============================================================================
+ * ud_input_skip() - Skip n input bytes.
+ * =============================================================================
+ */
+extern void
+ud_input_skip(struct ud* u, size_t n)
+{
+ while (n--) {
+ u->inp_hook(u);
+ }
+}
+
+/* =============================================================================
+ * ud_input_end() - Test for end of input.
+ * =============================================================================
+ */
+extern int
+ud_input_end(struct ud* u)
+{
+ return (u->inp_curr == u->inp_fill) && u->inp_end;
+}
+
+/* -----------------------------------------------------------------------------
+ * ud_inp_next() - Loads and returns the next byte from input.
+ *
+ * inp_curr and inp_fill are pointers to the cache. The program is written based
+ * on the property that they are 8-bits in size, and will eventually wrap around
+ * forming a circular buffer. So, the size of the cache is 256 in size, kind of
+ * unnecessary yet optimized.
+ *
+ * A buffer inp_sess stores the bytes disassembled for a single session.
+ * -----------------------------------------------------------------------------
+ */
+extern uint8_t ud_inp_next(struct ud* u)
+{
+ int c = -1;
+ /* if current pointer is not upto the fill point in the
+ * input cache.
+ */
+ if ( u->inp_curr != u->inp_fill ) {
+ c = u->inp_cache[ ++u->inp_curr ];
+ /* if !end-of-input, call the input hook and get a byte */
+ } else if ( u->inp_end || ( c = u->inp_hook( u ) ) == -1 ) {
+ /* end-of-input, mark it as an error, since the decoder,
+ * expected a byte more.
+ */
+ u->error = 1;
+ /* flag end of input */
+ u->inp_end = 1;
+ return 0;
+ } else {
+ /* increment pointers, we have a new byte. */
+ u->inp_curr = ++u->inp_fill;
+ /* add the byte to the cache */
+ u->inp_cache[ u->inp_fill ] = c;
+ }
+ /* record bytes input per decode-session. */
+ u->inp_sess[ u->inp_ctr++ ] = c;
+ /* return byte */
+ return ( uint8_t ) c;
+}
+
+/* -----------------------------------------------------------------------------
+ * ud_inp_back() - Move back a single byte in the stream.
+ * -----------------------------------------------------------------------------
+ */
+extern void
+ud_inp_back(struct ud* u)
+{
+ if ( u->inp_ctr > 0 ) {
+ --u->inp_curr;
+ --u->inp_ctr;
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * ud_inp_peek() - Peek into the next byte in source.
+ * -----------------------------------------------------------------------------
+ */
+extern uint8_t
+ud_inp_peek(struct ud* u)
+{
+ uint8_t r = ud_inp_next(u);
+ if ( !u->error ) ud_inp_back(u); /* Don't backup if there was an error */
+ return r;
+}
+
+/* -----------------------------------------------------------------------------
+ * ud_inp_move() - Move ahead n input bytes.
+ * -----------------------------------------------------------------------------
+ */
+extern void
+ud_inp_move(struct ud* u, size_t n)
+{
+ while (n--)
+ ud_inp_next(u);
+}
+
+/*------------------------------------------------------------------------------
+ * ud_inp_uintN() - return uintN from source.
+ *------------------------------------------------------------------------------
+ */
+extern uint8_t
+ud_inp_uint8(struct ud* u)
+{
+ return ud_inp_next(u);
+}
+
+extern uint16_t
+ud_inp_uint16(struct ud* u)
+{
+ uint16_t r, ret;
+
+ ret = ud_inp_next(u);
+ r = ud_inp_next(u);
+ return ret | (r << 8);
+}
+
+extern uint32_t
+ud_inp_uint32(struct ud* u)
+{
+ uint32_t r, ret;
+
+ ret = ud_inp_next(u);
+ r = ud_inp_next(u);
+ ret = ret | (r << 8);
+ r = ud_inp_next(u);
+ ret = ret | (r << 16);
+ r = ud_inp_next(u);
+ return ret | (r << 24);
+}
+
+extern uint64_t
+ud_inp_uint64(struct ud* u)
+{
+ uint64_t r, ret;
+
+ ret = ud_inp_next(u);
+ r = ud_inp_next(u);
+ ret = ret | (r << 8);
+ r = ud_inp_next(u);
+ ret = ret | (r << 16);
+ r = ud_inp_next(u);
+ ret = ret | (r << 24);
+ r = ud_inp_next(u);
+ ret = ret | (r << 32);
+ r = ud_inp_next(u);
+ ret = ret | (r << 40);
+ r = ud_inp_next(u);
+ ret = ret | (r << 48);
+ r = ud_inp_next(u);
+ return ret | (r << 56);
+}
+
+#endif // USE(UDIS86)
diff --git a/Source/JavaScriptCore/disassembler/udis86/udis86_input.h b/Source/JavaScriptCore/disassembler/udis86/udis86_input.h
new file mode 100644
index 000000000..96865a88b
--- /dev/null
+++ b/Source/JavaScriptCore/disassembler/udis86/udis86_input.h
@@ -0,0 +1,67 @@
+/* udis86 - libudis86/input.h
+ *
+ * Copyright (c) 2002-2009 Vivek Thampi
+ * 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 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 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 A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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 UD_INPUT_H
+#define UD_INPUT_H
+
+#include "udis86_types.h"
+
+uint8_t ud_inp_next(struct ud*);
+uint8_t ud_inp_peek(struct ud*);
+uint8_t ud_inp_uint8(struct ud*);
+uint16_t ud_inp_uint16(struct ud*);
+uint32_t ud_inp_uint32(struct ud*);
+uint64_t ud_inp_uint64(struct ud*);
+void ud_inp_move(struct ud*, size_t);
+void ud_inp_back(struct ud*);
+
+/* ud_inp_init() - Initializes the input system. */
+#define ud_inp_init(u) \
+do { \
+ u->inp_curr = 0; \
+ u->inp_fill = 0; \
+ u->inp_ctr = 0; \
+ u->inp_end = 0; \
+} while (0)
+
+/* ud_inp_start() - Should be called before each de-code operation. */
+#define ud_inp_start(u) u->inp_ctr = 0
+
+/* ud_inp_back() - Resets the current pointer to its position before the current
+ * instruction disassembly was started.
+ */
+#define ud_inp_reset(u) \
+do { \
+ u->inp_curr -= u->inp_ctr; \
+ u->inp_ctr = 0; \
+} while (0)
+
+/* ud_inp_sess() - Returns the pointer to current session. */
+#define ud_inp_sess(u) (u->inp_sess)
+
+/* inp_cur() - Returns the current input byte. */
+#define ud_inp_curr(u) ((u)->inp_cache[(u)->inp_curr])
+
+#endif
diff --git a/Source/JavaScriptCore/disassembler/udis86/udis86_itab_holder.c b/Source/JavaScriptCore/disassembler/udis86/udis86_itab_holder.c
new file mode 100644
index 000000000..d5d8726d6
--- /dev/null
+++ b/Source/JavaScriptCore/disassembler/udis86/udis86_itab_holder.c
@@ -0,0 +1,34 @@
+/*
+ * 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 <wtf/Platform.h>
+
+#if USE(UDIS86)
+
+#include "udis86_itab.c"
+
+#endif
+
diff --git a/Source/JavaScriptCore/disassembler/udis86/udis86_syn-att.c b/Source/JavaScriptCore/disassembler/udis86/udis86_syn-att.c
new file mode 100644
index 000000000..132d6ff84
--- /dev/null
+++ b/Source/JavaScriptCore/disassembler/udis86/udis86_syn-att.c
@@ -0,0 +1,253 @@
+/* udis86 - libudis86/syn-att.c
+ *
+ * Copyright (c) 2002-2009 Vivek Thampi
+ * 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 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 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 A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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 <wtf/Platform.h>
+
+#if USE(UDIS86)
+
+#include "udis86_types.h"
+#include "udis86_extern.h"
+#include "udis86_decode.h"
+#include "udis86_itab.h"
+#include "udis86_syn.h"
+
+/* -----------------------------------------------------------------------------
+ * opr_cast() - Prints an operand cast.
+ * -----------------------------------------------------------------------------
+ */
+static void
+opr_cast(struct ud* u, struct ud_operand* op)
+{
+ switch(op->size) {
+ case 16 : case 32 :
+ mkasm(u, "*"); break;
+ default: break;
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * gen_operand() - Generates assembly output for each operand.
+ * -----------------------------------------------------------------------------
+ */
+static void
+gen_operand(struct ud* u, struct ud_operand* op)
+{
+ switch(op->type) {
+ case UD_OP_REG:
+ mkasm(u, "%%%s", ud_reg_tab[op->base - UD_R_AL]);
+ break;
+
+ case UD_OP_MEM:
+ if (u->br_far) opr_cast(u, op);
+ if (u->pfx_seg)
+ mkasm(u, "%%%s:", ud_reg_tab[u->pfx_seg - UD_R_AL]);
+ if (op->offset == 8) {
+ if (op->lval.sbyte < 0)
+ mkasm(u, "-0x%x", (-op->lval.sbyte) & 0xff);
+ else mkasm(u, "0x%x", op->lval.sbyte);
+ }
+ else if (op->offset == 16)
+ mkasm(u, "0x%x", op->lval.uword);
+ else if (op->offset == 32)
+ mkasm(u, "0x%lx", (unsigned long)op->lval.udword);
+ else if (op->offset == 64)
+ mkasm(u, "0x" FMT64 "x", op->lval.uqword);
+
+ if (op->base)
+ mkasm(u, "(%%%s", ud_reg_tab[op->base - UD_R_AL]);
+ if (op->index) {
+ if (op->base)
+ mkasm(u, ",");
+ else mkasm(u, "(");
+ mkasm(u, "%%%s", ud_reg_tab[op->index - UD_R_AL]);
+ }
+ if (op->scale)
+ mkasm(u, ",%d", op->scale);
+ if (op->base || op->index)
+ mkasm(u, ")");
+ break;
+
+ case UD_OP_IMM: {
+ int64_t imm = 0;
+ uint64_t sext_mask = 0xffffffffffffffffull;
+ unsigned sext_size = op->size;
+
+ switch (op->size) {
+ case 8: imm = op->lval.sbyte; break;
+ case 16: imm = op->lval.sword; break;
+ case 32: imm = op->lval.sdword; break;
+ case 64: imm = op->lval.sqword; break;
+ }
+ if ( P_SEXT( u->itab_entry->prefix ) ) {
+ sext_size = u->operand[ 0 ].size;
+ if ( u->mnemonic == UD_Ipush )
+ /* push sign-extends to operand size */
+ sext_size = u->opr_mode;
+ }
+ if ( sext_size < 64 )
+ sext_mask = ( 1ull << sext_size ) - 1;
+ mkasm( u, "0x" FMT64 "x", imm & sext_mask );
+
+ break;
+ }
+
+ case UD_OP_JIMM:
+ switch (op->size) {
+ case 8:
+ mkasm(u, "0x" FMT64 "x", u->pc + op->lval.sbyte);
+ break;
+ case 16:
+ mkasm(u, "0x" FMT64 "x", (u->pc + op->lval.sword) & 0xffff );
+ break;
+ case 32:
+ if (u->dis_mode == 32)
+ mkasm(u, "0x" FMT64 "x", (u->pc + op->lval.sdword) & 0xffffffff);
+ else
+ mkasm(u, "0x" FMT64 "x", u->pc + op->lval.sdword);
+ break;
+ default:break;
+ }
+ break;
+
+ case UD_OP_PTR:
+ switch (op->size) {
+ case 32:
+ mkasm(u, "$0x%x, $0x%x", op->lval.ptr.seg,
+ op->lval.ptr.off & 0xFFFF);
+ break;
+ case 48:
+ mkasm(u, "$0x%x, $0x%lx", op->lval.ptr.seg,
+ (unsigned long)op->lval.ptr.off);
+ break;
+ }
+ break;
+
+ default: return;
+ }
+}
+
+/* =============================================================================
+ * translates to AT&T syntax
+ * =============================================================================
+ */
+extern void
+ud_translate_att(struct ud *u)
+{
+ int size = 0;
+
+ /* check if P_OSO prefix is used */
+ if (! P_OSO(u->itab_entry->prefix) && u->pfx_opr) {
+ switch (u->dis_mode) {
+ case 16:
+ mkasm(u, "o32 ");
+ break;
+ case 32:
+ case 64:
+ mkasm(u, "o16 ");
+ break;
+ }
+ }
+
+ /* check if P_ASO prefix was used */
+ if (! P_ASO(u->itab_entry->prefix) && u->pfx_adr) {
+ switch (u->dis_mode) {
+ case 16:
+ mkasm(u, "a32 ");
+ break;
+ case 32:
+ mkasm(u, "a16 ");
+ break;
+ case 64:
+ mkasm(u, "a32 ");
+ break;
+ }
+ }
+
+ if (u->pfx_lock)
+ mkasm(u, "lock ");
+ if (u->pfx_rep)
+ mkasm(u, "rep ");
+ if (u->pfx_repne)
+ mkasm(u, "repne ");
+
+ /* special instructions */
+ switch (u->mnemonic) {
+ case UD_Iretf:
+ mkasm(u, "lret ");
+ break;
+ case UD_Idb:
+ mkasm(u, ".byte 0x%x", u->operand[0].lval.ubyte);
+ return;
+ case UD_Ijmp:
+ case UD_Icall:
+ if (u->br_far) mkasm(u, "l");
+ mkasm(u, "%s", ud_lookup_mnemonic(u->mnemonic));
+ break;
+ case UD_Ibound:
+ case UD_Ienter:
+ if (u->operand[0].type != UD_NONE)
+ gen_operand(u, &u->operand[0]);
+ if (u->operand[1].type != UD_NONE) {
+ mkasm(u, ",");
+ gen_operand(u, &u->operand[1]);
+ }
+ return;
+ default:
+ mkasm(u, "%s", ud_lookup_mnemonic(u->mnemonic));
+ }
+
+ if (u->c1)
+ size = u->operand[0].size;
+ else if (u->c2)
+ size = u->operand[1].size;
+ else if (u->c3)
+ size = u->operand[2].size;
+
+ if (size == 8)
+ mkasm(u, "b");
+ else if (size == 16)
+ mkasm(u, "w");
+ else if (size == 64)
+ mkasm(u, "q");
+
+ mkasm(u, " ");
+
+ if (u->operand[2].type != UD_NONE) {
+ gen_operand(u, &u->operand[2]);
+ mkasm(u, ", ");
+ }
+
+ if (u->operand[1].type != UD_NONE) {
+ gen_operand(u, &u->operand[1]);
+ mkasm(u, ", ");
+ }
+
+ if (u->operand[0].type != UD_NONE)
+ gen_operand(u, &u->operand[0]);
+}
+
+#endif // USE(UDIS86)
+
diff --git a/Source/JavaScriptCore/disassembler/udis86/udis86_syn-intel.c b/Source/JavaScriptCore/disassembler/udis86/udis86_syn-intel.c
new file mode 100644
index 000000000..d250bd449
--- /dev/null
+++ b/Source/JavaScriptCore/disassembler/udis86/udis86_syn-intel.c
@@ -0,0 +1,279 @@
+/* udis86 - libudis86/syn-intel.c
+ *
+ * Copyright (c) 2002-2009 Vivek Thampi
+ * 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 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 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 A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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 <wtf/Platform.h>
+
+#if USE(UDIS86)
+
+#include "udis86_types.h"
+#include "udis86_extern.h"
+#include "udis86_decode.h"
+#include "udis86_itab.h"
+#include "udis86_syn.h"
+
+/* -----------------------------------------------------------------------------
+ * opr_cast() - Prints an operand cast.
+ * -----------------------------------------------------------------------------
+ */
+static void
+opr_cast(struct ud* u, struct ud_operand* op)
+{
+ switch(op->size) {
+ case 8: mkasm(u, "byte " ); break;
+ case 16: mkasm(u, "word " ); break;
+ case 32: mkasm(u, "dword "); break;
+ case 64: mkasm(u, "qword "); break;
+ case 80: mkasm(u, "tword "); break;
+ default: break;
+ }
+ if (u->br_far)
+ mkasm(u, "far ");
+}
+
+/* -----------------------------------------------------------------------------
+ * gen_operand() - Generates assembly output for each operand.
+ * -----------------------------------------------------------------------------
+ */
+static void gen_operand(struct ud* u, struct ud_operand* op, int syn_cast)
+{
+ switch(op->type) {
+ case UD_OP_REG:
+ mkasm(u, "%s", ud_reg_tab[op->base - UD_R_AL]);
+ break;
+
+ case UD_OP_MEM: {
+
+ int op_f = 0;
+
+ if (syn_cast)
+ opr_cast(u, op);
+
+ mkasm(u, "[");
+
+ if (u->pfx_seg)
+ mkasm(u, "%s:", ud_reg_tab[u->pfx_seg - UD_R_AL]);
+
+ if (op->base) {
+ mkasm(u, "%s", ud_reg_tab[op->base - UD_R_AL]);
+ op_f = 1;
+ }
+
+ if (op->index) {
+ if (op_f)
+ mkasm(u, "+");
+ mkasm(u, "%s", ud_reg_tab[op->index - UD_R_AL]);
+ op_f = 1;
+ }
+
+ if (op->scale)
+ mkasm(u, "*%d", op->scale);
+
+ if (op->offset == 8) {
+ if (op->lval.sbyte < 0)
+ mkasm(u, "-0x%x", -op->lval.sbyte);
+ else mkasm(u, "%s0x%x", (op_f) ? "+" : "", op->lval.sbyte);
+ }
+ else if (op->offset == 16)
+ mkasm(u, "%s0x%x", (op_f) ? "+" : "", op->lval.uword);
+ else if (op->offset == 32) {
+ if (u->adr_mode == 64) {
+ if (op->lval.sdword < 0)
+ mkasm(u, "-0x%x", -op->lval.sdword);
+ else mkasm(u, "%s0x%x", (op_f) ? "+" : "", op->lval.sdword);
+ }
+ else mkasm(u, "%s0x%lx", (op_f) ? "+" : "", (unsigned long)op->lval.udword);
+ }
+ else if (op->offset == 64)
+ mkasm(u, "%s0x" FMT64 "x", (op_f) ? "+" : "", op->lval.uqword);
+
+ mkasm(u, "]");
+ break;
+ }
+
+ case UD_OP_IMM: {
+ int64_t imm = 0;
+ uint64_t sext_mask = 0xffffffffffffffffull;
+ unsigned sext_size = op->size;
+
+ if (syn_cast)
+ opr_cast(u, op);
+ switch (op->size) {
+ case 8: imm = op->lval.sbyte; break;
+ case 16: imm = op->lval.sword; break;
+ case 32: imm = op->lval.sdword; break;
+ case 64: imm = op->lval.sqword; break;
+ }
+ if ( P_SEXT( u->itab_entry->prefix ) ) {
+ sext_size = u->operand[ 0 ].size;
+ if ( u->mnemonic == UD_Ipush )
+ /* push sign-extends to operand size */
+ sext_size = u->opr_mode;
+ }
+ if ( sext_size < 64 )
+ sext_mask = ( 1ull << sext_size ) - 1;
+ mkasm( u, "0x" FMT64 "x", imm & sext_mask );
+
+ break;
+ }
+
+
+ case UD_OP_JIMM:
+ if (syn_cast) opr_cast(u, op);
+ switch (op->size) {
+ case 8:
+ mkasm(u, "0x" FMT64 "x", u->pc + op->lval.sbyte);
+ break;
+ case 16:
+ mkasm(u, "0x" FMT64 "x", ( u->pc + op->lval.sword ) & 0xffff );
+ break;
+ case 32:
+ mkasm(u, "0x" FMT64 "x", ( u->pc + op->lval.sdword ) & 0xfffffffful );
+ break;
+ default:break;
+ }
+ break;
+
+ case UD_OP_PTR:
+ switch (op->size) {
+ case 32:
+ mkasm(u, "word 0x%x:0x%x", op->lval.ptr.seg,
+ op->lval.ptr.off & 0xFFFF);
+ break;
+ case 48:
+ mkasm(u, "dword 0x%x:0x%lx", op->lval.ptr.seg,
+ (unsigned long)op->lval.ptr.off);
+ break;
+ }
+ break;
+
+ case UD_OP_CONST:
+ if (syn_cast) opr_cast(u, op);
+ mkasm(u, "%d", op->lval.udword);
+ break;
+
+ default: return;
+ }
+}
+
+/* =============================================================================
+ * translates to intel syntax
+ * =============================================================================
+ */
+extern void ud_translate_intel(struct ud* u)
+{
+ /* -- prefixes -- */
+
+ /* check if P_OSO prefix is used */
+ if (! P_OSO(u->itab_entry->prefix) && u->pfx_opr) {
+ switch (u->dis_mode) {
+ case 16:
+ mkasm(u, "o32 ");
+ break;
+ case 32:
+ case 64:
+ mkasm(u, "o16 ");
+ break;
+ }
+ }
+
+ /* check if P_ASO prefix was used */
+ if (! P_ASO(u->itab_entry->prefix) && u->pfx_adr) {
+ switch (u->dis_mode) {
+ case 16:
+ mkasm(u, "a32 ");
+ break;
+ case 32:
+ mkasm(u, "a16 ");
+ break;
+ case 64:
+ mkasm(u, "a32 ");
+ break;
+ }
+ }
+
+ if ( u->pfx_seg &&
+ u->operand[0].type != UD_OP_MEM &&
+ u->operand[1].type != UD_OP_MEM ) {
+ mkasm(u, "%s ", ud_reg_tab[u->pfx_seg - UD_R_AL]);
+ }
+ if (u->pfx_lock)
+ mkasm(u, "lock ");
+ if (u->pfx_rep)
+ mkasm(u, "rep ");
+ if (u->pfx_repne)
+ mkasm(u, "repne ");
+
+ /* print the instruction mnemonic */
+ mkasm(u, "%s ", ud_lookup_mnemonic(u->mnemonic));
+
+ /* operand 1 */
+ if (u->operand[0].type != UD_NONE) {
+ int cast = 0;
+ if ( u->operand[0].type == UD_OP_IMM &&
+ u->operand[1].type == UD_NONE )
+ cast = u->c1;
+ if ( u->operand[0].type == UD_OP_MEM ) {
+ cast = u->c1;
+ if ( u->operand[1].type == UD_OP_IMM ||
+ u->operand[1].type == UD_OP_CONST )
+ cast = 1;
+ if ( u->operand[1].type == UD_NONE )
+ cast = 1;
+ if ( ( u->operand[0].size != u->operand[1].size ) && u->operand[1].size )
+ cast = 1;
+ } else if ( u->operand[ 0 ].type == UD_OP_JIMM ) {
+ if ( u->operand[ 0 ].size > 8 ) cast = 1;
+ }
+ gen_operand(u, &u->operand[0], cast);
+ }
+ /* operand 2 */
+ if (u->operand[1].type != UD_NONE) {
+ int cast = 0;
+ mkasm(u, ", ");
+ if ( u->operand[1].type == UD_OP_MEM ) {
+ cast = u->c1;
+
+ if ( u->operand[0].type != UD_OP_REG )
+ cast = 1;
+ if ( u->operand[0].size != u->operand[1].size && u->operand[1].size )
+ cast = 1;
+ if ( u->operand[0].type == UD_OP_REG &&
+ u->operand[0].base >= UD_R_ES &&
+ u->operand[0].base <= UD_R_GS )
+ cast = 0;
+ }
+ gen_operand(u, &u->operand[1], cast );
+ }
+
+ /* operand 3 */
+ if (u->operand[2].type != UD_NONE) {
+ mkasm(u, ", ");
+ gen_operand(u, &u->operand[2], u->c3);
+ }
+}
+
+#endif // USE(UDIS86)
+
diff --git a/Source/JavaScriptCore/disassembler/udis86/udis86_syn.c b/Source/JavaScriptCore/disassembler/udis86/udis86_syn.c
new file mode 100644
index 000000000..80391b4a0
--- /dev/null
+++ b/Source/JavaScriptCore/disassembler/udis86/udis86_syn.c
@@ -0,0 +1,87 @@
+/* udis86 - libudis86/syn.c
+ *
+ * Copyright (c) 2002-2009 Vivek Thampi
+ * 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 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 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 A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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 <wtf/Platform.h>
+
+#if USE(UDIS86)
+
+/* -----------------------------------------------------------------------------
+ * Intel Register Table - Order Matters (types.h)!
+ * -----------------------------------------------------------------------------
+ */
+const char* ud_reg_tab[] =
+{
+ "al", "cl", "dl", "bl",
+ "ah", "ch", "dh", "bh",
+ "spl", "bpl", "sil", "dil",
+ "r8b", "r9b", "r10b", "r11b",
+ "r12b", "r13b", "r14b", "r15b",
+
+ "ax", "cx", "dx", "bx",
+ "sp", "bp", "si", "di",
+ "r8w", "r9w", "r10w", "r11w",
+ "r12w", "r13W" , "r14w", "r15w",
+
+ "eax", "ecx", "edx", "ebx",
+ "esp", "ebp", "esi", "edi",
+ "r8d", "r9d", "r10d", "r11d",
+ "r12d", "r13d", "r14d", "r15d",
+
+ "rax", "rcx", "rdx", "rbx",
+ "rsp", "rbp", "rsi", "rdi",
+ "r8", "r9", "r10", "r11",
+ "r12", "r13", "r14", "r15",
+
+ "es", "cs", "ss", "ds",
+ "fs", "gs",
+
+ "cr0", "cr1", "cr2", "cr3",
+ "cr4", "cr5", "cr6", "cr7",
+ "cr8", "cr9", "cr10", "cr11",
+ "cr12", "cr13", "cr14", "cr15",
+
+ "dr0", "dr1", "dr2", "dr3",
+ "dr4", "dr5", "dr6", "dr7",
+ "dr8", "dr9", "dr10", "dr11",
+ "dr12", "dr13", "dr14", "dr15",
+
+ "mm0", "mm1", "mm2", "mm3",
+ "mm4", "mm5", "mm6", "mm7",
+
+ "st0", "st1", "st2", "st3",
+ "st4", "st5", "st6", "st7",
+
+ "xmm0", "xmm1", "xmm2", "xmm3",
+ "xmm4", "xmm5", "xmm6", "xmm7",
+ "xmm8", "xmm9", "xmm10", "xmm11",
+ "xmm12", "xmm13", "xmm14", "xmm15",
+
+ "rip"
+};
+
+#endif // USE(UDIS86)
+
diff --git a/Source/JavaScriptCore/disassembler/udis86/udis86_syn.h b/Source/JavaScriptCore/disassembler/udis86/udis86_syn.h
new file mode 100644
index 000000000..e8636163e
--- /dev/null
+++ b/Source/JavaScriptCore/disassembler/udis86/udis86_syn.h
@@ -0,0 +1,47 @@
+/* udis86 - libudis86/syn.h
+ *
+ * Copyright (c) 2002-2009
+ * 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 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 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 A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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 UD_SYN_H
+#define UD_SYN_H
+
+#include "udis86_types.h"
+#include <wtf/Assertions.h>
+
+#ifndef __UD_STANDALONE__
+# include <stdarg.h>
+#endif /* __UD_STANDALONE__ */
+
+extern const char* ud_reg_tab[];
+
+static void mkasm(struct ud* u, const char* fmt, ...) WTF_ATTRIBUTE_PRINTF(2, 3);
+static void mkasm(struct ud* u, const char* fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ u->insn_fill += vsnprintf((char*) u->insn_buffer + u->insn_fill, UD_STRING_BUFFER_SIZE - u->insn_fill, fmt, ap);
+ va_end(ap);
+}
+
+#endif
diff --git a/Source/JavaScriptCore/disassembler/udis86/udis86_types.h b/Source/JavaScriptCore/disassembler/udis86/udis86_types.h
new file mode 100644
index 000000000..320d1ca49
--- /dev/null
+++ b/Source/JavaScriptCore/disassembler/udis86/udis86_types.h
@@ -0,0 +1,238 @@
+/* udis86 - libudis86/types.h
+ *
+ * Copyright (c) 2002-2009 Vivek Thampi
+ * 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 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 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 A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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 UD_TYPES_H
+#define UD_TYPES_H
+
+#ifndef __UD_STANDALONE__
+# include <stdio.h>
+#endif /* __UD_STANDALONE__ */
+
+/* gcc specific extensions */
+#ifdef __GNUC__
+# define UD_ATTR_PACKED __attribute__((packed))
+#else
+# define UD_ATTR_PACKED
+#endif /* UD_ATTR_PACKED */
+
+#ifdef _MSC_VER
+# define FMT64 "%I64"
+ typedef unsigned __int8 uint8_t;
+ typedef unsigned __int16 uint16_t;
+ typedef unsigned __int32 uint32_t;
+ typedef unsigned __int64 uint64_t;
+ typedef __int8 int8_t;
+ typedef __int16 int16_t;
+ typedef __int32 int32_t;
+ typedef __int64 int64_t;
+#else
+# define FMT64 "%ll"
+# ifndef __UD_STANDALONE__
+# include <inttypes.h>
+# endif /* __UD_STANDALONE__ */
+#endif
+
+/* -----------------------------------------------------------------------------
+ * All possible "types" of objects in udis86. Order is Important!
+ * -----------------------------------------------------------------------------
+ */
+enum ud_type
+{
+ UD_NONE,
+
+ /* 8 bit GPRs */
+ UD_R_AL, UD_R_CL, UD_R_DL, UD_R_BL,
+ UD_R_AH, UD_R_CH, UD_R_DH, UD_R_BH,
+ UD_R_SPL, UD_R_BPL, UD_R_SIL, UD_R_DIL,
+ UD_R_R8B, UD_R_R9B, UD_R_R10B, UD_R_R11B,
+ UD_R_R12B, UD_R_R13B, UD_R_R14B, UD_R_R15B,
+
+ /* 16 bit GPRs */
+ UD_R_AX, UD_R_CX, UD_R_DX, UD_R_BX,
+ UD_R_SP, UD_R_BP, UD_R_SI, UD_R_DI,
+ UD_R_R8W, UD_R_R9W, UD_R_R10W, UD_R_R11W,
+ UD_R_R12W, UD_R_R13W, UD_R_R14W, UD_R_R15W,
+
+ /* 32 bit GPRs */
+ UD_R_EAX, UD_R_ECX, UD_R_EDX, UD_R_EBX,
+ UD_R_ESP, UD_R_EBP, UD_R_ESI, UD_R_EDI,
+ UD_R_R8D, UD_R_R9D, UD_R_R10D, UD_R_R11D,
+ UD_R_R12D, UD_R_R13D, UD_R_R14D, UD_R_R15D,
+
+ /* 64 bit GPRs */
+ UD_R_RAX, UD_R_RCX, UD_R_RDX, UD_R_RBX,
+ UD_R_RSP, UD_R_RBP, UD_R_RSI, UD_R_RDI,
+ UD_R_R8, UD_R_R9, UD_R_R10, UD_R_R11,
+ UD_R_R12, UD_R_R13, UD_R_R14, UD_R_R15,
+
+ /* segment registers */
+ UD_R_ES, UD_R_CS, UD_R_SS, UD_R_DS,
+ UD_R_FS, UD_R_GS,
+
+ /* control registers*/
+ UD_R_CR0, UD_R_CR1, UD_R_CR2, UD_R_CR3,
+ UD_R_CR4, UD_R_CR5, UD_R_CR6, UD_R_CR7,
+ UD_R_CR8, UD_R_CR9, UD_R_CR10, UD_R_CR11,
+ UD_R_CR12, UD_R_CR13, UD_R_CR14, UD_R_CR15,
+
+ /* debug registers */
+ UD_R_DR0, UD_R_DR1, UD_R_DR2, UD_R_DR3,
+ UD_R_DR4, UD_R_DR5, UD_R_DR6, UD_R_DR7,
+ UD_R_DR8, UD_R_DR9, UD_R_DR10, UD_R_DR11,
+ UD_R_DR12, UD_R_DR13, UD_R_DR14, UD_R_DR15,
+
+ /* mmx registers */
+ UD_R_MM0, UD_R_MM1, UD_R_MM2, UD_R_MM3,
+ UD_R_MM4, UD_R_MM5, UD_R_MM6, UD_R_MM7,
+
+ /* x87 registers */
+ UD_R_ST0, UD_R_ST1, UD_R_ST2, UD_R_ST3,
+ UD_R_ST4, UD_R_ST5, UD_R_ST6, UD_R_ST7,
+
+ /* extended multimedia registers */
+ UD_R_XMM0, UD_R_XMM1, UD_R_XMM2, UD_R_XMM3,
+ UD_R_XMM4, UD_R_XMM5, UD_R_XMM6, UD_R_XMM7,
+ UD_R_XMM8, UD_R_XMM9, UD_R_XMM10, UD_R_XMM11,
+ UD_R_XMM12, UD_R_XMM13, UD_R_XMM14, UD_R_XMM15,
+
+ UD_R_RIP,
+
+ /* Operand Types */
+ UD_OP_REG, UD_OP_MEM, UD_OP_PTR, UD_OP_IMM,
+ UD_OP_JIMM, UD_OP_CONST
+};
+
+#include "udis86_itab.h"
+
+/* -----------------------------------------------------------------------------
+ * struct ud_operand - Disassembled instruction Operand.
+ * -----------------------------------------------------------------------------
+ */
+struct ud_operand
+{
+ enum ud_type type;
+ uint8_t size;
+ union {
+ int8_t sbyte;
+ uint8_t ubyte;
+ int16_t sword;
+ uint16_t uword;
+ int32_t sdword;
+ uint32_t udword;
+ int64_t sqword;
+ uint64_t uqword;
+
+ struct {
+ uint16_t seg;
+ uint32_t off;
+ } ptr;
+ } lval;
+
+ enum ud_type base;
+ enum ud_type index;
+ uint8_t offset;
+ uint8_t scale;
+};
+
+#define UD_STRING_BUFFER_SIZE 64
+
+/* -----------------------------------------------------------------------------
+ * struct ud - The udis86 object.
+ * -----------------------------------------------------------------------------
+ */
+struct ud
+{
+ int (*inp_hook) (struct ud*);
+ uint8_t inp_curr;
+ uint8_t inp_fill;
+#ifndef __UD_STANDALONE__
+ FILE* inp_file;
+#endif
+ uint8_t inp_ctr;
+ uint8_t* inp_buff;
+ uint8_t* inp_buff_end;
+ uint8_t inp_end;
+ void (*translator)(struct ud*);
+ uint64_t insn_offset;
+ char insn_hexcode[32];
+ char insn_buffer[UD_STRING_BUFFER_SIZE];
+ unsigned int insn_fill;
+ uint8_t dis_mode;
+ uint64_t pc;
+ uint8_t vendor;
+ struct map_entry* mapen;
+ enum ud_mnemonic_code mnemonic;
+ struct ud_operand operand[3];
+ uint8_t error;
+ uint8_t pfx_rex;
+ uint8_t pfx_seg;
+ uint8_t pfx_opr;
+ uint8_t pfx_adr;
+ uint8_t pfx_lock;
+ uint8_t pfx_rep;
+ uint8_t pfx_repe;
+ uint8_t pfx_repne;
+ uint8_t pfx_insn;
+ uint8_t default64;
+ uint8_t opr_mode;
+ uint8_t adr_mode;
+ uint8_t br_far;
+ uint8_t br_near;
+ uint8_t implicit_addr;
+ uint8_t c1;
+ uint8_t c2;
+ uint8_t c3;
+ uint8_t inp_cache[256];
+ uint8_t inp_sess[64];
+ uint8_t have_modrm;
+ uint8_t modrm;
+ void * user_opaque_data;
+ struct ud_itab_entry * itab_entry;
+ struct ud_lookup_table_list_entry *le;
+};
+
+/* -----------------------------------------------------------------------------
+ * Type-definitions
+ * -----------------------------------------------------------------------------
+ */
+typedef enum ud_type ud_type_t;
+typedef enum ud_mnemonic_code ud_mnemonic_code_t;
+
+typedef struct ud ud_t;
+typedef struct ud_operand ud_operand_t;
+
+#define UD_SYN_INTEL ud_translate_intel
+#define UD_SYN_ATT ud_translate_att
+#define UD_EOI -1
+#define UD_INP_CACHE_SZ 32
+#define UD_VENDOR_AMD 0
+#define UD_VENDOR_INTEL 1
+#define UD_VENDOR_ANY 2
+
+#define bail_out(ud,error_code) longjmp( (ud)->bailout, error_code )
+#define try_decode(ud) if ( setjmp( (ud)->bailout ) == 0 )
+#define catch_error() else
+
+#endif
diff --git a/Source/JavaScriptCore/gyp/JavaScriptCore.gyp b/Source/JavaScriptCore/gyp/JavaScriptCore.gyp
deleted file mode 100644
index 8a93f1d53..000000000
--- a/Source/JavaScriptCore/gyp/JavaScriptCore.gyp
+++ /dev/null
@@ -1,227 +0,0 @@
-{
- 'includes': [
- '../../gyp/common.gypi',
- '../JavaScriptCore.gypi',
- ],
- 'configurations': {
- 'Production': {
- 'xcode_config_file': '<(project_dir)/Configurations/Base.xcconfig',
- },
- 'Profiling': {
- 'xcode_config_file': '<(project_dir)/Configurations/DebugRelease.xcconfig',
- 'xcode_settings': {
- 'STRIP_INSTALLED_PRODUCT': 'NO',
- },
- },
- 'Release': {
- 'xcode_config_file': '<(project_dir)/Configurations/DebugRelease.xcconfig',
- 'xcode_settings': {
- 'STRIP_INSTALLED_PRODUCT': 'NO',
- },
- },
- 'Debug': {
- 'xcode_config_file': '<(project_dir)/Configurations/DebugRelease.xcconfig',
- 'xcode_settings': {
- 'DEAD_CODE_STRIPPING': '$(DEAD_CODE_STRIPPING_debug)',
- 'DEBUG_DEFINES': '$(DEBUG_DEFINES_debug)',
- 'GCC_OPTIMIZATION_LEVEL': '$(GCC_OPTIMIZATION_LEVEL_debug)',
- 'STRIP_INSTALLED_PRODUCT': '$(STRIP_INSTALLED_PRODUCT_debug)',
- },
- },
- },
- 'variables': {
- 'javascriptcore_include_dirs': [
- '<(project_dir)',
- '<(project_dir)/icu',
- ],
- },
- 'target_defaults': {
- 'configurations': {
- 'Profiling': {},
- },
- },
- 'targets': [
- {
- 'target_name': 'JavaScriptCore',
- 'type': 'shared_library',
- 'dependencies': [
- 'Derived Sources',
- 'Update Version',
- ],
- 'include_dirs': [
- '<@(javascriptcore_include_dirs)',
- '<(PRODUCT_DIR)/DerivedSources/JavaScriptCore',
- ],
- 'configurations': {
- 'Production': {
- 'INSTALL_PATH': '$(BUILT_PRODUCTS_DIR)',
- },
- },
- 'sources': [
- '<@(javascriptcore_files)',
- '<@(javascriptcore_publicheader_files)',
- '<@(javascriptcore_privateheader_files)',
- '<@(javascriptcore_derived_source_files)',
- '$(SDKROOT)/System/Library/Frameworks/CoreFoundation.framework',
- '$(SDKROOT)/System/Library/Frameworks/Foundation.framework',
- '/usr/lib/libicucore.dylib',
- '/usr/lib/libobjc.dylib',
- ],
- 'mac_framework_headers': [
- '<@(javascriptcore_publicheader_files)',
- ],
- 'mac_framework_private_headers': [
- '<@(javascriptcore_privateheader_files)',
- ],
- 'xcode_config_file': '<(project_dir)/Configurations/JavaScriptCore.xcconfig',
- 'sources/': [
- ['exclude', 'API/tests/'],
- ['exclude', 'ForwardingHeaders/'],
- ['exclude', '(?<!unicode)/icu/'],
- ['exclude', 'os-win32/'],
- ['exclude', 'qt/'],
- ['exclude', 'wtf/(efl|gtk|qt|wince|wx)/'],
- ['exclude', 'wtf/unicode/glib/'],
- ['exclude', 'wtf/unicode/qt4/'],
- ['exclude', 'wtf/unicode/wince/'],
- ['exclude', 'wtf/url/'],
- ['exclude', '/(gtk|glib|gobject)/.*\\.(cpp|h)$'],
- ['exclude', '(Default|Gtk|Chromium|None|Qt|Win|Wx|Symbian)\\.(cpp|mm|h)$'],
- ['exclude', 'GCActivityCallback\.cpp$'],
- ['exclude', 'BSTR[^/]*$'],
- ],
- 'postbuilds': [
- {
- 'postbuild_name': 'Check For Global Initializers',
- 'action': [
- 'sh', '<(project_dir)/gyp/run-if-exists.sh', '<(DEPTH)/../Tools/Scripts/check-for-global-initializers'
- ],
- },
- {
- 'postbuild_name': 'Check For Exit Time Destructors',
- 'action': [
- 'sh', '<(project_dir)/gyp/run-if-exists.sh', '<(DEPTH)/../Tools/Scripts/check-for-exit-time-destructors'
- ],
- },
- {
- 'postbuild_name': 'Check For Weak VTables and Externals',
- 'action': [
- 'sh', '<(project_dir)/gyp/run-if-exists.sh', '<(DEPTH)/../Tools/Scripts/check-for-weak-vtables-and-externals'
- ],
- },
- ],
- 'conditions': [
- ['OS=="mac"', {
- 'mac_bundle': 1,
- 'xcode_settings': {
- # FIXME: Remove these overrides once JavaScriptCore.xcconfig is
- # used only by this project.
- 'GCC_PREFIX_HEADER': '<(project_dir)/JavaScriptCorePrefix.h',
- 'INFOPLIST_FILE': '<(project_dir)/Info.plist',
- },
- }],
- ],
- },
- {
- 'target_name': 'Derived Sources',
- 'type': 'none',
- 'actions': [
- {
- 'action_name': 'Generate Derived Sources',
- 'inputs': [],
- 'outputs': [
- '<@(javascriptcore_derived_source_files)',
- ],
- 'action': [
- 'sh', 'generate-derived-sources.sh'
- ],
- },
- {
- 'action_name': 'Generate DTrace Header',
- 'inputs': [],
- 'outputs': [],
- 'action': [
- 'sh', '<(project_dir)/gyp/generate-dtrace-header.sh', '<(project_dir)'
- ]
- }
- ],
- },
- {
- 'target_name': 'Update Version',
- 'type': 'none',
- 'actions': [{
- 'action_name': 'Update Info.plist with version information',
- 'inputs': [],
- 'outputs': [],
- 'action': [
- 'sh', '<(project_dir)/gyp/update-info-plist.sh', '<(project_dir)/Info.plist'
- ]
- }],
- },
- {
- 'target_name': 'minidom',
- 'type': 'executable',
- 'dependencies': [
- 'JavaScriptCore',
- ],
- # FIXME: We should use a header map instead of listing these explicitly.
- 'include_dirs': [
- '<@(javascriptcore_include_dirs)',
- ],
- 'sources': [
- '<@(minidom_files)',
- '$(SDKROOT)/System/Library/Frameworks/CoreFoundation.framework',
- ],
- 'copies': [{
- 'destination': '<(PRODUCT_DIR)',
- 'files': [
- '<@(minidom_support_files)',
- ],
- }],
- },
- {
- 'target_name': 'testapi',
- 'type': 'executable',
- 'dependencies': [
- 'JavaScriptCore',
- ],
- # FIXME: We should use a header map instead of listing these explicitly.
- 'include_dirs': [
- '<@(javascriptcore_include_dirs)',
- ],
- 'sources': [
- '<@(testapi_files)',
- '$(SDKROOT)/System/Library/Frameworks/CoreFoundation.framework',
- ],
- 'copies': [{
- 'destination': '<(PRODUCT_DIR)',
- 'files': [
- '<@(testapi_support_files)',
- ],
- }],
- },
- {
- 'target_name': 'jsc',
- 'type': 'executable',
- 'dependencies': [
- 'JavaScriptCore',
- ],
- # FIXME: We should use a header map instead of listing these explicitly.
- 'include_dirs': [
- '<@(javascriptcore_include_dirs)',
- ],
- 'configurations': {
- 'Production': {
- 'xcode_settings': {
- 'INSTALL_PATH': '$(JAVASCRIPTCORE_FRAMEWORKS_DIR)/JavaScriptCore.framework/Resources',
- },
- },
- },
- 'sources': [
- '<@(jsc_files)',
- '$(SDKROOT)/System/Library/Frameworks/CoreFoundation.framework',
- '/usr/lib/libedit.dylib',
- ],
- },
- ], # targets
-}
diff --git a/Source/JavaScriptCore/gyp/gtk.gyp b/Source/JavaScriptCore/gyp/gtk.gyp
deleted file mode 100644
index 33eaa17a2..000000000
--- a/Source/JavaScriptCore/gyp/gtk.gyp
+++ /dev/null
@@ -1,18 +0,0 @@
-{ # Just a stub file to allow Source/gyp/configure to run successfully for testing.
- 'includes': [
- '../../gyp/common.gypi',
- '../JavaScriptCore.gypi',
- ],
- 'targets': [
- {
- 'target_name': 'JavaScriptCore',
- 'type': 'static_library',
- 'sources': [
- '<@(javascriptcore_files)',
- '<@(javascriptcore_publicheader_files)',
- '<@(javascriptcore_privateheader_files)',
- '<@(javascriptcore_derived_source_files)',
- ],
- },
- ], # targets
-}
diff --git a/Source/JavaScriptCore/heap/BlockAllocator.cpp b/Source/JavaScriptCore/heap/BlockAllocator.cpp
index 485ec8dd1..fc4f8a4c6 100644
--- a/Source/JavaScriptCore/heap/BlockAllocator.cpp
+++ b/Source/JavaScriptCore/heap/BlockAllocator.cpp
@@ -37,13 +37,15 @@ BlockAllocator::BlockAllocator()
, m_blockFreeingThread(createThread(blockFreeingThreadStartFunc, this, "JavaScriptCore::BlockFree"))
{
ASSERT(m_blockFreeingThread);
+ m_freeBlockLock.Init();
}
BlockAllocator::~BlockAllocator()
{
releaseFreeBlocks();
{
- MutexLocker locker(m_freeBlockLock);
+ MutexLocker locker(m_freeBlockConditionLock);
+
m_blockFreeingThreadShouldQuit = true;
m_freeBlockCondition.broadcast();
}
@@ -55,7 +57,7 @@ void BlockAllocator::releaseFreeBlocks()
while (true) {
HeapBlock* block;
{
- MutexLocker locker(m_freeBlockLock);
+ SpinLockHolder locker(&m_freeBlockLock);
if (!m_numberOfFreeBlocks)
block = 0;
else {
@@ -76,7 +78,8 @@ void BlockAllocator::waitForRelativeTimeWhileHoldingLock(double relative)
{
if (m_blockFreeingThreadShouldQuit)
return;
- m_freeBlockCondition.timedWait(m_freeBlockLock, currentTime() + relative);
+
+ m_freeBlockCondition.timedWait(m_freeBlockConditionLock, currentTime() + relative);
}
void BlockAllocator::waitForRelativeTime(double relative)
@@ -85,7 +88,7 @@ void BlockAllocator::waitForRelativeTime(double relative)
// frequently. It would only be a bug if this function failed to return
// when it was asked to do so.
- MutexLocker locker(m_freeBlockLock);
+ MutexLocker locker(m_freeBlockConditionLock);
waitForRelativeTimeWhileHoldingLock(relative);
}
@@ -120,7 +123,7 @@ void BlockAllocator::blockFreeingThreadMain()
while (!m_blockFreeingThreadShouldQuit) {
HeapBlock* block;
{
- MutexLocker locker(m_freeBlockLock);
+ SpinLockHolder locker(&m_freeBlockLock);
if (m_numberOfFreeBlocks <= desiredNumberOfFreeBlocks)
block = 0;
else {
diff --git a/Source/JavaScriptCore/heap/BlockAllocator.h b/Source/JavaScriptCore/heap/BlockAllocator.h
index 846bdfa2a..7a99d2edd 100644
--- a/Source/JavaScriptCore/heap/BlockAllocator.h
+++ b/Source/JavaScriptCore/heap/BlockAllocator.h
@@ -30,6 +30,7 @@
#include <wtf/DoublyLinkedList.h>
#include <wtf/Forward.h>
#include <wtf/PageAllocationAligned.h>
+#include <wtf/TCSpinLock.h>
#include <wtf/Threading.h>
namespace JSC {
@@ -58,19 +59,22 @@ private:
size_t m_numberOfFreeBlocks;
bool m_isCurrentlyAllocating;
bool m_blockFreeingThreadShouldQuit;
- Mutex m_freeBlockLock;
+ SpinLock m_freeBlockLock;
+ Mutex m_freeBlockConditionLock;
ThreadCondition m_freeBlockCondition;
ThreadIdentifier m_blockFreeingThread;
};
inline PageAllocationAligned BlockAllocator::allocate()
{
- MutexLocker locker(m_freeBlockLock);
- m_isCurrentlyAllocating = true;
- if (m_numberOfFreeBlocks) {
- ASSERT(!m_freeBlocks.isEmpty());
- m_numberOfFreeBlocks--;
- return m_freeBlocks.removeHead()->m_allocation;
+ {
+ SpinLockHolder locker(&m_freeBlockLock);
+ m_isCurrentlyAllocating = true;
+ if (m_numberOfFreeBlocks) {
+ ASSERT(!m_freeBlocks.isEmpty());
+ m_numberOfFreeBlocks--;
+ return m_freeBlocks.removeHead()->m_allocation;
+ }
}
ASSERT(m_freeBlocks.isEmpty());
@@ -82,7 +86,7 @@ inline PageAllocationAligned BlockAllocator::allocate()
inline void BlockAllocator::deallocate(PageAllocationAligned allocation)
{
- MutexLocker locker(m_freeBlockLock);
+ SpinLockHolder locker(&m_freeBlockLock);
HeapBlock* heapBlock = new(NotNull, allocation.base()) HeapBlock(allocation);
m_freeBlocks.push(heapBlock);
m_numberOfFreeBlocks++;
diff --git a/Source/JavaScriptCore/heap/CopiedBlock.h b/Source/JavaScriptCore/heap/CopiedBlock.h
index b408aa40b..5ed58008e 100644
--- a/Source/JavaScriptCore/heap/CopiedBlock.h
+++ b/Source/JavaScriptCore/heap/CopiedBlock.h
@@ -39,6 +39,7 @@ class CopiedBlock : public HeapBlock {
friend class CopiedAllocator;
public:
static CopiedBlock* create(const PageAllocationAligned&);
+ static CopiedBlock* createNoZeroFill(const PageAllocationAligned&);
static PageAllocationAligned destroy(CopiedBlock*);
char* payload();
@@ -47,16 +48,37 @@ public:
private:
CopiedBlock(const PageAllocationAligned&);
+ void zeroFillToEnd(); // Can be called at any time to zero-fill to the end of the block.
void* m_offset;
uintptr_t m_isPinned;
};
-inline CopiedBlock* CopiedBlock::create(const PageAllocationAligned& allocation)
+inline CopiedBlock* CopiedBlock::createNoZeroFill(const PageAllocationAligned& allocation)
{
return new(NotNull, allocation.base()) CopiedBlock(allocation);
}
+inline CopiedBlock* CopiedBlock::create(const PageAllocationAligned& allocation)
+{
+ CopiedBlock* block = createNoZeroFill(allocation);
+ block->zeroFillToEnd();
+ return block;
+}
+
+inline void CopiedBlock::zeroFillToEnd()
+{
+#if USE(JSVALUE64)
+ char* offset = static_cast<char*>(m_offset);
+ memset(static_cast<void*>(offset), 0, static_cast<size_t>((reinterpret_cast<char*>(this) + m_allocation.size()) - offset));
+#else
+ JSValue emptyValue;
+ JSValue* limit = reinterpret_cast_ptr<JSValue*>(reinterpret_cast<char*>(this) + m_allocation.size());
+ for (JSValue* currentValue = reinterpret_cast<JSValue*>(m_offset); currentValue < limit; currentValue++)
+ *currentValue = emptyValue;
+#endif
+}
+
inline PageAllocationAligned CopiedBlock::destroy(CopiedBlock* block)
{
PageAllocationAligned allocation;
@@ -72,15 +94,6 @@ inline CopiedBlock::CopiedBlock(const PageAllocationAligned& allocation)
, m_isPinned(false)
{
ASSERT(is8ByteAligned(static_cast<void*>(m_offset)));
-#if USE(JSVALUE64)
- char* offset = static_cast<char*>(m_offset);
- memset(static_cast<void*>(offset), 0, static_cast<size_t>((reinterpret_cast<char*>(this) + allocation.size()) - offset));
-#else
- JSValue emptyValue;
- JSValue* limit = reinterpret_cast_ptr<JSValue*>(reinterpret_cast<char*>(this) + allocation.size());
- for (JSValue* currentValue = reinterpret_cast<JSValue*>(m_offset); currentValue < limit; currentValue++)
- *currentValue = emptyValue;
-#endif
}
inline char* CopiedBlock::payload()
diff --git a/Source/JavaScriptCore/heap/CopiedSpace.cpp b/Source/JavaScriptCore/heap/CopiedSpace.cpp
index 7f5a665df..631e829ec 100644
--- a/Source/JavaScriptCore/heap/CopiedSpace.cpp
+++ b/Source/JavaScriptCore/heap/CopiedSpace.cpp
@@ -38,6 +38,7 @@ CopiedSpace::CopiedSpace(Heap* heap)
, m_inCopyingPhase(false)
, m_numberOfLoanedBlocks(0)
{
+ m_toSpaceLock.Init();
}
CopiedSpace::~CopiedSpace()
@@ -57,8 +58,7 @@ void CopiedSpace::init()
m_toSpace = &m_blocks1;
m_fromSpace = &m_blocks2;
- if (!addNewBlock())
- CRASH();
+ allocateBlock();
}
CheckedBoolean CopiedSpace::tryAllocateSlowCase(size_t bytes, void** outPtr)
@@ -68,10 +68,8 @@ CheckedBoolean CopiedSpace::tryAllocateSlowCase(size_t bytes, void** outPtr)
m_heap->didAllocate(m_allocator.currentCapacity());
- if (!addNewBlock()) {
- *outPtr = 0;
- return false;
- }
+ allocateBlock();
+
*outPtr = m_allocator.allocate(bytes);
ASSERT(*outPtr);
return true;
@@ -167,8 +165,10 @@ void CopiedSpace::doneFillingBlock(CopiedBlock* block)
return;
}
+ block->zeroFillToEnd();
+
{
- MutexLocker locker(m_toSpaceLock);
+ SpinLockHolder locker(&m_toSpaceLock);
m_toSpace->push(block);
m_blockSet.add(block);
m_blockFilter.add(reinterpret_cast<Bits>(block));
@@ -222,35 +222,12 @@ void CopiedSpace::doneCopying()
curr = next;
}
- if (!m_toSpace->head()) {
- if (!addNewBlock())
- CRASH();
- } else
+ if (!m_toSpace->head())
+ allocateBlock();
+ else
m_allocator.resetCurrentBlock(static_cast<CopiedBlock*>(m_toSpace->head()));
}
-CheckedBoolean CopiedSpace::getFreshBlock(AllocationEffort allocationEffort, CopiedBlock** outBlock)
-{
- CopiedBlock* block = 0;
- if (allocationEffort == AllocationMustSucceed)
- block = CopiedBlock::create(m_heap->blockAllocator().allocate());
- else {
- ASSERT(allocationEffort == AllocationCanFail);
- if (m_heap->shouldCollect())
- m_heap->collect(Heap::DoNotSweep);
-
- if (!getFreshBlock(AllocationMustSucceed, &block)) {
- *outBlock = 0;
- ASSERT_NOT_REACHED();
- return false;
- }
- }
- ASSERT(block);
- ASSERT(is8ByteAligned(block->m_offset));
- *outBlock = block;
- return true;
-}
-
size_t CopiedSpace::size()
{
size_t calculatedSize = 0;
diff --git a/Source/JavaScriptCore/heap/CopiedSpace.h b/Source/JavaScriptCore/heap/CopiedSpace.h
index 27011781d..530e989da 100644
--- a/Source/JavaScriptCore/heap/CopiedSpace.h
+++ b/Source/JavaScriptCore/heap/CopiedSpace.h
@@ -37,6 +37,7 @@
#include <wtf/PageAllocationAligned.h>
#include <wtf/PageBlock.h>
#include <wtf/StdLibExtras.h>
+#include <wtf/TCSpinLock.h>
#include <wtf/ThreadingPrimitives.h>
namespace JSC {
@@ -76,22 +77,20 @@ public:
static CopiedBlock* blockFor(void*);
private:
- CheckedBoolean tryAllocateSlowCase(size_t, void**);
- CheckedBoolean addNewBlock();
- CheckedBoolean allocateNewBlock(CopiedBlock**);
-
static void* allocateFromBlock(CopiedBlock*, size_t);
+ static bool isOversize(size_t);
+ static bool fitsInBlock(CopiedBlock*, size_t);
+ static CopiedBlock* oversizeBlockFor(void* ptr);
+
+ CheckedBoolean tryAllocateSlowCase(size_t, void**);
CheckedBoolean tryAllocateOversize(size_t, void**);
CheckedBoolean tryReallocateOversize(void**, size_t, size_t);
- static bool isOversize(size_t);
-
- CheckedBoolean borrowBlock(CopiedBlock**);
- CheckedBoolean getFreshBlock(AllocationEffort, CopiedBlock**);
+ void allocateBlock();
+ CopiedBlock* allocateBlockForCopyingPhase();
+
void doneFillingBlock(CopiedBlock*);
void recycleBlock(CopiedBlock*);
- static bool fitsInBlock(CopiedBlock*, size_t);
- static CopiedBlock* oversizeBlockFor(void* ptr);
Heap* m_heap;
@@ -100,7 +99,7 @@ private:
TinyBloomFilter m_blockFilter;
HashSet<CopiedBlock*> m_blockSet;
- Mutex m_toSpaceLock;
+ SpinLock m_toSpaceLock;
DoublyLinkedList<HeapBlock>* m_toSpace;
DoublyLinkedList<HeapBlock>* m_fromSpace;
diff --git a/Source/JavaScriptCore/heap/CopiedSpaceInlineMethods.h b/Source/JavaScriptCore/heap/CopiedSpaceInlineMethods.h
index c97762598..1366cd8a7 100644
--- a/Source/JavaScriptCore/heap/CopiedSpaceInlineMethods.h
+++ b/Source/JavaScriptCore/heap/CopiedSpaceInlineMethods.h
@@ -84,46 +84,31 @@ inline void CopiedSpace::recycleBlock(CopiedBlock* block)
}
}
-inline CheckedBoolean CopiedSpace::borrowBlock(CopiedBlock** outBlock)
+inline CopiedBlock* CopiedSpace::allocateBlockForCopyingPhase()
{
- CopiedBlock* block = 0;
- if (!getFreshBlock(AllocationMustSucceed, &block)) {
- *outBlock = 0;
- return false;
- }
-
ASSERT(m_inCopyingPhase);
- MutexLocker locker(m_loanedBlocksLock);
- m_numberOfLoanedBlocks++;
+ CopiedBlock* block = CopiedBlock::createNoZeroFill(m_heap->blockAllocator().allocate());
+
+ {
+ MutexLocker locker(m_loanedBlocksLock);
+ m_numberOfLoanedBlocks++;
+ }
ASSERT(block->m_offset == block->payload());
- *outBlock = block;
- return true;
+ return block;
}
-inline CheckedBoolean CopiedSpace::addNewBlock()
+inline void CopiedSpace::allocateBlock()
{
- CopiedBlock* block = 0;
- if (!getFreshBlock(AllocationCanFail, &block))
- return false;
+ if (m_heap->shouldCollect())
+ m_heap->collect(Heap::DoNotSweep);
+
+ CopiedBlock* block = CopiedBlock::create(m_heap->blockAllocator().allocate());
m_toSpace->push(block);
m_blockFilter.add(reinterpret_cast<Bits>(block));
m_blockSet.add(block);
m_allocator.resetCurrentBlock(block);
- return true;
-}
-
-inline CheckedBoolean CopiedSpace::allocateNewBlock(CopiedBlock** outBlock)
-{
- PageAllocationAligned allocation = PageAllocationAligned::allocate(HeapBlock::s_blockSize, HeapBlock::s_blockSize, OSAllocator::JSGCHeapPages);
- if (!static_cast<bool>(allocation)) {
- *outBlock = 0;
- return false;
- }
-
- *outBlock = new (NotNull, allocation.base()) CopiedBlock(allocation);
- return true;
}
inline bool CopiedSpace::fitsInBlock(CopiedBlock* block, size_t bytes)
diff --git a/Source/JavaScriptCore/heap/Handle.h b/Source/JavaScriptCore/heap/Handle.h
index 8bf2bd896..62f267e12 100644
--- a/Source/JavaScriptCore/heap/Handle.h
+++ b/Source/JavaScriptCore/heap/Handle.h
@@ -114,7 +114,7 @@ private:
template <typename T> class Handle : public HandleBase, public HandleConverter<Handle<T>, T> {
public:
- template <typename A, typename B> friend class HandleConverter;
+ template <typename A, typename B> friend struct HandleConverter;
typedef typename HandleTypes<T>::ExternalType ExternalType;
template <typename U> Handle(Handle<U> o)
{
diff --git a/Source/JavaScriptCore/heap/Heap.cpp b/Source/JavaScriptCore/heap/Heap.cpp
index 90c4bb72c..ef062c9ce 100644
--- a/Source/JavaScriptCore/heap/Heap.cpp
+++ b/Source/JavaScriptCore/heap/Heap.cpp
@@ -245,8 +245,6 @@ Heap::Heap(JSGlobalData* globalData, HeapType heapType)
, m_operationInProgress(NoOperation)
, m_objectSpace(this)
, m_storageSpace(this)
- , m_activityCallback(DefaultGCActivityCallback::create(this))
- , m_sweeper(IncrementalSweeper::create(this))
, m_machineThreads(this)
, m_sharedData(globalData)
, m_slotVisitor(m_sharedData)
@@ -255,6 +253,8 @@ Heap::Heap(JSGlobalData* globalData, HeapType heapType)
, m_globalData(globalData)
, m_lastGCLength(0)
, m_lastCodeDiscardTime(WTF::currentTime())
+ , m_activityCallback(DefaultGCActivityCallback::create(this))
+ , m_sweeper(IncrementalSweeper::create(this))
{
m_storageSpace.init();
}
@@ -403,9 +403,6 @@ inline RegisterFile& Heap::registerFile()
void Heap::getConservativeRegisterRoots(HashSet<JSCell*>& roots)
{
ASSERT(isValidThreadState(m_globalData));
- if (m_operationInProgress != NoOperation)
- CRASH();
- m_operationInProgress = Collection;
ConservativeRoots registerFileRoots(&m_objectSpace.blocks(), &m_storageSpace);
registerFile().gatherConservativeRoots(registerFileRoots);
size_t registerFileRootCount = registerFileRoots.size();
@@ -414,7 +411,6 @@ void Heap::getConservativeRegisterRoots(HashSet<JSCell*>& roots)
setMarked(registerRoots[i]);
roots.add(registerRoots[i]);
}
- m_operationInProgress = NoOperation;
}
void Heap::markRoots(bool fullGC)
@@ -424,9 +420,10 @@ void Heap::markRoots(bool fullGC)
COND_GCPHASE(fullGC, MarkFullRoots, MarkYoungRoots);
UNUSED_PARAM(fullGC);
ASSERT(isValidThreadState(m_globalData));
- if (m_operationInProgress != NoOperation)
- CRASH();
- m_operationInProgress = Collection;
+
+#if ENABLE(OBJECT_MARK_LOGGING)
+ double gcStartTime = WTF::currentTime();
+#endif
void* dummy;
@@ -491,28 +488,33 @@ void Heap::markRoots(bool fullGC)
{
GCPHASE(VisitMachineRoots);
+ MARK_LOG_ROOT(visitor, "C++ Stack");
visitor.append(machineThreadRoots);
visitor.donateAndDrain();
}
{
GCPHASE(VisitRegisterFileRoots);
+ MARK_LOG_ROOT(visitor, "Register File");
visitor.append(registerFileRoots);
visitor.donateAndDrain();
}
#if ENABLE(DFG_JIT)
{
GCPHASE(VisitScratchBufferRoots);
+ MARK_LOG_ROOT(visitor, "Scratch Buffers");
visitor.append(scratchBufferRoots);
visitor.donateAndDrain();
}
#endif
{
GCPHASE(VisitProtectedObjects);
+ MARK_LOG_ROOT(visitor, "Protected Objects");
markProtectedObjects(heapRootVisitor);
visitor.donateAndDrain();
}
{
GCPHASE(VisitTempSortVectors);
+ MARK_LOG_ROOT(visitor, "Temp Sort Vectors");
markTempSortVectors(heapRootVisitor);
visitor.donateAndDrain();
}
@@ -520,30 +522,35 @@ void Heap::markRoots(bool fullGC)
{
GCPHASE(MarkingArgumentBuffers);
if (m_markListSet && m_markListSet->size()) {
+ MARK_LOG_ROOT(visitor, "Argument Buffers");
MarkedArgumentBuffer::markLists(heapRootVisitor, *m_markListSet);
visitor.donateAndDrain();
}
}
if (m_globalData->exception) {
GCPHASE(MarkingException);
+ MARK_LOG_ROOT(visitor, "Exceptions");
heapRootVisitor.visit(&m_globalData->exception);
visitor.donateAndDrain();
}
{
GCPHASE(VisitStrongHandles);
+ MARK_LOG_ROOT(visitor, "Strong Handles");
m_handleSet.visitStrongHandles(heapRootVisitor);
visitor.donateAndDrain();
}
{
GCPHASE(HandleStack);
+ MARK_LOG_ROOT(visitor, "Handle Stack");
m_handleStack.visit(heapRootVisitor);
visitor.donateAndDrain();
}
{
GCPHASE(TraceCodeBlocks);
+ MARK_LOG_ROOT(visitor, "Trace Code Blocks");
m_dfgCodeBlocks.traceMarkedCodeBlocks(visitor);
visitor.donateAndDrain();
}
@@ -560,6 +567,7 @@ void Heap::markRoots(bool fullGC)
// the liveness of the rest of the object graph.
{
GCPHASE(VisitingLiveWeakHandles);
+ MARK_LOG_ROOT(visitor, "Live Weak Handles");
while (true) {
m_objectSpace.visitWeakSets(heapRootVisitor);
harvestWeakReferences();
@@ -578,11 +586,21 @@ void Heap::markRoots(bool fullGC)
GCCOUNTER(VisitedValueCount, visitor.visitCount());
visitor.doneCopying();
+#if ENABLE(OBJECT_MARK_LOGGING)
+ size_t visitCount = visitor.visitCount();
+#if ENABLE(PARALLEL_GC)
+ visitCount += m_sharedData.childVisitCount();
+#endif
+ MARK_LOG_MESSAGE2("\nNumber of live Objects after full GC %lu, took %.6f secs\n", visitCount, WTF::currentTime() - gcStartTime);
+#endif
+
visitor.reset();
m_sharedData.reset();
+#if ENABLE(PARALLEL_GC)
+ m_sharedData.resetChildren();
+#endif
m_storageSpace.doneCopying();
- m_operationInProgress = NoOperation;
}
size_t Heap::objectCount()
@@ -625,15 +643,38 @@ PassOwnPtr<TypeCountSet> Heap::objectTypeCounts()
return m_objectSpace.forEachCell<RecordType>();
}
-void Heap::discardAllCompiledCode()
+void Heap::deleteAllCompiledCode()
{
- // If JavaScript is running, it's not safe to recompile, since we'll end
- // up throwing away code that is live on the stack.
+ // If JavaScript is running, it's not safe to delete code, since we'll end
+ // up deleting code that is live on the stack.
if (m_globalData->dynamicGlobalObject)
return;
- for (FunctionExecutable* current = m_functions.head(); current; current = current->next())
- current->discardCode();
+ for (ExecutableBase* current = m_compiledCode.head(); current; current = current->next()) {
+ if (!current->isFunctionExecutable())
+ continue;
+ static_cast<FunctionExecutable*>(current)->clearCodeIfNotCompiling();
+ }
+
+ m_dfgCodeBlocks.clearMarks();
+ m_dfgCodeBlocks.deleteUnmarkedJettisonedCodeBlocks();
+}
+
+void Heap::deleteUnmarkedCompiledCode()
+{
+ ExecutableBase* next;
+ for (ExecutableBase* current = m_compiledCode.head(); current; current = next) {
+ next = current->next();
+ if (isMarked(current))
+ continue;
+
+ // We do this because executable memory is limited on some platforms and because
+ // CodeBlock requires eager finalization.
+ ExecutableBase::clearCodeVirtual(current);
+ m_compiledCode.remove(current);
+ }
+
+ m_dfgCodeBlocks.deleteUnmarkedJettisonedCodeBlocks();
}
void Heap::collectAllGarbage()
@@ -654,12 +695,15 @@ void Heap::collect(SweepToggle sweepToggle)
ASSERT(globalData()->identifierTable == wtfThreadData().currentIdentifierTable());
ASSERT(m_isSafeToCollect);
JAVASCRIPTCORE_GC_BEGIN();
+ if (m_operationInProgress != NoOperation)
+ CRASH();
+ m_operationInProgress = Collection;
m_activityCallback->willCollect();
double lastGCStartTime = WTF::currentTime();
if (lastGCStartTime - m_lastCodeDiscardTime > minute) {
- discardAllCompiledCode();
+ deleteAllCompiledCode();
m_lastCodeDiscardTime = WTF::currentTime();
}
@@ -682,22 +726,21 @@ void Heap::collect(SweepToggle sweepToggle)
m_objectSpace.reapWeakSets();
}
+ JAVASCRIPTCORE_GC_MARKED();
+
{
GCPHASE(FinalizeUnconditionalFinalizers);
finalizeUnconditionalFinalizers();
}
{
- GCPHASE(FinalizeWeakHandles);
- m_objectSpace.sweepWeakSets();
+ GCPHASE(finalizeSmallStrings);
m_globalData->smallStrings.finalizeSmallStrings();
}
-
- JAVASCRIPTCORE_GC_MARKED();
{
GCPHASE(DeleteCodeBlocks);
- m_dfgCodeBlocks.deleteUnmarkedJettisonedCodeBlocks();
+ deleteUnmarkedCompiledCode();
}
if (sweepToggle == DoSweep) {
@@ -728,6 +771,9 @@ void Heap::collect(SweepToggle sweepToggle)
m_bytesAllocated = 0;
double lastGCEndTime = WTF::currentTime();
m_lastGCLength = lastGCEndTime - lastGCStartTime;
+ if (m_operationInProgress != Collection)
+ CRASH();
+ m_operationInProgress = NoOperation;
JAVASCRIPTCORE_GC_END();
}
@@ -784,14 +830,9 @@ void Heap::FinalizerOwner::finalize(Handle<Unknown> handle, void* context)
WeakSet::deallocate(WeakImpl::asWeakImpl(slot));
}
-void Heap::addFunctionExecutable(FunctionExecutable* executable)
-{
- m_functions.append(executable);
-}
-
-void Heap::removeFunctionExecutable(FunctionExecutable* executable)
+void Heap::addCompiledCode(ExecutableBase* executable)
{
- m_functions.remove(executable);
+ m_compiledCode.append(executable);
}
} // namespace JSC
diff --git a/Source/JavaScriptCore/heap/Heap.h b/Source/JavaScriptCore/heap/Heap.h
index 296447d7b..91c3aa58f 100644
--- a/Source/JavaScriptCore/heap/Heap.h
+++ b/Source/JavaScriptCore/heap/Heap.h
@@ -42,7 +42,7 @@ namespace JSC {
class CopiedSpace;
class CodeBlock;
- class FunctionExecutable;
+ class ExecutableBase;
class GCActivityCallback;
class GlobalCodeBlock;
class Heap;
@@ -85,6 +85,7 @@ namespace JSC {
static bool testAndSetMarked(const void*);
static void setMarked(const void*);
+ static bool isWriteBarrierEnabled();
static void writeBarrier(const JSCell*, JSValue);
static void writeBarrier(const JSCell*, JSCell*);
static uint8_t* addressOfCardFor(JSCell*);
@@ -115,10 +116,10 @@ namespace JSC {
typedef void (*Finalizer)(JSCell*);
JS_EXPORT_PRIVATE void addFinalizer(JSCell*, Finalizer);
- void addFunctionExecutable(FunctionExecutable*);
- void removeFunctionExecutable(FunctionExecutable*);
+ void addCompiledCode(ExecutableBase*);
void notifyIsSafeToCollect() { m_isSafeToCollect = true; }
+ bool isSafeToCollect() const { return m_isSafeToCollect; }
JS_EXPORT_PRIVATE void collectAllGarbage();
enum SweepToggle { DoNotSweep, DoSweep };
@@ -158,7 +159,7 @@ namespace JSC {
double lastGCLength() { return m_lastGCLength; }
void increaseLastGCLength(double amount) { m_lastGCLength += amount; }
- JS_EXPORT_PRIVATE void discardAllCompiledCode();
+ JS_EXPORT_PRIVATE void deleteAllCompiledCode();
void didAllocate(size_t);
void didAbandon(size_t);
@@ -193,6 +194,7 @@ namespace JSC {
void markTempSortVectors(HeapRootVisitor&);
void harvestWeakReferences();
void finalizeUnconditionalFinalizers();
+ void deleteUnmarkedCompiledCode();
RegisterFile& registerFile();
BlockAllocator& blockAllocator();
@@ -219,9 +221,6 @@ namespace JSC {
Vector<Vector<ValueStringPair>* > m_tempSortingVectors;
OwnPtr<HashSet<MarkedArgumentBuffer*> > m_markListSet;
- OwnPtr<GCActivityCallback> m_activityCallback;
- OwnPtr<IncrementalSweeper> m_sweeper;
-
MachineThreads m_machineThreads;
MarkStackThreadSharedData m_sharedData;
@@ -238,7 +237,10 @@ namespace JSC {
double m_lastGCLength;
double m_lastCodeDiscardTime;
- DoublyLinkedList<FunctionExecutable> m_functions;
+ OwnPtr<GCActivityCallback> m_activityCallback;
+ OwnPtr<IncrementalSweeper> m_sweeper;
+
+ DoublyLinkedList<ExecutableBase> m_compiledCode;
};
inline bool Heap::shouldCollect()
@@ -282,6 +284,15 @@ namespace JSC {
MarkedBlock::blockFor(cell)->setMarked(cell);
}
+ inline bool Heap::isWriteBarrierEnabled()
+ {
+#if ENABLE(GGC) || ENABLE(WRITE_BARRIER_PROFILING)
+ return true;
+#else
+ return false;
+#endif
+ }
+
#if ENABLE(GGC)
inline uint8_t* Heap::addressOfCardFor(JSCell* cell)
{
diff --git a/Source/JavaScriptCore/heap/HeapTimer.cpp b/Source/JavaScriptCore/heap/HeapTimer.cpp
new file mode 100644
index 000000000..bc42032f5
--- /dev/null
+++ b/Source/JavaScriptCore/heap/HeapTimer.cpp
@@ -0,0 +1,71 @@
+#include "config.h"
+#include "HeapTimer.h"
+
+#include <wtf/Threading.h>
+
+namespace JSC {
+
+#if USE(CF)
+
+const CFTimeInterval HeapTimer::s_decade = 60 * 60 * 24 * 365 * 10;
+
+HeapTimer::HeapTimer(JSGlobalData* globalData, CFRunLoopRef runLoop)
+ : m_globalData(globalData)
+ , m_runLoop(runLoop)
+{
+ memset(&m_context, 0, sizeof(CFRunLoopTimerContext));
+ m_context.info = this;
+ m_timer.adoptCF(CFRunLoopTimerCreate(0, s_decade, s_decade, 0, 0, HeapTimer::timerDidFire, &m_context));
+ CFRunLoopAddTimer(m_runLoop.get(), m_timer.get(), kCFRunLoopCommonModes);
+}
+
+HeapTimer::~HeapTimer()
+{
+ invalidate();
+}
+
+void HeapTimer::synchronize()
+{
+ if (CFRunLoopGetCurrent() == m_runLoop.get())
+ return;
+ CFRunLoopRemoveTimer(m_runLoop.get(), m_timer.get(), kCFRunLoopCommonModes);
+ m_runLoop = CFRunLoopGetCurrent();
+ CFRunLoopAddTimer(m_runLoop.get(), m_timer.get(), kCFRunLoopCommonModes);
+}
+
+void HeapTimer::invalidate()
+{
+ CFRunLoopRemoveTimer(m_runLoop.get(), m_timer.get(), kCFRunLoopCommonModes);
+ CFRunLoopTimerInvalidate(m_timer.get());
+}
+
+void HeapTimer::timerDidFire(CFRunLoopTimerRef, void* info)
+{
+ HeapTimer* agent = static_cast<HeapTimer*>(info);
+ agent->doWork();
+}
+
+#else
+
+HeapTimer::HeapTimer(JSGlobalData* globalData)
+ : m_globalData(globalData)
+{
+}
+
+HeapTimer::~HeapTimer()
+{
+}
+
+void HeapTimer::synchronize()
+{
+}
+
+void HeapTimer::invalidate()
+{
+}
+
+
+#endif
+
+
+} // namespace JSC
diff --git a/Source/JavaScriptCore/heap/HeapTimer.h b/Source/JavaScriptCore/heap/HeapTimer.h
new file mode 100644
index 000000000..ccd6ba8c5
--- /dev/null
+++ b/Source/JavaScriptCore/heap/HeapTimer.h
@@ -0,0 +1,45 @@
+#ifndef HeapTimer_h
+#define HeapTimer_h
+
+#include <wtf/RetainPtr.h>
+
+#if USE(CF)
+#include <CoreFoundation/CoreFoundation.h>
+#endif
+
+namespace JSC {
+
+class JSGlobalData;
+
+class HeapTimer {
+public:
+#if USE(CF)
+ HeapTimer(JSGlobalData*, CFRunLoopRef);
+ static void timerDidFire(CFRunLoopTimerRef, void*);
+#else
+ HeapTimer(JSGlobalData*);
+#endif
+
+ virtual ~HeapTimer();
+
+ virtual void synchronize();
+ virtual void doWork() = 0;
+
+protected:
+ JSGlobalData* m_globalData;
+
+#if USE(CF)
+ static const CFTimeInterval s_decade;
+
+ RetainPtr<CFRunLoopTimerRef> m_timer;
+ RetainPtr<CFRunLoopRef> m_runLoop;
+ CFRunLoopTimerContext m_context;
+#endif
+
+private:
+ void invalidate();
+};
+
+} // namespace JSC
+
+#endif
diff --git a/Source/JavaScriptCore/heap/IncrementalSweeper.cpp b/Source/JavaScriptCore/heap/IncrementalSweeper.cpp
index 08a9f6c73..0d0116f42 100644
--- a/Source/JavaScriptCore/heap/IncrementalSweeper.cpp
+++ b/Source/JavaScriptCore/heap/IncrementalSweeper.cpp
@@ -14,33 +14,20 @@ namespace JSC {
#if USE(CF)
-static const CFTimeInterval decade = 60 * 60 * 24 * 365 * 10;
static const CFTimeInterval sweepTimeSlicePerBlock = 0.01;
static const CFTimeInterval sweepTimeMultiplier = 1.0 / sweepTimeSlicePerBlock;
-void IncrementalSweeper::timerDidFire(CFRunLoopTimerRef, void* info)
+void IncrementalSweeper::doWork()
{
- Heap* heap = static_cast<Heap*>(info);
- APIEntryShim shim(heap->globalData());
- heap->sweeper()->doSweep(WTF::monotonicallyIncreasingTime());
+ APIEntryShim shim(m_globalData);
+ doSweep(WTF::monotonicallyIncreasingTime());
}
IncrementalSweeper::IncrementalSweeper(Heap* heap, CFRunLoopRef runLoop)
- : m_heap(heap)
+ : HeapTimer(heap->globalData(), runLoop)
, m_currentBlockToSweepIndex(0)
, m_lengthOfLastSweepIncrement(0.0)
{
- memset(&m_context, 0, sizeof(CFRunLoopTimerContext));
- m_context.info = m_heap;
- m_runLoop = runLoop;
- m_timer.adoptCF(CFRunLoopTimerCreate(0, CFAbsoluteTimeGetCurrent(), decade, 0, 0, &timerDidFire, &m_context));
- CFRunLoopAddTimer(m_runLoop.get(), m_timer.get(), kCFRunLoopCommonModes);
-}
-
-IncrementalSweeper::~IncrementalSweeper()
-{
- CFRunLoopRemoveTimer(m_runLoop.get(), m_timer.get(), kCFRunLoopCommonModes);
- CFRunLoopTimerInvalidate(m_timer.get());
}
PassOwnPtr<IncrementalSweeper> IncrementalSweeper::create(Heap* heap)
@@ -55,7 +42,7 @@ void IncrementalSweeper::scheduleTimer()
void IncrementalSweeper::cancelTimer()
{
- CFRunLoopTimerSetNextFireDate(m_timer.get(), CFAbsoluteTimeGetCurrent() + decade);
+ CFRunLoopTimerSetNextFireDate(m_timer.get(), CFAbsoluteTimeGetCurrent() + s_decade);
}
void IncrementalSweeper::doSweep(double sweepBeginTime)
@@ -85,17 +72,18 @@ void IncrementalSweeper::startSweeping(const HashSet<MarkedBlock*>& blockSnapsho
#else
-IncrementalSweeper::IncrementalSweeper()
+IncrementalSweeper::IncrementalSweeper(JSGlobalData* globalData)
+ : HeapTimer(globalData)
{
}
-IncrementalSweeper::~IncrementalSweeper()
+void IncrementalSweeper::doWork()
{
}
-PassOwnPtr<IncrementalSweeper> IncrementalSweeper::create(Heap*)
+PassOwnPtr<IncrementalSweeper> IncrementalSweeper::create(Heap* heap)
{
- return adoptPtr(new IncrementalSweeper());
+ return adoptPtr(new IncrementalSweeper(heap->globalData()));
}
void IncrementalSweeper::startSweeping(const HashSet<MarkedBlock*>&)
diff --git a/Source/JavaScriptCore/heap/IncrementalSweeper.h b/Source/JavaScriptCore/heap/IncrementalSweeper.h
index 48f040409..80d674ca9 100644
--- a/Source/JavaScriptCore/heap/IncrementalSweeper.h
+++ b/Source/JavaScriptCore/heap/IncrementalSweeper.h
@@ -1,47 +1,37 @@
#ifndef IncrementalSweeper_h
#define IncrementalSweeper_h
+#include "HeapTimer.h"
#include "MarkedBlock.h"
#include <wtf/HashSet.h>
#include <wtf/PassOwnPtr.h>
#include <wtf/RetainPtr.h>
#include <wtf/Vector.h>
-#if USE(CF)
-#include <CoreFoundation/CoreFoundation.h>
-#endif
-
namespace JSC {
class Heap;
-class IncrementalSweeper {
+class IncrementalSweeper : public HeapTimer {
public:
- ~IncrementalSweeper();
-
static PassOwnPtr<IncrementalSweeper> create(Heap*);
void startSweeping(const HashSet<MarkedBlock*>& blockSnapshot);
+ virtual void doWork();
private:
#if USE(CF)
IncrementalSweeper(Heap*, CFRunLoopRef);
- static void timerDidFire(CFRunLoopTimerRef, void*);
void doSweep(double startTime);
void scheduleTimer();
void cancelTimer();
- Heap* m_heap;
unsigned m_currentBlockToSweepIndex;
- RetainPtr<CFRunLoopTimerRef> m_timer;
- RetainPtr<CFRunLoopRef> m_runLoop;
- CFRunLoopTimerContext m_context;
-
double m_lengthOfLastSweepIncrement;
Vector<MarkedBlock*> m_blocksToSweep;
#else
- IncrementalSweeper();
+ IncrementalSweeper(JSGlobalData*);
#endif
};
diff --git a/Source/JavaScriptCore/heap/ListableHandler.h b/Source/JavaScriptCore/heap/ListableHandler.h
index 41f18fbce..2cb03251f 100644
--- a/Source/JavaScriptCore/heap/ListableHandler.h
+++ b/Source/JavaScriptCore/heap/ListableHandler.h
@@ -24,6 +24,7 @@
#include <wtf/Locker.h>
#include <wtf/Noncopyable.h>
#include <wtf/ThreadingPrimitives.h>
+#include <wtf/TCSpinLock.h>
namespace JSC {
@@ -60,15 +61,12 @@ private:
List()
: m_first(0)
{
+ m_lock.Init();
}
void addThreadSafe(T* handler)
{
- // NOTE: If we ever want this to be faster, we could turn it into
- // a CAS loop, since this is a singly-linked-list that, in parallel
- // tracing mode, can only grow. I.e. we don't have to worry about
- // any ABA problems.
- MutexLocker locker(m_lock);
+ SpinLockHolder locker(&m_lock);
addNotThreadSafe(handler);
}
@@ -106,7 +104,7 @@ private:
m_first = handler;
}
- Mutex m_lock;
+ SpinLock m_lock;
T* m_first;
};
diff --git a/Source/JavaScriptCore/heap/MarkStack.cpp b/Source/JavaScriptCore/heap/MarkStack.cpp
index 678f1cb45..3eb02c4e8 100644
--- a/Source/JavaScriptCore/heap/MarkStack.cpp
+++ b/Source/JavaScriptCore/heap/MarkStack.cpp
@@ -36,6 +36,7 @@
#include "JSObject.h"
#include "ScopeChain.h"
#include "Structure.h"
+#include "UString.h"
#include "WriteBarrier.h"
#include <wtf/DataLog.h>
#include <wtf/MainThread.h>
@@ -45,6 +46,7 @@ namespace JSC {
MarkStackSegmentAllocator::MarkStackSegmentAllocator()
: m_nextFreeSegment(0)
{
+ m_lock.Init();
}
MarkStackSegmentAllocator::~MarkStackSegmentAllocator()
@@ -55,7 +57,7 @@ MarkStackSegmentAllocator::~MarkStackSegmentAllocator()
MarkStackSegment* MarkStackSegmentAllocator::allocate()
{
{
- MutexLocker locker(m_lock);
+ SpinLockHolder locker(&m_lock);
if (m_nextFreeSegment) {
MarkStackSegment* result = m_nextFreeSegment;
m_nextFreeSegment = result->m_previous;
@@ -68,7 +70,7 @@ MarkStackSegment* MarkStackSegmentAllocator::allocate()
void MarkStackSegmentAllocator::release(MarkStackSegment* segment)
{
- MutexLocker locker(m_lock);
+ SpinLockHolder locker(&m_lock);
segment->m_previous = m_nextFreeSegment;
m_nextFreeSegment = segment;
}
@@ -77,7 +79,7 @@ void MarkStackSegmentAllocator::shrinkReserve()
{
MarkStackSegment* segments;
{
- MutexLocker locker(m_lock);
+ SpinLockHolder locker(&m_lock);
segments = m_nextFreeSegment;
m_nextFreeSegment = 0;
}
@@ -141,23 +143,31 @@ bool MarkStackArray::refill()
return true;
}
-bool MarkStackArray::donateSomeCellsTo(MarkStackArray& other)
+void MarkStackArray::donateSomeCellsTo(MarkStackArray& other)
{
+ // Try to donate about 1 / 2 of our cells. To reduce copying costs,
+ // we prefer donating whole segments over donating individual cells,
+ // even if this skews away from our 1 / 2 target.
+
ASSERT(m_segmentCapacity == other.m_segmentCapacity);
+
+ size_t segmentsToDonate = (m_numberOfPreviousSegments + 2 - 1) / 2; // Round up to donate 1 / 1 previous segments.
+
+ if (!segmentsToDonate) {
+ size_t cellsToDonate = m_top / 2; // Round down to donate 0 / 1 cells.
+ while (cellsToDonate--) {
+ ASSERT(m_top);
+ other.append(removeLast());
+ }
+ return;
+ }
+
validatePrevious();
other.validatePrevious();
-
- // Fast check: see if the other mark stack already has enough segments.
- if (other.m_numberOfPreviousSegments + 1 >= Options::maximumNumberOfSharedSegments)
- return false;
-
- size_t numberOfCellsToKeep = Options::minimumNumberOfCellsToKeep;
- ASSERT(m_top > numberOfCellsToKeep || m_topSegment->m_previous);
-
- // Looks like we should donate! Give the other mark stack all of our
- // previous segments, and then top it off.
+
MarkStackSegment* previous = m_topSegment->m_previous;
- while (previous) {
+ while (segmentsToDonate--) {
+ ASSERT(previous);
ASSERT(m_numberOfPreviousSegments);
MarkStackSegment* current = previous;
@@ -169,23 +179,18 @@ bool MarkStackArray::donateSomeCellsTo(MarkStackArray& other)
m_numberOfPreviousSegments--;
other.m_numberOfPreviousSegments++;
}
- ASSERT(!m_numberOfPreviousSegments);
- m_topSegment->m_previous = 0;
+ m_topSegment->m_previous = previous;
+
validatePrevious();
other.validatePrevious();
-
- // Now top off. We want to keep at a minimum numberOfCellsToKeep, but if
- // we really have a lot of work, we give up half.
- if (m_top > numberOfCellsToKeep * 2)
- numberOfCellsToKeep = m_top / 2;
- while (m_top > numberOfCellsToKeep)
- other.append(removeLast());
-
- return true;
}
-void MarkStackArray::stealSomeCellsFrom(MarkStackArray& other)
+void MarkStackArray::stealSomeCellsFrom(MarkStackArray& other, size_t idleThreadCount)
{
+ // Try to steal 1 / Nth of the shared array, where N is the number of idle threads.
+ // To reduce copying costs, we prefer stealing a whole segment over stealing
+ // individual cells, even if this skews away from our 1 / N target.
+
ASSERT(m_segmentCapacity == other.m_segmentCapacity);
validatePrevious();
other.validatePrevious();
@@ -210,28 +215,42 @@ void MarkStackArray::stealSomeCellsFrom(MarkStackArray& other)
other.validatePrevious();
return;
}
-
- // Otherwise drain 1/Nth of the shared array where N is the number of
- // workers, or Options::minimumNumberOfCellsToKeep, whichever is bigger.
- size_t numberOfCellsToSteal = std::max((size_t)Options::minimumNumberOfCellsToKeep, other.size() / Options::numberOfGCMarkers);
+
+ size_t numberOfCellsToSteal = (other.size() + idleThreadCount - 1) / idleThreadCount; // Round up to steal 1 / 1.
while (numberOfCellsToSteal-- > 0 && other.canRemoveLast())
append(other.removeLast());
}
#if ENABLE(PARALLEL_GC)
-void MarkStackThreadSharedData::markingThreadMain()
+void MarkStackThreadSharedData::resetChildren()
+{
+ for (unsigned i = 0; i < m_markingThreadsMarkStack.size(); ++i)
+ m_markingThreadsMarkStack[i]->reset();
+}
+
+size_t MarkStackThreadSharedData::childVisitCount()
+{
+ unsigned long result = 0;
+ for (unsigned i = 0; i < m_markingThreadsMarkStack.size(); ++i)
+ result += m_markingThreadsMarkStack[i]->visitCount();
+ return result;
+}
+
+void MarkStackThreadSharedData::markingThreadMain(SlotVisitor* slotVisitor)
{
WTF::registerGCThread();
{
- SlotVisitor slotVisitor(*this);
- ParallelModeEnabler enabler(slotVisitor);
- slotVisitor.drainFromShared(SlotVisitor::SlaveDrain);
+ ParallelModeEnabler enabler(*slotVisitor);
+ slotVisitor->drainFromShared(SlotVisitor::SlaveDrain);
}
+ delete slotVisitor;
}
-void MarkStackThreadSharedData::markingThreadStartFunc(void* shared)
-{
- static_cast<MarkStackThreadSharedData*>(shared)->markingThreadMain();
+void MarkStackThreadSharedData::markingThreadStartFunc(void* myVisitor)
+{
+ SlotVisitor* slotVisitor = static_cast<SlotVisitor*>(myVisitor);
+
+ slotVisitor->sharedData().markingThreadMain(slotVisitor);
}
#endif
@@ -244,7 +263,9 @@ MarkStackThreadSharedData::MarkStackThreadSharedData(JSGlobalData* globalData)
{
#if ENABLE(PARALLEL_GC)
for (unsigned i = 1; i < Options::numberOfGCMarkers; ++i) {
- m_markingThreads.append(createThread(markingThreadStartFunc, this, "JavaScriptCore::Marking"));
+ SlotVisitor* slotVisitor = new SlotVisitor(*this);
+ m_markingThreadsMarkStack.append(slotVisitor);
+ m_markingThreads.append(createThread(markingThreadStartFunc, slotVisitor, "JavaScriptCore::Marking"));
ASSERT(m_markingThreads.last());
}
#endif
@@ -276,7 +297,6 @@ void MarkStackThreadSharedData::reset()
#else
ASSERT(m_opaqueRoots.isEmpty());
#endif
-
m_weakReferenceHarvesters.removeAll();
}
@@ -325,18 +345,31 @@ ALWAYS_INLINE static void visitChildren(SlotVisitor& visitor, const JSCell* cell
cell->methodTable()->visitChildren(const_cast<JSCell*>(cell), visitor);
}
-void SlotVisitor::donateSlow()
+void SlotVisitor::donateKnownParallel()
{
- // Refuse to donate if shared has more entries than I do.
- if (m_shared.m_sharedMarkStack.size() > m_stack.size())
+ // NOTE: Because we re-try often, we can afford to be conservative, and
+ // assume that donating is not profitable.
+
+ // Avoid locking when a thread reaches a dead end in the object graph.
+ if (m_stack.size() < 2)
return;
- MutexLocker locker(m_shared.m_markingLock);
- if (m_stack.donateSomeCellsTo(m_shared.m_sharedMarkStack)) {
- // Only wake up threads if the shared stack is big enough; otherwise assume that
- // it's more profitable for us to just scan this ourselves later.
- if (m_shared.m_sharedMarkStack.size() >= Options::sharedStackWakeupThreshold)
- m_shared.m_markingCondition.broadcast();
- }
+
+ // If there's already some shared work queued up, be conservative and assume
+ // that donating more is not profitable.
+ if (m_shared.m_sharedMarkStack.size())
+ return;
+
+ // If we're contending on the lock, be conservative and assume that another
+ // thread is already donating.
+ MutexTryLocker locker(m_shared.m_markingLock);
+ if (!locker.locked())
+ return;
+
+ // Otherwise, assume that a thread will go idle soon, and donate.
+ m_stack.donateSomeCellsTo(m_shared.m_sharedMarkStack);
+
+ if (m_shared.m_numberOfActiveParallelMarkers < Options::numberOfGCMarkers)
+ m_shared.m_markingCondition.broadcast();
}
void SlotVisitor::drain()
@@ -436,7 +469,8 @@ void SlotVisitor::drainFromShared(SharedDrainMode sharedDrainMode)
}
}
- m_stack.stealSomeCellsFrom(m_shared.m_sharedMarkStack);
+ size_t idleThreadCount = Options::numberOfGCMarkers - m_shared.m_numberOfActiveParallelMarkers;
+ m_stack.stealSomeCellsFrom(m_shared.m_sharedMarkStack, idleThreadCount);
m_shared.m_numberOfActiveParallelMarkers++;
}
@@ -461,8 +495,7 @@ void MarkStack::mergeOpaqueRoots()
void SlotVisitor::startCopying()
{
ASSERT(!m_copyBlock);
- if (!m_shared.m_copiedSpace->borrowBlock(&m_copyBlock))
- CRASH();
+ m_copyBlock = m_shared.m_copiedSpace->allocateBlockForCopyingPhase();
}
void* SlotVisitor::allocateNewSpace(void* ptr, size_t bytes)
@@ -483,8 +516,7 @@ void* SlotVisitor::allocateNewSpace(void* ptr, size_t 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_copiedSpace->doneFillingBlock(m_copyBlock);
- if (!m_shared.m_copiedSpace->borrowBlock(&m_copyBlock))
- CRASH();
+ m_copyBlock = m_shared.m_copiedSpace->allocateBlockForCopyingPhase();
}
return CopiedSpace::allocateFromBlock(m_copyBlock, bytes);
}
diff --git a/Source/JavaScriptCore/heap/MarkStack.h b/Source/JavaScriptCore/heap/MarkStack.h
index 0695b1b32..c3065e7d6 100644
--- a/Source/JavaScriptCore/heap/MarkStack.h
+++ b/Source/JavaScriptCore/heap/MarkStack.h
@@ -28,18 +28,46 @@
#include "CopiedSpace.h"
#include "HandleTypes.h"
-#include "Options.h"
#include "JSValue.h"
+#include "Options.h"
#include "Register.h"
#include "UnconditionalFinalizer.h"
#include "VTableSpectrum.h"
#include "WeakReferenceHarvester.h"
+#include <wtf/DataLog.h>
+#include <wtf/Forward.h>
#include <wtf/HashMap.h>
#include <wtf/HashSet.h>
-#include <wtf/Vector.h>
#include <wtf/Noncopyable.h>
#include <wtf/OSAllocator.h>
#include <wtf/PageBlock.h>
+#include <wtf/TCSpinLock.h>
+#include <wtf/text/StringHash.h>
+#include <wtf/Vector.h>
+
+#if ENABLE(OBJECT_MARK_LOGGING)
+#define MARK_LOG_MESSAGE0(message) dataLog(message)
+#define MARK_LOG_MESSAGE1(message, arg1) dataLog(message, arg1)
+#define MARK_LOG_MESSAGE2(message, arg1, arg2) dataLog(message, arg1, arg2)
+#define MARK_LOG_ROOT(visitor, rootName) \
+ dataLog("\n%s: ", rootName); \
+ (visitor).resetChildCount()
+#define MARK_LOG_PARENT(visitor, parent) \
+ dataLog("\n%p (%s): ", parent, parent->className() ? parent->className() : "unknown"); \
+ (visitor).resetChildCount()
+#define MARK_LOG_CHILD(visitor, child) \
+ if ((visitor).childCount()) \
+ dataLogString(", "); \
+ dataLog("%p", child); \
+ (visitor).incrementChildCount()
+#else
+#define MARK_LOG_MESSAGE0(message) do { } while (false)
+#define MARK_LOG_MESSAGE1(message, arg1) do { } while (false)
+#define MARK_LOG_MESSAGE2(message, arg1, arg2) do { } while (false)
+#define MARK_LOG_ROOT(visitor, rootName) do { } while (false)
+#define MARK_LOG_PARENT(visitor, parent) do { } while (false)
+#define MARK_LOG_CHILD(visitor, child) do { } while (false)
+#endif
namespace JSC {
@@ -85,7 +113,7 @@ namespace JSC {
void shrinkReserve();
private:
- Mutex m_lock;
+ SpinLock m_lock;
MarkStackSegment* m_nextFreeSegment;
};
@@ -102,10 +130,9 @@ namespace JSC {
bool isEmpty();
- bool canDonateSomeCells(); // Returns false if you should definitely not call doanteSomeCellsTo().
- bool donateSomeCellsTo(MarkStackArray& other); // Returns true if some cells were donated.
+ void donateSomeCellsTo(MarkStackArray& other);
- void stealSomeCellsFrom(MarkStackArray& other);
+ void stealSomeCellsFrom(MarkStackArray& other, size_t idleThreadCount);
size_t size();
@@ -171,13 +198,19 @@ namespace JSC {
~MarkStackThreadSharedData();
void reset();
+
+#if ENABLE(PARALLEL_GC)
+ void resetChildren();
+ size_t childVisitCount();
+ size_t childDupStrings();
+#endif
private:
friend class MarkStack;
friend class SlotVisitor;
#if ENABLE(PARALLEL_GC)
- void markingThreadMain();
+ void markingThreadMain(SlotVisitor*);
static void markingThreadStartFunc(void* heap);
#endif
@@ -187,6 +220,7 @@ namespace JSC {
MarkStackSegmentAllocator m_segmentAllocator;
Vector<ThreadIdentifier> m_markingThreads;
+ Vector<MarkStack*> m_markingThreadsMarkStack;
Mutex m_markingLock;
ThreadCondition m_markingCondition;
@@ -221,7 +255,8 @@ namespace JSC {
void addOpaqueRoot(void*);
bool containsOpaqueRoot(void*);
int opaqueRootCount();
-
+
+ MarkStackThreadSharedData& sharedData() { return m_shared; }
bool isEmpty() { return m_stack.isEmpty(); }
void reset();
@@ -242,6 +277,12 @@ namespace JSC {
m_shared.m_unconditionalFinalizers.addThreadSafe(unconditionalFinalizer);
}
+#if ENABLE(OBJECT_MARK_LOGGING)
+ inline void resetChildCount() { m_logChildCount = 0; }
+ inline unsigned childCount() { return m_logChildCount; }
+ inline void incrementChildCount() { m_logChildCount++; }
+#endif
+
protected:
JS_EXPORT_PRIVATE static void validate(JSCell*);
@@ -283,6 +324,10 @@ namespace JSC {
bool m_isInParallelMode;
MarkStackThreadSharedData& m_shared;
+
+#if ENABLE(OBJECT_MARK_LOGGING)
+ unsigned m_logChildCount;
+#endif
};
inline MarkStack::MarkStack(MarkStackThreadSharedData& shared)
@@ -369,22 +414,6 @@ namespace JSC {
return true;
}
- inline bool MarkStackArray::canDonateSomeCells()
- {
- size_t numberOfCellsToKeep = Options::minimumNumberOfCellsToKeep;
- // Another check: see if we have enough cells to warrant donation.
- if (m_top <= numberOfCellsToKeep) {
- // This indicates that we might not want to donate anything; check if we have
- // another full segment. If not, then don't donate.
- if (!m_topSegment->m_previous)
- return false;
-
- ASSERT(m_topSegment->m_previous->m_top == m_segmentCapacity);
- }
-
- return true;
- }
-
inline size_t MarkStackArray::size()
{
return m_top + m_segmentCapacity * m_numberOfPreviousSegments;
diff --git a/Source/JavaScriptCore/heap/MarkedAllocator.cpp b/Source/JavaScriptCore/heap/MarkedAllocator.cpp
index ac0cf570a..9552a54ea 100644
--- a/Source/JavaScriptCore/heap/MarkedAllocator.cpp
+++ b/Source/JavaScriptCore/heap/MarkedAllocator.cpp
@@ -47,6 +47,7 @@ inline void* MarkedAllocator::tryAllocateHelper()
inline void* MarkedAllocator::tryAllocate()
{
+ ASSERT(!m_heap->isBusy());
m_heap->m_operationInProgress = Allocation;
void* result = tryAllocateHelper();
m_heap->m_operationInProgress = NoOperation;
diff --git a/Source/JavaScriptCore/heap/MarkedBlock.cpp b/Source/JavaScriptCore/heap/MarkedBlock.cpp
index 0075f78d7..01e4237cb 100644
--- a/Source/JavaScriptCore/heap/MarkedBlock.cpp
+++ b/Source/JavaScriptCore/heap/MarkedBlock.cpp
@@ -114,6 +114,8 @@ MarkedBlock::FreeList MarkedBlock::sweep(SweepMode sweepMode)
{
HEAP_LOG_BLOCK_STATE_TRANSITION(this);
+ m_weakSet.sweep();
+
if (sweepMode == SweepOnly && !m_cellsNeedDestruction)
return FreeList();
diff --git a/Source/JavaScriptCore/heap/MarkedBlock.h b/Source/JavaScriptCore/heap/MarkedBlock.h
index b94c1e2b0..eb1cb681b 100644
--- a/Source/JavaScriptCore/heap/MarkedBlock.h
+++ b/Source/JavaScriptCore/heap/MarkedBlock.h
@@ -129,11 +129,9 @@ namespace JSC {
FreeList sweep(SweepMode = SweepOnly);
void shrink();
- void resetAllocator();
void visitWeakSet(HeapRootVisitor&);
void reapWeakSet();
- void sweepWeakSet();
// While allocating from a free list, MarkedBlock temporarily has bogus
// cell liveness data. To restore accurate cell liveness data, call one
@@ -274,11 +272,6 @@ namespace JSC {
m_weakSet.shrink();
}
- inline void MarkedBlock::resetAllocator()
- {
- m_weakSet.resetAllocator();
- }
-
inline void MarkedBlock::visitWeakSet(HeapRootVisitor& heapRootVisitor)
{
m_weakSet.visit(heapRootVisitor);
@@ -289,11 +282,6 @@ namespace JSC {
m_weakSet.reap();
}
- inline void MarkedBlock::sweepWeakSet()
- {
- m_weakSet.sweep();
- }
-
inline void MarkedBlock::didConsumeFreeList()
{
HEAP_LOG_BLOCK_STATE_TRANSITION(this);
diff --git a/Source/JavaScriptCore/heap/MarkedSpace.cpp b/Source/JavaScriptCore/heap/MarkedSpace.cpp
index 1604d2d63..42247a385 100644
--- a/Source/JavaScriptCore/heap/MarkedSpace.cpp
+++ b/Source/JavaScriptCore/heap/MarkedSpace.cpp
@@ -77,10 +77,6 @@ struct ReapWeakSet : MarkedBlock::VoidFunctor {
void operator()(MarkedBlock* block) { block->reapWeakSet(); }
};
-struct SweepWeakSet : MarkedBlock::VoidFunctor {
- void operator()(MarkedBlock* block) { block->sweepWeakSet(); }
-};
-
MarkedSpace::MarkedSpace(Heap* heap)
: m_heap(heap)
{
@@ -112,10 +108,6 @@ void MarkedSpace::lastChanceToFinalize()
forEachBlock<LastChanceToFinalize>();
}
-struct ResetAllocator : MarkedBlock::VoidFunctor {
- void operator()(MarkedBlock* block) { block->resetAllocator(); }
-};
-
void MarkedSpace::resetAllocators()
{
for (size_t cellSize = preciseStep; cellSize <= preciseCutoff; cellSize += preciseStep) {
@@ -127,8 +119,6 @@ void MarkedSpace::resetAllocators()
allocatorFor(cellSize).reset();
destructorAllocatorFor(cellSize).reset();
}
-
- forEachBlock<ResetAllocator>();
}
void MarkedSpace::visitWeakSets(HeapRootVisitor& heapRootVisitor)
@@ -142,11 +132,6 @@ void MarkedSpace::reapWeakSets()
forEachBlock<ReapWeakSet>();
}
-void MarkedSpace::sweepWeakSets()
-{
- forEachBlock<SweepWeakSet>();
-}
-
void MarkedSpace::canonicalizeCellLivenessData()
{
for (size_t cellSize = preciseStep; cellSize <= preciseCutoff; cellSize += preciseStep) {
diff --git a/Source/JavaScriptCore/heap/MarkedSpace.h b/Source/JavaScriptCore/heap/MarkedSpace.h
index 18b57c6d0..3f82bac96 100644
--- a/Source/JavaScriptCore/heap/MarkedSpace.h
+++ b/Source/JavaScriptCore/heap/MarkedSpace.h
@@ -85,7 +85,6 @@ public:
void visitWeakSets(HeapRootVisitor&);
void reapWeakSets();
- void sweepWeakSets();
MarkedBlockSet& blocks() { return m_blocks; }
diff --git a/Source/JavaScriptCore/heap/SlotVisitor.h b/Source/JavaScriptCore/heap/SlotVisitor.h
index 01eb219fc..715e2008c 100644
--- a/Source/JavaScriptCore/heap/SlotVisitor.h
+++ b/Source/JavaScriptCore/heap/SlotVisitor.h
@@ -68,15 +68,8 @@ public:
private:
void* allocateNewSpace(void*, size_t);
- void donateSlow();
-
- void donateKnownParallel()
- {
- if (!m_stack.canDonateSomeCells())
- return;
- donateSlow();
- }
-
+ void donateKnownParallel();
+
CopiedBlock* m_copyBlock;
};
diff --git a/Source/JavaScriptCore/heap/Weak.h b/Source/JavaScriptCore/heap/Weak.h
index e5e0a97ec..07698fd06 100644
--- a/Source/JavaScriptCore/heap/Weak.h
+++ b/Source/JavaScriptCore/heap/Weak.h
@@ -153,15 +153,15 @@ template<typename T> inline WeakImpl* Weak<T>::hashTableDeletedValue()
// This function helps avoid modifying a weak table while holding an iterator into it. (Object allocation
// can run a finalizer that modifies the table. We avoid that by requiring a pre-constructed object as our value.)
-template<typename T, typename U> inline void weakAdd(HashMap<T, Weak<U> >& map, const T& key, PassWeak<U> value)
+template<typename Map, typename Key, typename Value> inline void weakAdd(Map& map, const Key& key, Value value)
{
ASSERT(!map.get(key));
map.set(key, value); // The table may still have a zombie for value.
}
-template<typename T, typename U> inline void weakRemove(HashMap<T, Weak<U> >& map, const T& key, typename Weak<U>::GetType value)
+template<typename Map, typename Key, typename Value> inline void weakRemove(Map& map, const Key& key, Value value)
{
- typename HashMap<T, Weak<U> >::iterator it = map.find(key);
+ typename Map::iterator it = map.find(key);
ASSERT_UNUSED(value, value);
ASSERT(it != map.end());
ASSERT(it->second.was(value));
diff --git a/Source/JavaScriptCore/heap/WeakBlock.cpp b/Source/JavaScriptCore/heap/WeakBlock.cpp
index 685779d3a..8900e73df 100644
--- a/Source/JavaScriptCore/heap/WeakBlock.cpp
+++ b/Source/JavaScriptCore/heap/WeakBlock.cpp
@@ -69,7 +69,8 @@ void WeakBlock::lastChanceToFinalize()
void WeakBlock::sweep()
{
- if (!m_sweepResult.isNull())
+ // If a block is completely empty, a sweep won't have any effect.
+ if (isEmpty())
return;
SweepResult sweepResult;
diff --git a/Source/JavaScriptCore/heap/WeakSet.cpp b/Source/JavaScriptCore/heap/WeakSet.cpp
index 9374fd8ff..4a510b899 100644
--- a/Source/JavaScriptCore/heap/WeakSet.cpp
+++ b/Source/JavaScriptCore/heap/WeakSet.cpp
@@ -42,17 +42,10 @@ WeakSet::~WeakSet()
void WeakSet::sweep()
{
- WeakBlock* next;
- for (WeakBlock* block = m_blocks.head(); block; block = next) {
- next = block->next();
-
- // If a block is completely empty, a new sweep won't have any effect.
- if (block->isEmpty())
- continue;
-
- block->takeSweepResult(); // Force a new sweep by discarding the last sweep.
+ for (WeakBlock* block = m_blocks.head(); block; block = block->next())
block->sweep();
- }
+
+ resetAllocator();
}
WeakBlock::FreeCell* WeakSet::findAllocator()
@@ -69,7 +62,6 @@ WeakBlock::FreeCell* WeakSet::tryFindAllocator()
WeakBlock* block = m_nextAllocator;
m_nextAllocator = m_nextAllocator->next();
- block->sweep();
WeakBlock::SweepResult sweepResult = block->takeSweepResult();
if (sweepResult.freeList)
return sweepResult.freeList;
diff --git a/Source/JavaScriptCore/heap/WeakSet.h b/Source/JavaScriptCore/heap/WeakSet.h
index be9844a64..291d0aebd 100644
--- a/Source/JavaScriptCore/heap/WeakSet.h
+++ b/Source/JavaScriptCore/heap/WeakSet.h
@@ -118,6 +118,8 @@ inline void WeakSet::shrink()
if (block->isEmpty())
removeAllocator(block);
}
+
+ resetAllocator();
}
inline void WeakSet::resetAllocator()
diff --git a/Source/JavaScriptCore/interpreter/Interpreter.cpp b/Source/JavaScriptCore/interpreter/Interpreter.cpp
index ba72e9bba..b8610e7bf 100644
--- a/Source/JavaScriptCore/interpreter/Interpreter.cpp
+++ b/Source/JavaScriptCore/interpreter/Interpreter.cpp
@@ -1043,7 +1043,7 @@ NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSV
HandlerInfo* handler = 0;
while (isInterrupt || !(handler = codeBlock->handlerForBytecodeOffset(bytecodeOffset))) {
if (!unwindCallFrame(callFrame, exceptionValue, bytecodeOffset, codeBlock)) {
- if (Profiler* profiler = *Profiler::enabledProfilerReference())
+ if (Profiler* profiler = callFrame->globalData().enabledProfiler())
profiler->exceptionUnwind(callFrame);
callFrame->globalData().topCallFrame = callFrame;
return 0;
@@ -1051,7 +1051,7 @@ NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSV
}
callFrame->globalData().topCallFrame = callFrame;
- if (Profiler* profiler = *Profiler::enabledProfilerReference())
+ if (Profiler* profiler = callFrame->globalData().enabledProfiler())
profiler->exceptionUnwind(callFrame);
// Shrink the JS stack, in case stack overflow made it huge.
@@ -1097,7 +1097,7 @@ JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, S
ASSERT(!scopeChain->globalData->exception);
ASSERT(!callFrame->globalData().isCollectorBusy());
if (callFrame->globalData().isCollectorBusy())
- return jsNull();
+ CRASH();
if (m_reentryDepth >= MaxSmallThreadReentryDepth && m_reentryDepth >= callFrame->globalData().maxReentryDepth)
return checkedReturn(throwStackOverflowError(callFrame));
@@ -1218,9 +1218,8 @@ failedJSONP:
newCallFrame->setThisValue(thisObj);
TopCallFrameSetter topCallFrame(callFrame->globalData(), newCallFrame);
- Profiler** profiler = Profiler::enabledProfilerReference();
- if (*profiler)
- (*profiler)->willExecute(callFrame, program->sourceURL(), program->lineNo());
+ if (Profiler* profiler = callFrame->globalData().enabledProfiler())
+ profiler->willExecute(callFrame, program->sourceURL(), program->lineNo());
JSValue result;
{
@@ -1237,8 +1236,8 @@ failedJSONP:
m_reentryDepth--;
}
- if (*profiler)
- (*profiler)->didExecute(callFrame, program->sourceURL(), program->lineNo());
+ if (Profiler* profiler = callFrame->globalData().enabledProfiler())
+ profiler->didExecute(callFrame, program->sourceURL(), program->lineNo());
m_registerFile.shrink(oldEnd);
@@ -1291,9 +1290,8 @@ JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallT
TopCallFrameSetter topCallFrame(callFrame->globalData(), newCallFrame);
- Profiler** profiler = Profiler::enabledProfilerReference();
- if (*profiler)
- (*profiler)->willExecute(callFrame, function);
+ if (Profiler* profiler = callFrame->globalData().enabledProfiler())
+ profiler->willExecute(callFrame, function);
JSValue result;
{
@@ -1309,8 +1307,8 @@ JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallT
m_reentryDepth--;
}
- if (*profiler)
- (*profiler)->didExecute(callFrame, function);
+ if (Profiler* profiler = callFrame->globalData().enabledProfiler())
+ profiler->didExecute(callFrame, function);
m_registerFile.shrink(oldEnd);
return checkedReturn(result);
@@ -1324,9 +1322,8 @@ JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallT
DynamicGlobalObjectScope globalObjectScope(*scopeChain->globalData, scopeChain->globalObject.get());
- Profiler** profiler = Profiler::enabledProfilerReference();
- if (*profiler)
- (*profiler)->willExecute(callFrame, function);
+ if (Profiler* profiler = callFrame->globalData().enabledProfiler())
+ profiler->willExecute(callFrame, function);
JSValue result;
{
@@ -1334,8 +1331,8 @@ JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallT
result = JSValue::decode(callData.native.function(newCallFrame));
}
- if (*profiler)
- (*profiler)->didExecute(callFrame, function);
+ if (Profiler* profiler = callFrame->globalData().enabledProfiler())
+ profiler->didExecute(callFrame, function);
m_registerFile.shrink(oldEnd);
return checkedReturn(result);
@@ -1387,9 +1384,8 @@ JSObject* Interpreter::executeConstruct(CallFrame* callFrame, JSObject* construc
TopCallFrameSetter topCallFrame(callFrame->globalData(), newCallFrame);
- Profiler** profiler = Profiler::enabledProfilerReference();
- if (*profiler)
- (*profiler)->willExecute(callFrame, constructor);
+ if (Profiler* profiler = callFrame->globalData().enabledProfiler())
+ profiler->willExecute(callFrame, constructor);
JSValue result;
{
@@ -1405,8 +1401,8 @@ JSObject* Interpreter::executeConstruct(CallFrame* callFrame, JSObject* construc
m_reentryDepth--;
}
- if (*profiler)
- (*profiler)->didExecute(callFrame, constructor);
+ if (Profiler* profiler = callFrame->globalData().enabledProfiler())
+ profiler->didExecute(callFrame, constructor);
m_registerFile.shrink(oldEnd);
if (callFrame->hadException())
@@ -1423,9 +1419,8 @@ JSObject* Interpreter::executeConstruct(CallFrame* callFrame, JSObject* construc
DynamicGlobalObjectScope globalObjectScope(*scopeChain->globalData, scopeChain->globalObject.get());
- Profiler** profiler = Profiler::enabledProfilerReference();
- if (*profiler)
- (*profiler)->willExecute(callFrame, constructor);
+ if (Profiler* profiler = callFrame->globalData().enabledProfiler())
+ profiler->willExecute(callFrame, constructor);
JSValue result;
{
@@ -1433,8 +1428,8 @@ JSObject* Interpreter::executeConstruct(CallFrame* callFrame, JSObject* construc
result = JSValue::decode(constructData.native.function(newCallFrame));
}
- if (*profiler)
- (*profiler)->didExecute(callFrame, constructor);
+ if (Profiler* profiler = callFrame->globalData().enabledProfiler())
+ profiler->didExecute(callFrame, constructor);
m_registerFile.shrink(oldEnd);
if (callFrame->hadException())
@@ -1490,9 +1485,8 @@ JSValue Interpreter::execute(CallFrameClosure& closure)
if (closure.oldCallFrame->globalData().isCollectorBusy())
return jsNull();
closure.resetCallFrame();
- Profiler** profiler = Profiler::enabledProfilerReference();
- if (*profiler)
- (*profiler)->willExecute(closure.oldCallFrame, closure.function);
+ if (Profiler* profiler = closure.oldCallFrame->globalData().enabledProfiler())
+ profiler->willExecute(closure.oldCallFrame, closure.function);
TopCallFrameSetter topCallFrame(*closure.globalData, closure.newCallFrame);
@@ -1516,8 +1510,8 @@ JSValue Interpreter::execute(CallFrameClosure& closure)
m_reentryDepth--;
}
- if (*profiler)
- (*profiler)->didExecute(closure.oldCallFrame, closure.function);
+ if (Profiler* profiler = closure.oldCallFrame->globalData().enabledProfiler())
+ profiler->didExecute(closure.oldCallFrame, closure.function);
return checkedReturn(result);
}
@@ -1549,7 +1543,7 @@ JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSValue
for (ScopeChainNode* node = scopeChain; ; node = node->next.get()) {
ASSERT(node);
if (node->object->isVariableObject() && !node->object->isStaticScopeObject()) {
- variableObject = jsCast<JSVariableObject*>(node->object.get());
+ variableObject = jsCast<JSSymbolTableObject*>(node->object.get());
break;
}
}
@@ -1597,9 +1591,8 @@ JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSValue
TopCallFrameSetter topCallFrame(callFrame->globalData(), newCallFrame);
- Profiler** profiler = Profiler::enabledProfilerReference();
- if (*profiler)
- (*profiler)->willExecute(callFrame, eval->sourceURL(), eval->lineNo());
+ if (Profiler* profiler = callFrame->globalData().enabledProfiler())
+ profiler->willExecute(callFrame, eval->sourceURL(), eval->lineNo());
JSValue result;
{
@@ -1622,8 +1615,8 @@ JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSValue
m_reentryDepth--;
}
- if (*profiler)
- (*profiler)->didExecute(callFrame, eval->sourceURL(), eval->lineNo());
+ if (Profiler* profiler = callFrame->globalData().enabledProfiler())
+ profiler->didExecute(callFrame, eval->sourceURL(), eval->lineNo());
m_registerFile.shrink(oldEnd);
if (pushedScope)
@@ -1935,7 +1928,6 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
CodeBlock* codeBlock = callFrame->codeBlock();
Instruction* vPC = codeBlock->instructions().begin();
- Profiler** enabledProfilerReference = Profiler::enabledProfilerReference();
unsigned tickCount = globalData->timeoutChecker.ticksUntilNextCheck();
JSValue functionReturnValue;
@@ -2868,33 +2860,59 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
NEXT_INSTRUCTION();
}
DEFINE_OPCODE(op_get_global_var) {
- /* get_global_var dst(r) globalObject(c) index(n)
+ /* get_global_var dst(r) globalObject(c) registerPointer(n)
Gets the global var at global slot index and places it in register dst.
*/
int dst = vPC[1].u.operand;
- JSGlobalObject* scope = codeBlock->globalObject();
- ASSERT(scope->isGlobalObject());
- int index = vPC[2].u.operand;
+ WriteBarrier<Unknown>* registerPointer = vPC[2].u.registerPointer;
- callFrame->uncheckedR(dst) = scope->registerAt(index).get();
+ callFrame->uncheckedR(dst) = registerPointer->get();
vPC += OPCODE_LENGTH(op_get_global_var);
NEXT_INSTRUCTION();
}
+ DEFINE_OPCODE(op_get_global_var_watchable) {
+ /* get_global_var_watchable dst(r) globalObject(c) registerPointer(n)
+
+ Gets the global var at global slot index and places it in register dst.
+ */
+ int dst = vPC[1].u.operand;
+ WriteBarrier<Unknown>* registerPointer = vPC[2].u.registerPointer;
+
+ callFrame->uncheckedR(dst) = registerPointer->get();
+ vPC += OPCODE_LENGTH(op_get_global_var_watchable);
+ NEXT_INSTRUCTION();
+ }
DEFINE_OPCODE(op_put_global_var) {
- /* put_global_var globalObject(c) index(n) value(r)
+ /* put_global_var globalObject(c) registerPointer(n) value(r)
Puts value into global slot index.
*/
JSGlobalObject* scope = codeBlock->globalObject();
ASSERT(scope->isGlobalObject());
- int index = vPC[1].u.operand;
+ WriteBarrier<Unknown>* registerPointer = vPC[1].u.registerPointer;
int value = vPC[2].u.operand;
- scope->registerAt(index).set(*globalData, scope, callFrame->r(value).jsValue());
+ registerPointer->set(*globalData, scope, callFrame->r(value).jsValue());
vPC += OPCODE_LENGTH(op_put_global_var);
NEXT_INSTRUCTION();
}
+ DEFINE_OPCODE(op_put_global_var_check) {
+ /* put_global_var_check globalObject(c) registerPointer(n) value(r)
+
+ Puts value into global slot index. In JIT configurations this will
+ perform a watchpoint check. If we're running with the old interpreter,
+ this is not necessary; the interpreter never uses these watchpoints.
+ */
+ JSGlobalObject* scope = codeBlock->globalObject();
+ ASSERT(scope->isGlobalObject());
+ WriteBarrier<Unknown>* registerPointer = vPC[1].u.registerPointer;
+ int value = vPC[2].u.operand;
+
+ registerPointer->set(*globalData, scope, callFrame->r(value).jsValue());
+ vPC += OPCODE_LENGTH(op_put_global_var_check);
+ NEXT_INSTRUCTION();
+ }
DEFINE_OPCODE(op_get_scoped_var) {
/* get_scoped_var dst(r) index(n) skip(n)
@@ -5226,8 +5244,8 @@ skip_id_custom_self:
*/
int function = vPC[1].u.operand;
- if (*enabledProfilerReference)
- (*enabledProfilerReference)->willExecute(callFrame, callFrame->r(function).jsValue());
+ if (Profiler* profiler = globalData->enabledProfiler())
+ profiler->willExecute(callFrame, callFrame->r(function).jsValue());
vPC += OPCODE_LENGTH(op_profile_will_call);
NEXT_INSTRUCTION();
@@ -5240,8 +5258,8 @@ skip_id_custom_self:
*/
int function = vPC[1].u.operand;
- if (*enabledProfilerReference)
- (*enabledProfilerReference)->didExecute(callFrame, callFrame->r(function).jsValue());
+ if (Profiler* profiler = globalData->enabledProfiler())
+ profiler->didExecute(callFrame, callFrame->r(function).jsValue());
vPC += OPCODE_LENGTH(op_profile_did_call);
NEXT_INSTRUCTION();
diff --git a/Source/JavaScriptCore/jit/HostCallReturnValue.h b/Source/JavaScriptCore/jit/HostCallReturnValue.h
index fc9127faf..b134c73da 100644
--- a/Source/JavaScriptCore/jit/HostCallReturnValue.h
+++ b/Source/JavaScriptCore/jit/HostCallReturnValue.h
@@ -43,10 +43,10 @@
namespace JSC {
-extern "C" EncodedJSValue HOST_CALL_RETURN_VALUE_OPTION getHostCallReturnValue() REFERENCED_FROM_ASM;
+extern "C" EncodedJSValue HOST_CALL_RETURN_VALUE_OPTION getHostCallReturnValue() REFERENCED_FROM_ASM WTF_INTERNAL;
// This is a public declaration only to convince CLANG not to elide it.
-extern "C" EncodedJSValue HOST_CALL_RETURN_VALUE_OPTION getHostCallReturnValueWithExecState(ExecState*) REFERENCED_FROM_ASM;
+extern "C" EncodedJSValue HOST_CALL_RETURN_VALUE_OPTION getHostCallReturnValueWithExecState(ExecState*) REFERENCED_FROM_ASM WTF_INTERNAL;
inline void initializeHostCallReturnValue()
{
diff --git a/Source/JavaScriptCore/jit/JIT.cpp b/Source/JavaScriptCore/jit/JIT.cpp
index ff5615f44..2aca35146 100644
--- a/Source/JavaScriptCore/jit/JIT.cpp
+++ b/Source/JavaScriptCore/jit/JIT.cpp
@@ -259,6 +259,7 @@ void JIT::privateCompileMainPass()
DEFINE_OP(op_get_by_val)
DEFINE_OP(op_get_argument_by_val)
DEFINE_OP(op_get_by_pname)
+ DEFINE_OP(op_get_global_var_watchable)
DEFINE_OP(op_get_global_var)
DEFINE_OP(op_get_pnames)
DEFINE_OP(op_get_scoped_var)
@@ -324,6 +325,7 @@ void JIT::privateCompileMainPass()
DEFINE_OP(op_put_by_val)
DEFINE_OP(op_put_getter_setter)
DEFINE_OP(op_put_global_var)
+ DEFINE_OP(op_put_global_var_check)
DEFINE_OP(op_put_scoped_var)
DEFINE_OP(op_resolve)
DEFINE_OP(op_resolve_base)
@@ -481,6 +483,7 @@ void JIT::privateCompileSlowCases()
case op_put_by_id_transition_normal:
DEFINE_SLOWCASE_OP(op_put_by_id)
DEFINE_SLOWCASE_OP(op_put_by_val)
+ DEFINE_SLOWCASE_OP(op_put_global_var_check);
DEFINE_SLOWCASE_OP(op_resolve_global)
DEFINE_SLOWCASE_OP(op_resolve_global_dynamic)
DEFINE_SLOWCASE_OP(op_rshift)
@@ -715,11 +718,9 @@ JITCode JIT::privateCompile(CodePtr* functionEntryArityCheck, JITCompilationEffo
patchBuffer.link(iter->from, FunctionPtr(iter->to));
}
- if (m_codeBlock->needsCallReturnIndices()) {
- m_codeBlock->callReturnIndexVector().reserveCapacity(m_calls.size());
- for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter)
- m_codeBlock->callReturnIndexVector().append(CallReturnOffsetToBytecodeOffset(patchBuffer.returnAddressOffset(iter->from), iter->bytecodeOffset));
- }
+ m_codeBlock->callReturnIndexVector().reserveCapacity(m_calls.size());
+ for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter)
+ m_codeBlock->callReturnIndexVector().append(CallReturnOffsetToBytecodeOffset(patchBuffer.returnAddressOffset(iter->from), iter->bytecodeOffset));
m_codeBlock->setNumberOfStructureStubInfos(m_propertyAccessCompilationInfo.size());
for (unsigned i = 0; i < m_propertyAccessCompilationInfo.size(); ++i)
@@ -760,7 +761,8 @@ JITCode JIT::privateCompile(CodePtr* functionEntryArityCheck, JITCompilationEffo
if (m_codeBlock->codeType() == FunctionCode && functionEntryArityCheck)
*functionEntryArityCheck = patchBuffer.locationOf(arityCheck);
- CodeRef result = patchBuffer.finalizeCode();
+ CodeRef result = FINALIZE_CODE(
+ patchBuffer, ("Baseline JIT code for CodeBlock %p", m_codeBlock));
m_globalData->machineCodeBytesPerBytecodeWordForBaselineJIT.add(
static_cast<double>(result.size()) /
diff --git a/Source/JavaScriptCore/jit/JIT.h b/Source/JavaScriptCore/jit/JIT.h
index d1143105a..6491edbed 100644
--- a/Source/JavaScriptCore/jit/JIT.h
+++ b/Source/JavaScriptCore/jit/JIT.h
@@ -463,7 +463,7 @@ namespace JSC {
bool isMapped(int virtualRegisterIndex);
bool getMappedPayload(int virtualRegisterIndex, RegisterID& payload);
bool getMappedTag(int virtualRegisterIndex, RegisterID& tag);
-
+
void emitJumpSlowCaseIfNotJSCell(int virtualRegisterIndex);
void emitJumpSlowCaseIfNotJSCell(int virtualRegisterIndex, RegisterID tag);
@@ -599,6 +599,7 @@ namespace JSC {
void emit_op_get_argument_by_val(Instruction*);
void emit_op_get_by_pname(Instruction*);
void emit_op_get_global_var(Instruction*);
+ void emit_op_get_global_var_watchable(Instruction* instruction) { emit_op_get_global_var(instruction); }
void emit_op_get_scoped_var(Instruction*);
void emit_op_init_lazy_reg(Instruction*);
void emit_op_check_has_instance(Instruction*);
@@ -662,6 +663,7 @@ namespace JSC {
void emit_op_put_by_val(Instruction*);
void emit_op_put_getter_setter(Instruction*);
void emit_op_put_global_var(Instruction*);
+ void emit_op_put_global_var_check(Instruction*);
void emit_op_put_scoped_var(Instruction*);
void emit_op_resolve(Instruction*);
void emit_op_resolve_base(Instruction*);
@@ -739,6 +741,7 @@ namespace JSC {
void emitSlow_op_pre_inc(Instruction*, Vector<SlowCaseEntry>::iterator&);
void emitSlow_op_put_by_id(Instruction*, Vector<SlowCaseEntry>::iterator&);
void emitSlow_op_put_by_val(Instruction*, Vector<SlowCaseEntry>::iterator&);
+ void emitSlow_op_put_global_var_check(Instruction*, Vector<SlowCaseEntry>::iterator&);
void emitSlow_op_resolve_global(Instruction*, Vector<SlowCaseEntry>::iterator&);
void emitSlow_op_resolve_global_dynamic(Instruction*, Vector<SlowCaseEntry>::iterator&);
void emitSlow_op_rshift(Instruction*, Vector<SlowCaseEntry>::iterator&);
diff --git a/Source/JavaScriptCore/jit/JITCode.h b/Source/JavaScriptCore/jit/JITCode.h
index c85e02e80..478fcc7bf 100644
--- a/Source/JavaScriptCore/jit/JITCode.h
+++ b/Source/JavaScriptCore/jit/JITCode.h
@@ -29,6 +29,7 @@
#if ENABLE(JIT)
#include "CallFrame.h"
#include "JSValue.h"
+#include "Disassembler.h"
#include "MacroAssemblerCodeRef.h"
#include "Profiler.h"
#endif
@@ -105,6 +106,11 @@ namespace JSC {
return reinterpret_cast<char*>(m_ref.code().executableAddress()) + offset;
}
+ void* executableAddress() const
+ {
+ return executableAddressAtOffset(0);
+ }
+
void* dataAddressAtOffset(size_t offset) const
{
ASSERT(offset <= size()); // use <= instead of < because it is valid to ask for an address at the exclusive end of the code.
@@ -124,7 +130,7 @@ namespace JSC {
// Execute the code!
inline JSValue execute(RegisterFile* registerFile, CallFrame* callFrame, JSGlobalData* globalData)
{
- JSValue result = JSValue::decode(ctiTrampoline(m_ref.code().executableAddress(), registerFile, callFrame, 0, Profiler::enabledProfilerReference(), globalData));
+ JSValue result = JSValue::decode(ctiTrampoline(m_ref.code().executableAddress(), registerFile, callFrame, 0, 0, globalData));
return globalData->exception ? jsNull() : result;
}
@@ -138,6 +144,11 @@ namespace JSC {
ASSERT(m_ref.code().executableAddress());
return m_ref.size();
}
+
+ bool tryToDisassemble(const char* prefix) const
+ {
+ return m_ref.tryToDisassemble(prefix);
+ }
ExecutableMemoryHandle* getExecutableMemory()
{
diff --git a/Source/JavaScriptCore/jit/JITOpcodes.cpp b/Source/JavaScriptCore/jit/JITOpcodes.cpp
index aa2938cc2..ad7a56e12 100644
--- a/Source/JavaScriptCore/jit/JITOpcodes.cpp
+++ b/Source/JavaScriptCore/jit/JITOpcodes.cpp
@@ -211,7 +211,7 @@ PassRefPtr<ExecutableMemoryHandle> JIT::privateCompileCTIMachineTrampolines(JSGl
patchBuffer.link(callCallNotJSFunction, FunctionPtr(cti_op_call_NotJSFunction));
patchBuffer.link(callConstructNotJSFunction, FunctionPtr(cti_op_construct_NotJSConstruct));
- CodeRef finalCode = patchBuffer.finalizeCode();
+ CodeRef finalCode = FINALIZE_CODE(patchBuffer, ("JIT CTI machine trampolines"));
RefPtr<ExecutableMemoryHandle> executableMemory = finalCode.executableMemory();
trampolines->ctiVirtualCallLink = patchBuffer.trampolineAt(virtualCallLinkBegin);
@@ -1290,25 +1290,16 @@ void JIT::emitSlow_op_create_this(Instruction* currentInstruction, Vector<SlowCa
void JIT::emit_op_profile_will_call(Instruction* currentInstruction)
{
- peek(regT1, OBJECT_OFFSETOF(JITStackFrame, enabledProfilerReference) / sizeof(void*));
- Jump noProfiler = branchTestPtr(Zero, Address(regT1));
-
JITStubCall stubCall(this, cti_op_profile_will_call);
stubCall.addArgument(currentInstruction[1].u.operand, regT1);
stubCall.call();
- noProfiler.link(this);
-
}
void JIT::emit_op_profile_did_call(Instruction* currentInstruction)
{
- peek(regT1, OBJECT_OFFSETOF(JITStackFrame, enabledProfilerReference) / sizeof(void*));
- Jump noProfiler = branchTestPtr(Zero, Address(regT1));
-
JITStubCall stubCall(this, cti_op_profile_did_call);
stubCall.addArgument(currentInstruction[1].u.operand, regT1);
stubCall.call();
- noProfiler.link(this);
}
diff --git a/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp b/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp
index 12e47b2ee..57ef7ef2f 100644
--- a/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp
+++ b/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp
@@ -207,7 +207,7 @@ PassRefPtr<ExecutableMemoryHandle> JIT::privateCompileCTIMachineTrampolines(JSGl
patchBuffer.link(callCallNotJSFunction, FunctionPtr(cti_op_call_NotJSFunction));
patchBuffer.link(callConstructNotJSFunction, FunctionPtr(cti_op_construct_NotJSConstruct));
- CodeRef finalCode = patchBuffer.finalizeCode();
+ CodeRef finalCode = FINALIZE_CODE(patchBuffer, ("JIT CTI machine trampolines"));
RefPtr<ExecutableMemoryHandle> executableMemory = finalCode.executableMemory();
trampolines->ctiVirtualCallLink = patchBuffer.trampolineAt(virtualCallLinkBegin);
@@ -497,7 +497,7 @@ JIT::CodeRef JIT::privateCompileCTINativeCall(JSGlobalData* globalData, NativeFu
LinkBuffer patchBuffer(*m_globalData, this, GLOBAL_THUNK_ID);
patchBuffer.link(nativeCall, FunctionPtr(func));
- return patchBuffer.finalizeCode();
+ return FINALIZE_CODE(patchBuffer, ("JIT CTI native call"));
}
void JIT::emit_op_mov(Instruction* currentInstruction)
@@ -1590,24 +1590,16 @@ void JIT::emitSlow_op_convert_this(Instruction* currentInstruction, Vector<SlowC
void JIT::emit_op_profile_will_call(Instruction* currentInstruction)
{
- peek(regT2, OBJECT_OFFSETOF(JITStackFrame, enabledProfilerReference) / sizeof(void*));
- Jump noProfiler = branchTestPtr(Zero, Address(regT2));
-
JITStubCall stubCall(this, cti_op_profile_will_call);
stubCall.addArgument(currentInstruction[1].u.operand);
stubCall.call();
- noProfiler.link(this);
}
void JIT::emit_op_profile_did_call(Instruction* currentInstruction)
{
- peek(regT2, OBJECT_OFFSETOF(JITStackFrame, enabledProfilerReference) / sizeof(void*));
- Jump noProfiler = branchTestPtr(Zero, Address(regT2));
-
JITStubCall stubCall(this, cti_op_profile_did_call);
stubCall.addArgument(currentInstruction[1].u.operand);
stubCall.call();
- noProfiler.link(this);
}
void JIT::emit_op_get_arguments_length(Instruction* currentInstruction)
@@ -1672,7 +1664,7 @@ void JIT::emitSlow_op_get_argument_by_val(Instruction* currentInstruction, Vecto
JITStubCall stubCall(this, cti_op_get_by_val);
stubCall.addArgument(arguments);
stubCall.addArgument(property);
- stubCall.call(dst);
+ stubCall.callWithValueProfiling(dst);
}
} // namespace JSC
diff --git a/Source/JavaScriptCore/jit/JITPropertyAccess.cpp b/Source/JavaScriptCore/jit/JITPropertyAccess.cpp
index 5d39735af..7478f9184 100644
--- a/Source/JavaScriptCore/jit/JITPropertyAccess.cpp
+++ b/Source/JavaScriptCore/jit/JITPropertyAccess.cpp
@@ -30,12 +30,13 @@
#include "CodeBlock.h"
#include "GetterSetter.h"
+#include "Interpreter.h"
#include "JITInlineMethods.h"
#include "JITStubCall.h"
#include "JSArray.h"
#include "JSFunction.h"
#include "JSPropertyNameIterator.h"
-#include "Interpreter.h"
+#include "JSVariableObject.h"
#include "LinkBuffer.h"
#include "RepatchBuffer.h"
#include "ResultType.h"
@@ -87,7 +88,7 @@ JIT::CodeRef JIT::stringGetByValStubGenerator(JSGlobalData* globalData)
jit.ret();
LinkBuffer patchBuffer(*globalData, &jit, GLOBAL_THUNK_ID);
- return patchBuffer.finalizeCode();
+ return FINALIZE_CODE(patchBuffer, ("String get_by_val stub"));
}
void JIT::emit_op_get_by_val(Instruction* currentInstruction)
@@ -563,7 +564,10 @@ void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure
patchBuffer.link(m_calls[0].from, FunctionPtr(cti_op_put_by_id_transition_realloc));
}
- stubInfo->stubRoutine = patchBuffer.finalizeCode();
+ stubInfo->stubRoutine = FINALIZE_CODE(
+ patchBuffer,
+ ("Baseline put_by_id transition for CodeBlock %p, return point %p",
+ m_codeBlock, returnAddress.value()));
RepatchBuffer repatchBuffer(m_codeBlock);
repatchBuffer.relinkCallerToTrampoline(returnAddress, CodeLocationLabel(stubInfo->stubRoutine.code()));
}
@@ -624,7 +628,11 @@ void JIT::privateCompilePatchGetArrayLength(ReturnAddressPtr returnAddress)
patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(stubInfo->patch.baseline.u.get.putResult));
// Track the stub we have created so that it will be deleted later.
- stubInfo->stubRoutine = patchBuffer.finalizeCode();
+ stubInfo->stubRoutine = FINALIZE_CODE(
+ patchBuffer,
+ ("Basline JIT get_by_id array length stub for CodeBlock %p, return point %p",
+ m_codeBlock, stubInfo->hotPathBegin.labelAtOffset(
+ stubInfo->patch.baseline.u.get.putResult).executableAddress()));
// Finally patch the jump to slow case back in the hot path to jump here instead.
CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(stubInfo->patch.baseline.u.get.structureCheck);
@@ -687,7 +695,11 @@ void JIT::privateCompileGetByIdProto(StructureStubInfo* stubInfo, Structure* str
}
}
// Track the stub we have created so that it will be deleted later.
- stubInfo->stubRoutine = patchBuffer.finalizeCode();
+ stubInfo->stubRoutine = FINALIZE_CODE(
+ patchBuffer,
+ ("Baseline JIT get_by_id proto stub for CodeBlock %p, return point %p",
+ m_codeBlock, stubInfo->hotPathBegin.labelAtOffset(
+ stubInfo->patch.baseline.u.get.putResult).executableAddress()));
// Finally patch the jump to slow case back in the hot path to jump here instead.
CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(stubInfo->patch.baseline.u.get.structureCheck);
@@ -744,7 +756,11 @@ void JIT::privateCompileGetByIdSelfList(StructureStubInfo* stubInfo, Polymorphic
// On success return back to the hot patch code, at a point it will perform the store to dest for us.
patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(stubInfo->patch.baseline.u.get.putResult));
- MacroAssemblerCodeRef stubCode = patchBuffer.finalizeCode();
+ MacroAssemblerCodeRef stubCode = FINALIZE_CODE(
+ patchBuffer,
+ ("Baseline JIT get_by_id list stub for CodeBlock %p, return point %p",
+ m_codeBlock, stubInfo->hotPathBegin.labelAtOffset(
+ stubInfo->patch.baseline.u.get.putResult).executableAddress()));
polymorphicStructures->list[currentIndex].set(*m_globalData, m_codeBlock->ownerExecutable(), stubCode, structure, isDirect);
@@ -810,7 +826,11 @@ void JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, Polymorphi
// On success return back to the hot patch code, at a point it will perform the store to dest for us.
patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(stubInfo->patch.baseline.u.get.putResult));
- MacroAssemblerCodeRef stubCode = patchBuffer.finalizeCode();
+ MacroAssemblerCodeRef stubCode = FINALIZE_CODE(
+ patchBuffer,
+ ("Baseline JIT get_by_id proto list stub for CodeBlock %p, return point %p",
+ m_codeBlock, stubInfo->hotPathBegin.labelAtOffset(
+ stubInfo->patch.baseline.u.get.putResult).executableAddress()));
prototypeStructures->list[currentIndex].set(*m_globalData, m_codeBlock->ownerExecutable(), stubCode, structure, prototypeStructure, isDirect);
// Finally patch the jump to slow case back in the hot path to jump here instead.
@@ -879,7 +899,11 @@ void JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, Polymorphi
// On success return back to the hot patch code, at a point it will perform the store to dest for us.
patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(stubInfo->patch.baseline.u.get.putResult));
- CodeRef stubRoutine = patchBuffer.finalizeCode();
+ CodeRef stubRoutine = FINALIZE_CODE(
+ patchBuffer,
+ ("Baseline JIT get_by_id chain list stub for CodeBlock %p, return point %p",
+ m_codeBlock, stubInfo->hotPathBegin.labelAtOffset(
+ stubInfo->patch.baseline.u.get.putResult).executableAddress()));
// Track the stub we have created so that it will be deleted later.
prototypeStructures->list[currentIndex].set(callFrame->globalData(), m_codeBlock->ownerExecutable(), stubRoutine, structure, chain, isDirect);
@@ -946,7 +970,11 @@ void JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* str
patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(stubInfo->patch.baseline.u.get.putResult));
// Track the stub we have created so that it will be deleted later.
- CodeRef stubRoutine = patchBuffer.finalizeCode();
+ CodeRef stubRoutine = FINALIZE_CODE(
+ patchBuffer,
+ ("Baseline JIT get_by_id chain stub for CodeBlock %p, return point %p",
+ m_codeBlock, stubInfo->hotPathBegin.labelAtOffset(
+ stubInfo->patch.baseline.u.get.putResult).executableAddress()));
stubInfo->stubRoutine = stubRoutine;
// Finally patch the jump to slow case back in the hot path to jump here instead.
@@ -1010,9 +1038,7 @@ void JIT::emit_op_put_scoped_var(Instruction* currentInstruction)
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);
+ loadPtr(currentInstruction[2].u.registerPointer, regT0);
emitValueProfilingSite();
emitPutVirtualRegister(currentInstruction[1].u.operand);
}
@@ -1022,11 +1048,33 @@ void JIT::emit_op_put_global_var(Instruction* currentInstruction)
JSGlobalObject* globalObject = m_codeBlock->globalObject();
emitGetVirtualRegister(currentInstruction[2].u.operand, regT0);
+
+ storePtr(regT0, currentInstruction[1].u.registerPointer);
+ if (Heap::isWriteBarrierEnabled())
+ emitWriteBarrier(globalObject, regT0, regT2, ShouldFilterImmediates, WriteBarrierForVariableAccess);
+}
- move(TrustedImmPtr(globalObject), regT1);
- loadPtr(Address(regT1, JSVariableObject::offsetOfRegisters()), regT1);
- storePtr(regT0, Address(regT1, currentInstruction[1].u.operand * sizeof(Register)));
- emitWriteBarrier(globalObject, regT0, regT2, ShouldFilterImmediates, WriteBarrierForVariableAccess);
+void JIT::emit_op_put_global_var_check(Instruction* currentInstruction)
+{
+ emitGetVirtualRegister(currentInstruction[2].u.operand, regT0);
+
+ addSlowCase(branchTest8(NonZero, AbsoluteAddress(currentInstruction[3].u.predicatePointer)));
+
+ JSGlobalObject* globalObject = m_codeBlock->globalObject();
+
+ storePtr(regT0, currentInstruction[1].u.registerPointer);
+ if (Heap::isWriteBarrierEnabled())
+ emitWriteBarrier(globalObject, regT0, regT2, ShouldFilterImmediates, WriteBarrierForVariableAccess);
+}
+
+void JIT::emitSlow_op_put_global_var_check(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ linkSlowCase(iter);
+
+ JITStubCall stubCall(this, cti_op_put_global_var_check);
+ stubCall.addArgument(regT0);
+ stubCall.addArgument(TrustedImm32(currentInstruction[4].u.operand));
+ stubCall.call();
}
void JIT::resetPatchGetById(RepatchBuffer& repatchBuffer, StructureStubInfo* stubInfo)
diff --git a/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp b/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp
index bd57484c4..a44c576c5 100644
--- a/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp
+++ b/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp
@@ -30,12 +30,13 @@
#include "JIT.h"
#include "CodeBlock.h"
+#include "Interpreter.h"
#include "JITInlineMethods.h"
#include "JITStubCall.h"
#include "JSArray.h"
#include "JSFunction.h"
#include "JSPropertyNameIterator.h"
-#include "Interpreter.h"
+#include "JSVariableObject.h"
#include "LinkBuffer.h"
#include "RepatchBuffer.h"
#include "ResultType.h"
@@ -193,7 +194,7 @@ JIT::CodeRef JIT::stringGetByValStubGenerator(JSGlobalData* globalData)
jit.ret();
LinkBuffer patchBuffer(*globalData, &jit, GLOBAL_THUNK_ID);
- return patchBuffer.finalizeCode();
+ return FINALIZE_CODE(patchBuffer, ("String get_by_val stub"));
}
void JIT::emit_op_get_by_val(Instruction* currentInstruction)
@@ -544,7 +545,10 @@ void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure
patchBuffer.link(m_calls[0].from, FunctionPtr(cti_op_put_by_id_transition_realloc));
}
- stubInfo->stubRoutine = patchBuffer.finalizeCode();
+ stubInfo->stubRoutine = FINALIZE_CODE(
+ patchBuffer,
+ ("Baseline put_by_id transition stub for CodeBlock %p, return point %p",
+ m_codeBlock, returnAddress.value()));
RepatchBuffer repatchBuffer(m_codeBlock);
repatchBuffer.relinkCallerToTrampoline(returnAddress, CodeLocationLabel(stubInfo->stubRoutine.code()));
}
@@ -610,7 +614,11 @@ void JIT::privateCompilePatchGetArrayLength(ReturnAddressPtr returnAddress)
patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(stubInfo->patch.baseline.u.get.putResult));
// Track the stub we have created so that it will be deleted later.
- stubInfo->stubRoutine = patchBuffer.finalizeCode();
+ stubInfo->stubRoutine = FINALIZE_CODE(
+ patchBuffer,
+ ("Baseline get_by_id array length stub for CodeBlock %p, return point %p",
+ m_codeBlock, stubInfo->hotPathBegin.labelAtOffset(
+ stubInfo->patch.baseline.u.get.putResult).executableAddress()));
// Finally patch the jump to slow case back in the hot path to jump here instead.
CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(stubInfo->patch.baseline.u.get.structureCheck);
@@ -676,7 +684,11 @@ void JIT::privateCompileGetByIdProto(StructureStubInfo* stubInfo, Structure* str
}
// Track the stub we have created so that it will be deleted later.
- stubInfo->stubRoutine = patchBuffer.finalizeCode();
+ stubInfo->stubRoutine = FINALIZE_CODE(
+ patchBuffer,
+ ("Baseline get_by_id proto stub for CodeBlock %p, return point %p",
+ m_codeBlock, stubInfo->hotPathBegin.labelAtOffset(
+ stubInfo->patch.baseline.u.get.putResult).executableAddress()));
// Finally patch the jump to slow case back in the hot path to jump here instead.
CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(stubInfo->patch.baseline.u.get.structureCheck);
@@ -734,7 +746,11 @@ void JIT::privateCompileGetByIdSelfList(StructureStubInfo* stubInfo, Polymorphic
// On success return back to the hot patch code, at a point it will perform the store to dest for us.
patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(stubInfo->patch.baseline.u.get.putResult));
- CodeRef stubRoutine = patchBuffer.finalizeCode();
+ MacroAssemblerCodeRef stubRoutine = FINALIZE_CODE(
+ patchBuffer,
+ ("Baseline get_by_id self list stub for CodeBlock %p, return point %p",
+ m_codeBlock, stubInfo->hotPathBegin.labelAtOffset(
+ stubInfo->patch.baseline.u.get.putResult).executableAddress()));
polymorphicStructures->list[currentIndex].set(*m_globalData, m_codeBlock->ownerExecutable(), stubRoutine, structure, isDirect);
@@ -799,7 +815,11 @@ void JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, Polymorphi
// On success return back to the hot patch code, at a point it will perform the store to dest for us.
patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(stubInfo->patch.baseline.u.get.putResult));
- CodeRef stubRoutine = patchBuffer.finalizeCode();
+ MacroAssemblerCodeRef stubRoutine = FINALIZE_CODE(
+ patchBuffer,
+ ("Baseline get_by_id proto list stub for CodeBlock %p, return point %p",
+ m_codeBlock, stubInfo->hotPathBegin.labelAtOffset(
+ stubInfo->patch.baseline.u.get.putResult).executableAddress()));
prototypeStructures->list[currentIndex].set(callFrame->globalData(), m_codeBlock->ownerExecutable(), stubRoutine, structure, prototypeStructure, isDirect);
@@ -869,7 +889,11 @@ void JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, Polymorphi
// On success return back to the hot patch code, at a point it will perform the store to dest for us.
patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(stubInfo->patch.baseline.u.get.putResult));
- CodeRef stubRoutine = patchBuffer.finalizeCode();
+ MacroAssemblerCodeRef stubRoutine = FINALIZE_CODE(
+ patchBuffer,
+ ("Baseline get_by_id chain list stub for CodeBlock %p, return point %p",
+ m_codeBlock, stubInfo->hotPathBegin.labelAtOffset(
+ stubInfo->patch.baseline.u.get.putResult).executableAddress()));
// Track the stub we have created so that it will be deleted later.
prototypeStructures->list[currentIndex].set(callFrame->globalData(), m_codeBlock->ownerExecutable(), stubRoutine, structure, chain, isDirect);
@@ -935,7 +959,11 @@ void JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* str
patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(stubInfo->patch.baseline.u.get.putResult));
// Track the stub we have created so that it will be deleted later.
- CodeRef stubRoutine = patchBuffer.finalizeCode();
+ MacroAssemblerCodeRef stubRoutine = FINALIZE_CODE(
+ patchBuffer,
+ ("Baseline get_by_id chain stub for CodeBlock %p, return point %p",
+ m_codeBlock, stubInfo->hotPathBegin.labelAtOffset(
+ stubInfo->patch.baseline.u.get.putResult).executableAddress()));
stubInfo->stubRoutine = stubRoutine;
// Finally patch the jump to slow case back in the hot path to jump here instead.
@@ -1060,13 +1088,10 @@ void JIT::emit_op_put_scoped_var(Instruction* currentInstruction)
void JIT::emit_op_get_global_var(Instruction* currentInstruction)
{
int dst = currentInstruction[1].u.operand;
- JSGlobalObject* globalObject = m_codeBlock->globalObject();
- ASSERT(globalObject->isGlobalObject());
- int index = currentInstruction[2].u.operand;
+ WriteBarrier<Unknown>* registerPointer = currentInstruction[2].u.registerPointer;
- loadPtr(&globalObject->m_registers, regT2);
-
- emitLoad(index, regT1, regT0, regT2);
+ load32(registerPointer->tagPointer(), regT1);
+ load32(registerPointer->payloadPointer(), regT0);
emitValueProfilingSite();
emitStore(dst, regT1, regT0);
map(m_bytecodeOffset + OPCODE_LENGTH(op_get_global_var), dst, regT1, regT0);
@@ -1074,21 +1099,55 @@ void JIT::emit_op_get_global_var(Instruction* currentInstruction)
void JIT::emit_op_put_global_var(Instruction* currentInstruction)
{
- int index = currentInstruction[1].u.operand;
+ WriteBarrier<Unknown>* registerPointer = currentInstruction[1].u.registerPointer;
int value = currentInstruction[2].u.operand;
JSGlobalObject* globalObject = m_codeBlock->globalObject();
emitLoad(value, regT1, regT0);
- move(TrustedImmPtr(globalObject), regT2);
-
- emitWriteBarrier(globalObject, regT1, regT3, ShouldFilterImmediates, WriteBarrierForVariableAccess);
+
+ if (Heap::isWriteBarrierEnabled()) {
+ move(TrustedImmPtr(globalObject), regT2);
+
+ emitWriteBarrier(globalObject, regT1, regT3, ShouldFilterImmediates, WriteBarrierForVariableAccess);
+ }
- loadPtr(Address(regT2, JSVariableObject::offsetOfRegisters()), regT2);
- emitStore(index, regT1, regT0, regT2);
+ store32(regT1, registerPointer->tagPointer());
+ store32(regT0, registerPointer->payloadPointer());
map(m_bytecodeOffset + OPCODE_LENGTH(op_put_global_var), value, regT1, regT0);
}
+void JIT::emit_op_put_global_var_check(Instruction* currentInstruction)
+{
+ WriteBarrier<Unknown>* registerPointer = currentInstruction[1].u.registerPointer;
+ int value = currentInstruction[2].u.operand;
+
+ JSGlobalObject* globalObject = m_codeBlock->globalObject();
+
+ emitLoad(value, regT1, regT0);
+
+ addSlowCase(branchTest8(NonZero, AbsoluteAddress(currentInstruction[3].u.predicatePointer)));
+
+ if (Heap::isWriteBarrierEnabled()) {
+ move(TrustedImmPtr(globalObject), regT2);
+ emitWriteBarrier(globalObject, regT1, regT3, ShouldFilterImmediates, WriteBarrierForVariableAccess);
+ }
+
+ store32(regT1, registerPointer->tagPointer());
+ store32(regT0, registerPointer->payloadPointer());
+ unmap();
+}
+
+void JIT::emitSlow_op_put_global_var_check(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ linkSlowCase(iter);
+
+ JITStubCall stubCall(this, cti_op_put_global_var_check);
+ stubCall.addArgument(regT1, regT0);
+ stubCall.addArgument(TrustedImm32(currentInstruction[4].u.operand));
+ stubCall.call();
+}
+
void JIT::resetPatchGetById(RepatchBuffer& repatchBuffer, StructureStubInfo* stubInfo)
{
repatchBuffer.relink(stubInfo->callReturnLocation, cti_op_get_by_id);
diff --git a/Source/JavaScriptCore/jit/JITStubs.cpp b/Source/JavaScriptCore/jit/JITStubs.cpp
index e75f2825c..12f3ec344 100644
--- a/Source/JavaScriptCore/jit/JITStubs.cpp
+++ b/Source/JavaScriptCore/jit/JITStubs.cpp
@@ -112,7 +112,7 @@ asm (
HIDE_SYMBOL(ctiVMThrowTrampoline) "\n"
SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
"movl %esp, %ecx" "\n"
- "call " SYMBOL_STRING_RELOCATION(cti_vm_throw) "\n"
+ "call " LOCAL_REFERENCE(cti_vm_throw) "\n"
"int3" "\n"
);
@@ -172,7 +172,7 @@ asm (
HIDE_SYMBOL(ctiVMThrowTrampoline) "\n"
SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
"movq %rsp, %rdi" "\n"
- "call " SYMBOL_STRING_RELOCATION(cti_vm_throw) "\n"
+ "call " LOCAL_REFERENCE(cti_vm_throw) "\n"
"int3" "\n"
);
@@ -205,7 +205,7 @@ SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
#define REGISTER_FILE_OFFSET 0x60
#define CALLFRAME_OFFSET 0x64
#define EXCEPTION_OFFSET 0x64
-#define ENABLE_PROFILER_REFERENCE_OFFSET 0x68
+#define FIRST_STACK_ARGUMENT 0x68
#elif (COMPILER(GCC) || COMPILER(MSVC) || COMPILER(RVCT)) && CPU(ARM_TRADITIONAL)
@@ -225,7 +225,7 @@ COMPILE_ASSERT(offsetof(struct JITStackFrame, code) == 0x50, JITStackFrame_code_
extern "C" {
- __declspec(naked) EncodedJSValue ctiTrampoline(void* code, RegisterFile*, CallFrame*, void* /*unused1*/, Profiler**, JSGlobalData*)
+ __declspec(naked) EncodedJSValue ctiTrampoline(void* code, RegisterFile*, CallFrame*, void* /*unused1*/, void* /*unused2*/, JSGlobalData*)
{
__asm {
push ebp;
@@ -284,12 +284,11 @@ extern "C" {
#define REGISTER_FILE_OFFSET 84
#define CALLFRAME_OFFSET 88
#define EXCEPTION_OFFSET 92
-#define ENABLE_PROFILER_REFERENCE_OFFSET 96
#define GLOBAL_DATA_OFFSET 100
#define STACK_LENGTH 104
#elif CPU(SH4)
#define SYMBOL_STRING(name) #name
-/* code (r4), RegisterFile* (r5), CallFrame* (r6), JSValue* exception (r7), Profiler**(sp), JSGlobalData (sp)*/
+/* code (r4), RegisterFile* (r5), CallFrame* (r6), void* unused1 (r7), void* unused2(sp), JSGlobalData (sp)*/
asm volatile (
".text\n"
@@ -417,7 +416,7 @@ asm (
HIDE_SYMBOL(ctiVMThrowTrampoline) "\n"
SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
"movq %rsp, %rdi" "\n"
- "call " SYMBOL_STRING_RELOCATION(cti_vm_throw) "\n"
+ "call " LOCAL_REFERENCE(cti_vm_throw) "\n"
"int3" "\n"
);
@@ -465,9 +464,7 @@ SYMBOL_STRING(ctiTrampoline) ":" "\n"
"sw $5," STRINGIZE_VALUE_OF(REGISTER_FILE_OFFSET) "($29) # store registerFile to current stack" "\n"
"sw $6," STRINGIZE_VALUE_OF(CALLFRAME_OFFSET) "($29) # store callFrame to curent stack" "\n"
"sw $7," STRINGIZE_VALUE_OF(EXCEPTION_OFFSET) "($29) # store exception to current stack" "\n"
- "lw $8," STRINGIZE_VALUE_OF(STACK_LENGTH + 16) "($29) # load enableProfilerReference from previous stack" "\n"
"lw $9," STRINGIZE_VALUE_OF(STACK_LENGTH + 20) "($29) # load globalData from previous stack" "\n"
- "sw $8," STRINGIZE_VALUE_OF(ENABLE_PROFILER_REFERENCE_OFFSET) "($29) # store enableProfilerReference to current stack" "\n"
"jalr $25" "\n"
"sw $9," STRINGIZE_VALUE_OF(GLOBAL_DATA_OFFSET) "($29) # store globalData to current stack" "\n"
"lw $16," STRINGIZE_VALUE_OF(PRESERVED_S0_OFFSET) "($29)" "\n"
@@ -543,7 +540,7 @@ HIDE_SYMBOL(ctiTrampoline) "\n"
".thumb" "\n"
".thumb_func " THUMB_FUNC_PARAM(ctiTrampoline) "\n"
SYMBOL_STRING(ctiTrampoline) ":" "\n"
- "sub sp, sp, #" STRINGIZE_VALUE_OF(ENABLE_PROFILER_REFERENCE_OFFSET) "\n"
+ "sub sp, sp, #" STRINGIZE_VALUE_OF(FIRST_STACK_ARGUMENT) "\n"
"str lr, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_RETURN_ADDRESS_OFFSET) "]" "\n"
"str r4, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R4_OFFSET) "]" "\n"
"str r5, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R5_OFFSET) "]" "\n"
@@ -568,7 +565,7 @@ SYMBOL_STRING(ctiTrampoline) ":" "\n"
"ldr r5, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R5_OFFSET) "]" "\n"
"ldr r4, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R4_OFFSET) "]" "\n"
"ldr lr, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_RETURN_ADDRESS_OFFSET) "]" "\n"
- "add sp, sp, #" STRINGIZE_VALUE_OF(ENABLE_PROFILER_REFERENCE_OFFSET) "\n"
+ "add sp, sp, #" STRINGIZE_VALUE_OF(FIRST_STACK_ARGUMENT) "\n"
"bx lr" "\n"
".align 2" "\n"
".globl " SYMBOL_STRING(ctiTrampolineEnd) "\n"
@@ -587,7 +584,7 @@ HIDE_SYMBOL(ctiVMThrowTrampoline) "\n"
".thumb_func " THUMB_FUNC_PARAM(ctiVMThrowTrampoline) "\n"
SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
"mov r0, sp" "\n"
- "bl " SYMBOL_STRING_RELOCATION(cti_vm_throw) "\n"
+ "bl " LOCAL_REFERENCE(cti_vm_throw) "\n"
"ldr r11, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R11_OFFSET) "]" "\n"
"ldr r10, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R10_OFFSET) "]" "\n"
"ldr r9, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R9_OFFSET) "]" "\n"
@@ -597,7 +594,7 @@ SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
"ldr r5, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R5_OFFSET) "]" "\n"
"ldr r4, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R4_OFFSET) "]" "\n"
"ldr lr, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_RETURN_ADDRESS_OFFSET) "]" "\n"
- "add sp, sp, #" STRINGIZE_VALUE_OF(ENABLE_PROFILER_REFERENCE_OFFSET) "\n"
+ "add sp, sp, #" STRINGIZE_VALUE_OF(FIRST_STACK_ARGUMENT) "\n"
"bx lr" "\n"
);
@@ -618,7 +615,7 @@ SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
"ldr r5, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R5_OFFSET) "]" "\n"
"ldr r4, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R4_OFFSET) "]" "\n"
"ldr lr, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_RETURN_ADDRESS_OFFSET) "]" "\n"
- "add sp, sp, #" STRINGIZE_VALUE_OF(ENABLE_PROFILER_REFERENCE_OFFSET) "\n"
+ "add sp, sp, #" STRINGIZE_VALUE_OF(FIRST_STACK_ARGUMENT) "\n"
"bx lr" "\n"
);
@@ -661,10 +658,10 @@ SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
#elif COMPILER(RVCT) && CPU(ARM_THUMB2)
-__asm EncodedJSValue ctiTrampoline(void*, RegisterFile*, CallFrame*, JSValue*, Profiler**, JSGlobalData*)
+__asm EncodedJSValue ctiTrampoline(void*, RegisterFile*, CallFrame*, void* /*unused1*/, void* /*unused2*/, JSGlobalData*)
{
PRESERVE8
- sub sp, sp, # ENABLE_PROFILER_REFERENCE_OFFSET
+ sub sp, sp, # FIRST_STACK_ARGUMENT
str lr, [sp, # PRESERVED_RETURN_ADDRESS_OFFSET ]
str r4, [sp, # PRESERVED_R4_OFFSET ]
str r5, [sp, # PRESERVED_R5_OFFSET ]
@@ -689,7 +686,7 @@ __asm EncodedJSValue ctiTrampoline(void*, RegisterFile*, CallFrame*, JSValue*, P
ldr r5, [sp, # PRESERVED_R5_OFFSET ]
ldr r4, [sp, # PRESERVED_R4_OFFSET ]
ldr lr, [sp, # PRESERVED_RETURN_ADDRESS_OFFSET ]
- add sp, sp, # ENABLE_PROFILER_REFERENCE_OFFSET
+ add sp, sp, # FIRST_STACK_ARGUMENT
bx lr
}
@@ -708,7 +705,7 @@ __asm void ctiVMThrowTrampoline()
ldr r5, [sp, # PRESERVED_R5_OFFSET ]
ldr r4, [sp, # PRESERVED_R4_OFFSET ]
ldr lr, [sp, # PRESERVED_RETURN_ADDRESS_OFFSET ]
- add sp, sp, # ENABLE_PROFILER_REFERENCE_OFFSET
+ add sp, sp, # FIRST_STACK_ARGUMENT
bx lr
}
@@ -725,13 +722,13 @@ __asm void ctiOpThrowNotCaught()
ldr r5, [sp, # PRESERVED_R5_OFFSET ]
ldr r4, [sp, # PRESERVED_R4_OFFSET ]
ldr lr, [sp, # PRESERVED_RETURN_ADDRESS_OFFSET ]
- add sp, sp, # ENABLE_PROFILER_REFERENCE_OFFSET
+ add sp, sp, # FIRST_STACK_ARGUMENT
bx lr
}
#elif COMPILER(RVCT) && CPU(ARM_TRADITIONAL)
-__asm EncodedJSValue ctiTrampoline(void*, RegisterFile*, CallFrame*, void* /*unused1*/, Profiler**, JSGlobalData*)
+__asm EncodedJSValue ctiTrampoline(void*, RegisterFile*, CallFrame*, void* /*unused1*/, void* /*unused2*/, JSGlobalData*)
{
ARM
stmdb sp!, {r1-r3}
@@ -800,7 +797,7 @@ JITThunks::JITThunks(JSGlobalData* globalData)
ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, registerFile) == REGISTER_FILE_OFFSET);
ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, callFrame) == CALLFRAME_OFFSET);
// The fifth argument is the first item already on the stack.
- ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, enabledProfilerReference) == ENABLE_PROFILER_REFERENCE_OFFSET);
+ ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, unused1) == FIRST_STACK_ARGUMENT);
ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, thunkReturnAddress) == THUNK_RETURN_ADDRESS_OFFSET);
@@ -820,7 +817,6 @@ JITThunks::JITThunks(JSGlobalData* globalData)
ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, registerFile) == REGISTER_FILE_OFFSET);
ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, callFrame) == CALLFRAME_OFFSET);
ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, unused1) == EXCEPTION_OFFSET);
- ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, enabledProfilerReference) == ENABLE_PROFILER_REFERENCE_OFFSET);
ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, globalData) == GLOBAL_DATA_OFFSET);
#endif
@@ -870,6 +866,7 @@ NEVER_INLINE void JITThunks::tryCachePutByID(CallFrame* callFrame, CodeBlock* co
normalizePrototypeChain(callFrame, baseCell);
StructureChain* prototypeChain = structure->prototypeChain(callFrame);
+ ASSERT(structure->previousID()->transitionWatchpointSetHasBeenInvalidated());
stubInfo->initPutByIdTransition(callFrame->globalData(), codeBlock->ownerExecutable(), structure->previousID(), structure, prototypeChain, direct);
JIT::compilePutByIdTransition(callFrame->scopeChain()->globalData, codeBlock, stubInfo, structure->previousID(), structure, slot.cachedOffset(), prototypeChain, returnAddress, direct);
return;
@@ -949,7 +946,7 @@ NEVER_INLINE void JITThunks::tryCacheGetByID(CallFrame* callFrame, CodeBlock* co
offset = slotBaseObject->structure()->get(callFrame->globalData(), propertyName);
}
- stubInfo->initGetByIdProto(callFrame->globalData(), codeBlock->ownerExecutable(), structure, slotBaseObject->structure());
+ stubInfo->initGetByIdProto(callFrame->globalData(), codeBlock->ownerExecutable(), structure, slotBaseObject->structure(), slot.cachedPropertyType() == PropertySlot::Value);
ASSERT(!structure->isDictionary());
ASSERT(!slotBaseObject->structure()->isDictionary());
@@ -965,7 +962,7 @@ NEVER_INLINE void JITThunks::tryCacheGetByID(CallFrame* callFrame, CodeBlock* co
}
StructureChain* prototypeChain = structure->prototypeChain(callFrame);
- stubInfo->initGetByIdChain(callFrame->globalData(), codeBlock->ownerExecutable(), structure, prototypeChain);
+ stubInfo->initGetByIdChain(callFrame->globalData(), codeBlock->ownerExecutable(), structure, prototypeChain, count, slot.cachedPropertyType() == PropertySlot::Value);
JIT::compileGetByIdChain(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, structure, prototypeChain, count, propertyName, slot, offset, returnAddress);
}
@@ -2355,16 +2352,16 @@ DEFINE_STUB_FUNCTION(void, op_profile_will_call)
{
STUB_INIT_STACK_FRAME(stackFrame);
- ASSERT(*stackFrame.enabledProfilerReference);
- (*stackFrame.enabledProfilerReference)->willExecute(stackFrame.callFrame, stackFrame.args[0].jsValue());
+ if (Profiler* profiler = stackFrame.globalData->enabledProfiler())
+ profiler->willExecute(stackFrame.callFrame, stackFrame.args[0].jsValue());
}
DEFINE_STUB_FUNCTION(void, op_profile_did_call)
{
STUB_INIT_STACK_FRAME(stackFrame);
- ASSERT(*stackFrame.enabledProfilerReference);
- (*stackFrame.enabledProfilerReference)->didExecute(stackFrame.callFrame, stackFrame.args[0].jsValue());
+ if (Profiler* profiler = stackFrame.globalData->enabledProfiler())
+ profiler->didExecute(stackFrame.callFrame, stackFrame.args[0].jsValue());
}
DEFINE_STUB_FUNCTION(JSObject*, op_new_array)
@@ -2381,6 +2378,15 @@ DEFINE_STUB_FUNCTION(JSObject*, op_new_array_buffer)
return constructArray(stackFrame.callFrame, stackFrame.callFrame->codeBlock()->constantBuffer(stackFrame.args[0].int32()), stackFrame.args[1].int32());
}
+DEFINE_STUB_FUNCTION(void, op_put_global_var_check)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ CallFrame* callFrame = stackFrame.callFrame;
+ CodeBlock* codeBlock = callFrame->codeBlock();
+ symbolTablePut(codeBlock->globalObject(), callFrame, codeBlock->identifier(stackFrame.args[1].int32()), stackFrame.args[0].jsValue(), true);
+}
+
DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve)
{
STUB_INIT_STACK_FRAME(stackFrame);
diff --git a/Source/JavaScriptCore/jit/JITStubs.h b/Source/JavaScriptCore/jit/JITStubs.h
index 664338fd3..251776075 100644
--- a/Source/JavaScriptCore/jit/JITStubs.h
+++ b/Source/JavaScriptCore/jit/JITStubs.h
@@ -104,7 +104,7 @@ namespace JSC {
RegisterFile* registerFile;
CallFrame* callFrame;
void* unused1;
- Profiler** enabledProfilerReference;
+ void* unused2;
JSGlobalData* globalData;
void* savedRBX;
@@ -140,7 +140,7 @@ namespace JSC {
RegisterFile* registerFile;
CallFrame* callFrame;
void* unused1;
- Profiler** enabledProfilerReference;
+ void* unused2;
JSGlobalData* globalData;
// When JIT code makes a call, it pushes its return address just below the rest of the stack.
@@ -171,7 +171,7 @@ namespace JSC {
CallFrame* callFrame;
// These arguments passed on the stack.
- Profiler** enabledProfilerReference;
+ void* unused1;
JSGlobalData* globalData;
ReturnAddressPtr* returnAddressSlot() { return &thunkReturnAddress; }
@@ -199,7 +199,7 @@ namespace JSC {
void* unused1;
// These arguments passed on the stack.
- Profiler** enabledProfilerReference;
+ void* unused2;
JSGlobalData* globalData;
// When JIT code makes a call, it pushes its return address just below the rest of the stack.
@@ -231,7 +231,7 @@ namespace JSC {
void* unused1;
// These arguments passed on the stack.
- Profiler** enabledProfilerReference;
+ void* unused2;
JSGlobalData* globalData;
ReturnAddressPtr* returnAddressSlot() { return &thunkReturnAddress; }
@@ -252,7 +252,7 @@ namespace JSC {
RegisterFile* registerFile;
CallFrame* callFrame;
JSValue* exception;
- Profiler** enabledProfilerReference;
+ void* unused1;
JSGlobalData* globalData;
ReturnAddressPtr* returnAddressSlot() { return &thunkReturnAddress; }
@@ -282,7 +282,7 @@ namespace JSC {
extern "C" void ctiVMThrowTrampoline();
extern "C" void ctiOpThrowNotCaught();
- extern "C" EncodedJSValue ctiTrampoline(void* code, RegisterFile*, CallFrame*, void* /*unused1*/, Profiler**, JSGlobalData*);
+ extern "C" EncodedJSValue ctiTrampoline(void* code, RegisterFile*, CallFrame*, void* /*unused1*/, void* /*unused2*/, JSGlobalData*);
#if ENABLE(DFG_JIT)
extern "C" void ctiTrampolineEnd();
@@ -341,129 +341,130 @@ namespace JSC {
};
extern "C" {
- EncodedJSValue JIT_STUB cti_op_add(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_bitand(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_bitor(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_bitxor(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_call_NotJSFunction(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_call_eval(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_construct_NotJSConstruct(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_create_this(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_convert_this(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_create_arguments(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_del_by_id(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_del_by_val(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_div(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_get_by_id(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_get_by_id_array_fail(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_get_by_id_custom_stub(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_get_by_id_generic(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_get_by_id_getter_stub(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_get_by_id_method_check(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_get_by_id_method_check_update(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_get_by_id_proto_fail(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_get_by_id_proto_list(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_get_by_id_proto_list_full(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_get_by_id_self_fail(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_get_by_id_string_fail(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_get_by_val(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_get_by_val_string(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_in(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_instanceof(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_is_boolean(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_is_function(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_is_number(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_is_object(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_is_string(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_is_undefined(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_less(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_lesseq(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_greater(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_greatereq(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_lshift(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_mod(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_mul(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_negate(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_not(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_nstricteq(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_post_dec(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_post_inc(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_pre_dec(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_pre_inc(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_resolve(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_resolve_base(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_resolve_base_strict_put(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_ensure_property_exists(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_resolve_global(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_resolve_global_dynamic(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_resolve_skip(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_resolve_with_base(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_resolve_with_this(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_rshift(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_strcat(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_stricteq(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_sub(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_to_jsnumber(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_to_primitive(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_typeof(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_urshift(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_to_object(STUB_ARGS_DECLARATION);
- JSObject* JIT_STUB cti_op_new_array(STUB_ARGS_DECLARATION);
- JSObject* JIT_STUB cti_op_new_array_buffer(STUB_ARGS_DECLARATION);
- JSObject* JIT_STUB cti_op_new_func(STUB_ARGS_DECLARATION);
- JSObject* JIT_STUB cti_op_new_func_exp(STUB_ARGS_DECLARATION);
- JSObject* JIT_STUB cti_op_new_object(STUB_ARGS_DECLARATION);
- JSObject* JIT_STUB cti_op_new_regexp(STUB_ARGS_DECLARATION);
- JSObject* JIT_STUB cti_op_push_activation(STUB_ARGS_DECLARATION);
- JSObject* JIT_STUB cti_op_push_new_scope(STUB_ARGS_DECLARATION);
- JSObject* JIT_STUB cti_op_push_scope(STUB_ARGS_DECLARATION);
- JSObject* JIT_STUB cti_op_put_by_id_transition_realloc(STUB_ARGS_DECLARATION);
- JSPropertyNameIterator* JIT_STUB cti_op_get_pnames(STUB_ARGS_DECLARATION);
- int JIT_STUB cti_op_eq(STUB_ARGS_DECLARATION);
- int JIT_STUB cti_op_eq_strings(STUB_ARGS_DECLARATION);
- int JIT_STUB cti_op_jless(STUB_ARGS_DECLARATION);
- int JIT_STUB cti_op_jlesseq(STUB_ARGS_DECLARATION);
- int JIT_STUB cti_op_jgreater(STUB_ARGS_DECLARATION);
- int JIT_STUB cti_op_jgreatereq(STUB_ARGS_DECLARATION);
- int JIT_STUB cti_op_jtrue(STUB_ARGS_DECLARATION);
- void* JIT_STUB cti_op_load_varargs(STUB_ARGS_DECLARATION);
- int JIT_STUB cti_timeout_check(STUB_ARGS_DECLARATION);
- int JIT_STUB cti_has_property(STUB_ARGS_DECLARATION);
- void JIT_STUB cti_op_check_has_instance(STUB_ARGS_DECLARATION);
- void JIT_STUB cti_op_debug(STUB_ARGS_DECLARATION);
- void JIT_STUB cti_op_end(STUB_ARGS_DECLARATION);
- void JIT_STUB cti_op_jmp_scopes(STUB_ARGS_DECLARATION);
- void JIT_STUB cti_op_pop_scope(STUB_ARGS_DECLARATION);
- void JIT_STUB cti_op_profile_did_call(STUB_ARGS_DECLARATION);
- void JIT_STUB cti_op_profile_will_call(STUB_ARGS_DECLARATION);
- void JIT_STUB cti_op_put_by_id(STUB_ARGS_DECLARATION);
- void JIT_STUB cti_op_put_by_id_fail(STUB_ARGS_DECLARATION);
- void JIT_STUB cti_op_put_by_id_generic(STUB_ARGS_DECLARATION);
- void JIT_STUB cti_op_put_by_id_direct(STUB_ARGS_DECLARATION);
- void JIT_STUB cti_op_put_by_id_direct_fail(STUB_ARGS_DECLARATION);
- void JIT_STUB cti_op_put_by_id_direct_generic(STUB_ARGS_DECLARATION);
- 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_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);
+ EncodedJSValue JIT_STUB cti_op_add(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_bitand(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_bitor(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_bitxor(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_call_NotJSFunction(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_call_eval(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_construct_NotJSConstruct(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_create_this(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_convert_this(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_create_arguments(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_del_by_id(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_del_by_val(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_div(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_get_by_id(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_get_by_id_array_fail(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_get_by_id_custom_stub(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_get_by_id_generic(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_get_by_id_getter_stub(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_get_by_id_method_check(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_get_by_id_method_check_update(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_get_by_id_proto_fail(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_get_by_id_proto_list(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_get_by_id_proto_list_full(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_get_by_id_self_fail(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_get_by_id_string_fail(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_get_by_val(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_get_by_val_string(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_in(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_instanceof(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_is_boolean(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_is_function(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_is_number(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_is_object(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_is_string(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_is_undefined(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_less(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_lesseq(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_greater(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_greatereq(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_lshift(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_mod(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_mul(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_negate(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_not(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_nstricteq(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_post_dec(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_post_inc(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_pre_dec(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_pre_inc(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_resolve(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_resolve_base(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_resolve_base_strict_put(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_ensure_property_exists(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_resolve_global(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_resolve_global_dynamic(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_resolve_skip(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_resolve_with_base(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_resolve_with_this(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_rshift(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_strcat(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_stricteq(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_sub(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_to_jsnumber(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_to_primitive(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_typeof(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_op_urshift(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ EncodedJSValue JIT_STUB cti_to_object(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ JSObject* JIT_STUB cti_op_new_array(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ JSObject* JIT_STUB cti_op_new_array_buffer(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ JSObject* JIT_STUB cti_op_new_func(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ JSObject* JIT_STUB cti_op_new_func_exp(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ JSObject* JIT_STUB cti_op_new_object(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ JSObject* JIT_STUB cti_op_new_regexp(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ JSObject* JIT_STUB cti_op_push_activation(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ JSObject* JIT_STUB cti_op_push_new_scope(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ JSObject* JIT_STUB cti_op_push_scope(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ JSObject* JIT_STUB cti_op_put_by_id_transition_realloc(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ JSPropertyNameIterator* JIT_STUB cti_op_get_pnames(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ int JIT_STUB cti_op_eq(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ int JIT_STUB cti_op_eq_strings(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ int JIT_STUB cti_op_jless(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ int JIT_STUB cti_op_jlesseq(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ int JIT_STUB cti_op_jgreater(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ int JIT_STUB cti_op_jgreatereq(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ int JIT_STUB cti_op_jtrue(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ void* JIT_STUB cti_op_load_varargs(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ int JIT_STUB cti_timeout_check(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ int JIT_STUB cti_has_property(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ void JIT_STUB cti_op_check_has_instance(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ void JIT_STUB cti_op_debug(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ void JIT_STUB cti_op_end(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ void JIT_STUB cti_op_jmp_scopes(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ void JIT_STUB cti_op_pop_scope(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ void JIT_STUB cti_op_profile_did_call(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ void JIT_STUB cti_op_profile_will_call(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ void JIT_STUB cti_op_put_by_id(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ void JIT_STUB cti_op_put_by_id_fail(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ void JIT_STUB cti_op_put_by_id_generic(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ void JIT_STUB cti_op_put_by_id_direct(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ void JIT_STUB cti_op_put_by_id_direct_fail(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ void JIT_STUB cti_op_put_by_id_direct_generic(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ void JIT_STUB cti_op_put_by_index(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ void JIT_STUB cti_op_put_by_val(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ void JIT_STUB cti_op_put_getter_setter(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ void JIT_STUB cti_op_put_global_var_check(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ void JIT_STUB cti_op_tear_off_activation(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ void JIT_STUB cti_op_tear_off_arguments(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ void JIT_STUB cti_op_throw_reference_error(STUB_ARGS_DECLARATION) WTF_INTERNAL;
#if ENABLE(DFG_JIT)
- void JIT_STUB cti_optimize_from_loop(STUB_ARGS_DECLARATION);
- void JIT_STUB cti_optimize_from_ret(STUB_ARGS_DECLARATION);
+ void JIT_STUB cti_optimize_from_loop(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ void JIT_STUB cti_optimize_from_ret(STUB_ARGS_DECLARATION) WTF_INTERNAL;
#endif
- void* JIT_STUB cti_op_call_arityCheck(STUB_ARGS_DECLARATION);
- void* JIT_STUB cti_op_construct_arityCheck(STUB_ARGS_DECLARATION);
- void* JIT_STUB cti_op_call_jitCompile(STUB_ARGS_DECLARATION);
- void* JIT_STUB cti_op_construct_jitCompile(STUB_ARGS_DECLARATION);
- void* JIT_STUB cti_op_switch_char(STUB_ARGS_DECLARATION);
- void* JIT_STUB cti_op_switch_imm(STUB_ARGS_DECLARATION);
- void* JIT_STUB cti_op_switch_string(STUB_ARGS_DECLARATION);
- void* JIT_STUB cti_op_throw(STUB_ARGS_DECLARATION);
- void* JIT_STUB cti_register_file_check(STUB_ARGS_DECLARATION);
- void* JIT_STUB cti_vm_lazyLinkCall(STUB_ARGS_DECLARATION);
- void* JIT_STUB cti_vm_lazyLinkConstruct(STUB_ARGS_DECLARATION);
- void* JIT_STUB cti_vm_throw(STUB_ARGS_DECLARATION) REFERENCED_FROM_ASM;
+ void* JIT_STUB cti_op_call_arityCheck(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ void* JIT_STUB cti_op_construct_arityCheck(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ void* JIT_STUB cti_op_call_jitCompile(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ void* JIT_STUB cti_op_construct_jitCompile(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ void* JIT_STUB cti_op_switch_char(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ void* JIT_STUB cti_op_switch_imm(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ void* JIT_STUB cti_op_switch_string(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ void* JIT_STUB cti_op_throw(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ void* JIT_STUB cti_register_file_check(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ void* JIT_STUB cti_vm_lazyLinkCall(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ void* JIT_STUB cti_vm_lazyLinkConstruct(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ void* JIT_STUB cti_vm_throw(STUB_ARGS_DECLARATION) REFERENCED_FROM_ASM WTF_INTERNAL;
} // extern "C"
#endif // ENABLE(JIT)
diff --git a/Source/JavaScriptCore/jit/SpecializedThunkJIT.h b/Source/JavaScriptCore/jit/SpecializedThunkJIT.h
index 74e94ea3c..c98e57d12 100644
--- a/Source/JavaScriptCore/jit/SpecializedThunkJIT.h
+++ b/Source/JavaScriptCore/jit/SpecializedThunkJIT.h
@@ -132,13 +132,13 @@ namespace JSC {
ret();
}
- MacroAssemblerCodeRef finalize(JSGlobalData& globalData, MacroAssemblerCodePtr fallback)
+ MacroAssemblerCodeRef finalize(JSGlobalData& globalData, MacroAssemblerCodePtr fallback, const char* thunkKind)
{
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);
- return patchBuffer.finalizeCode();
+ return FINALIZE_CODE(patchBuffer, ("Specialized thunk for %s", thunkKind));
}
// Assumes that the target function uses fpRegister0 as the first argument
diff --git a/Source/JavaScriptCore/jit/ThunkGenerators.cpp b/Source/JavaScriptCore/jit/ThunkGenerators.cpp
index e46ba809c..c440b5157 100644
--- a/Source/JavaScriptCore/jit/ThunkGenerators.cpp
+++ b/Source/JavaScriptCore/jit/ThunkGenerators.cpp
@@ -78,7 +78,7 @@ MacroAssemblerCodeRef charCodeAtThunkGenerator(JSGlobalData* globalData)
SpecializedThunkJIT jit(1, globalData);
stringCharLoad(jit);
jit.returnInt32(SpecializedThunkJIT::regT0);
- return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall());
+ return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall(), "charCodeAt");
}
MacroAssemblerCodeRef charAtThunkGenerator(JSGlobalData* globalData)
@@ -87,7 +87,7 @@ MacroAssemblerCodeRef charAtThunkGenerator(JSGlobalData* globalData)
stringCharLoad(jit);
charToString(jit, globalData, SpecializedThunkJIT::regT0, SpecializedThunkJIT::regT0, SpecializedThunkJIT::regT1);
jit.returnJSCell(SpecializedThunkJIT::regT0);
- return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall());
+ return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall(), "charAt");
}
MacroAssemblerCodeRef fromCharCodeThunkGenerator(JSGlobalData* globalData)
@@ -97,7 +97,7 @@ MacroAssemblerCodeRef fromCharCodeThunkGenerator(JSGlobalData* globalData)
jit.loadInt32Argument(0, SpecializedThunkJIT::regT0);
charToString(jit, globalData, SpecializedThunkJIT::regT0, SpecializedThunkJIT::regT0, SpecializedThunkJIT::regT1);
jit.returnJSCell(SpecializedThunkJIT::regT0);
- return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall());
+ return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall(), "fromCharCode");
}
MacroAssemblerCodeRef sqrtThunkGenerator(JSGlobalData* globalData)
@@ -109,7 +109,7 @@ MacroAssemblerCodeRef sqrtThunkGenerator(JSGlobalData* globalData)
jit.loadDoubleArgument(0, SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0);
jit.sqrtDouble(SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::fpRegT0);
jit.returnDouble(SpecializedThunkJIT::fpRegT0);
- return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall());
+ return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall(), "sqrt");
}
@@ -135,7 +135,7 @@ double jsRound(double d)
".globl " SYMBOL_STRING(function##Thunk) "\n" \
HIDE_SYMBOL(function##Thunk) "\n" \
SYMBOL_STRING(function##Thunk) ":" "\n" \
- "call " SYMBOL_STRING_RELOCATION(function) "\n" \
+ "call " GLOBAL_REFERENCE(function) "\n" \
"ret\n" \
);\
extern "C" { \
@@ -152,7 +152,7 @@ double jsRound(double d)
SYMBOL_STRING(function##Thunk) ":" "\n" \
"subl $8, %esp\n" \
"movsd %xmm0, (%esp) \n" \
- "call " SYMBOL_STRING_RELOCATION(function) "\n" \
+ "call " GLOBAL_REFERENCE(function) "\n" \
"fstpl (%esp) \n" \
"movsd (%esp), %xmm0 \n" \
"addl $8, %esp\n" \
@@ -175,6 +175,11 @@ defineUnaryDoubleOpWrapper(log);
defineUnaryDoubleOpWrapper(floor);
defineUnaryDoubleOpWrapper(ceil);
+static const double oneConstant = 1.0;
+static const double negativeHalfConstant = -0.5;
+static const double zeroConstant = 0.0;
+static const double halfConstant = 0.5;
+
MacroAssemblerCodeRef floorThunkGenerator(JSGlobalData* globalData)
{
SpecializedThunkJIT jit(1, globalData);
@@ -185,13 +190,26 @@ MacroAssemblerCodeRef floorThunkGenerator(JSGlobalData* globalData)
jit.returnInt32(SpecializedThunkJIT::regT0);
nonIntJump.link(&jit);
jit.loadDoubleArgument(0, SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0);
- jit.callDoubleToDouble(UnaryDoubleOpWrapper(floor));
+ SpecializedThunkJIT::Jump intResult;
SpecializedThunkJIT::JumpList doubleResult;
+ if (jit.supportsFloatingPointTruncate()) {
+ jit.loadDouble(&zeroConstant, SpecializedThunkJIT::fpRegT1);
+ doubleResult.append(jit.branchDouble(MacroAssembler::DoubleEqual, SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::fpRegT1));
+ SpecializedThunkJIT::JumpList slowPath;
+ // Handle the negative doubles in the slow path for now.
+ slowPath.append(jit.branchDouble(MacroAssembler::DoubleLessThanOrUnordered, SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::fpRegT1));
+ slowPath.append(jit.branchTruncateDoubleToInt32(SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0));
+ intResult = jit.jump();
+ slowPath.link(&jit);
+ }
+ jit.callDoubleToDouble(UnaryDoubleOpWrapper(floor));
jit.branchConvertDoubleToInt32(SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0, doubleResult, SpecializedThunkJIT::fpRegT1);
+ if (jit.supportsFloatingPointTruncate())
+ intResult.link(&jit);
jit.returnInt32(SpecializedThunkJIT::regT0);
doubleResult.link(&jit);
jit.returnDouble(SpecializedThunkJIT::fpRegT0);
- return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall());
+ return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall(), "floor");
}
MacroAssemblerCodeRef ceilThunkGenerator(JSGlobalData* globalData)
@@ -210,12 +228,9 @@ MacroAssemblerCodeRef ceilThunkGenerator(JSGlobalData* globalData)
jit.returnInt32(SpecializedThunkJIT::regT0);
doubleResult.link(&jit);
jit.returnDouble(SpecializedThunkJIT::fpRegT0);
- return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall());
+ return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall(), "ceil");
}
-static const double oneConstant = 1.0;
-static const double negativeHalfConstant = -0.5;
-
MacroAssemblerCodeRef roundThunkGenerator(JSGlobalData* globalData)
{
SpecializedThunkJIT jit(1, globalData);
@@ -226,13 +241,28 @@ MacroAssemblerCodeRef roundThunkGenerator(JSGlobalData* globalData)
jit.returnInt32(SpecializedThunkJIT::regT0);
nonIntJump.link(&jit);
jit.loadDoubleArgument(0, SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0);
- jit.callDoubleToDouble(UnaryDoubleOpWrapper(jsRound));
+ SpecializedThunkJIT::Jump intResult;
SpecializedThunkJIT::JumpList doubleResult;
+ if (jit.supportsFloatingPointTruncate()) {
+ jit.loadDouble(&zeroConstant, SpecializedThunkJIT::fpRegT1);
+ doubleResult.append(jit.branchDouble(MacroAssembler::DoubleEqual, SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::fpRegT1));
+ SpecializedThunkJIT::JumpList slowPath;
+ // Handle the negative doubles in the slow path for now.
+ slowPath.append(jit.branchDouble(MacroAssembler::DoubleLessThanOrUnordered, SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::fpRegT1));
+ jit.loadDouble(&halfConstant, SpecializedThunkJIT::fpRegT1);
+ jit.addDouble(SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::fpRegT1);
+ slowPath.append(jit.branchTruncateDoubleToInt32(SpecializedThunkJIT::fpRegT1, SpecializedThunkJIT::regT0));
+ intResult = jit.jump();
+ slowPath.link(&jit);
+ }
+ jit.callDoubleToDouble(UnaryDoubleOpWrapper(jsRound));
jit.branchConvertDoubleToInt32(SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0, doubleResult, SpecializedThunkJIT::fpRegT1);
+ if (jit.supportsFloatingPointTruncate())
+ intResult.link(&jit);
jit.returnInt32(SpecializedThunkJIT::regT0);
doubleResult.link(&jit);
jit.returnDouble(SpecializedThunkJIT::fpRegT0);
- return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall());
+ return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall(), "round");
}
MacroAssemblerCodeRef expThunkGenerator(JSGlobalData* globalData)
@@ -245,7 +275,7 @@ MacroAssemblerCodeRef expThunkGenerator(JSGlobalData* globalData)
jit.loadDoubleArgument(0, SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0);
jit.callDoubleToDouble(UnaryDoubleOpWrapper(exp));
jit.returnDouble(SpecializedThunkJIT::fpRegT0);
- return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall());
+ return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall(), "exp");
}
MacroAssemblerCodeRef logThunkGenerator(JSGlobalData* globalData)
@@ -258,7 +288,7 @@ MacroAssemblerCodeRef logThunkGenerator(JSGlobalData* globalData)
jit.loadDoubleArgument(0, SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0);
jit.callDoubleToDouble(UnaryDoubleOpWrapper(log));
jit.returnDouble(SpecializedThunkJIT::fpRegT0);
- return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall());
+ return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall(), "log");
}
MacroAssemblerCodeRef absThunkGenerator(JSGlobalData* globalData)
@@ -278,7 +308,7 @@ MacroAssemblerCodeRef absThunkGenerator(JSGlobalData* globalData)
jit.loadDoubleArgument(0, SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0);
jit.absDouble(SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::fpRegT1);
jit.returnDouble(SpecializedThunkJIT::fpRegT1);
- return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall());
+ return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall(), "abs");
}
MacroAssemblerCodeRef powThunkGenerator(JSGlobalData* globalData)
@@ -330,7 +360,7 @@ MacroAssemblerCodeRef powThunkGenerator(JSGlobalData* globalData)
} else
jit.appendFailure(nonIntExponent);
- return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall());
+ return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall(), "pow");
}
}
diff --git a/Source/JavaScriptCore/llint/LLIntOfflineAsmConfig.h b/Source/JavaScriptCore/llint/LLIntOfflineAsmConfig.h
index 2539ee9b3..7720f5ec2 100644
--- a/Source/JavaScriptCore/llint/LLIntOfflineAsmConfig.h
+++ b/Source/JavaScriptCore/llint/LLIntOfflineAsmConfig.h
@@ -94,14 +94,14 @@
#if CPU(ARM_THUMB2)
#define OFFLINE_ASM_GLOBAL_LABEL(label) \
".globl " SYMBOL_STRING(label) "\n" \
- HIDE_SYMBOL(name) "\n" \
+ HIDE_SYMBOL(label) "\n" \
".thumb\n" \
".thumb_func " THUMB_FUNC_PARAM(label) "\n" \
SYMBOL_STRING(label) ":\n"
#else
#define OFFLINE_ASM_GLOBAL_LABEL(label) \
".globl " SYMBOL_STRING(label) "\n" \
- HIDE_SYMBOL(name) "\n" \
+ HIDE_SYMBOL(label) "\n" \
SYMBOL_STRING(label) ":\n"
#endif
diff --git a/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp b/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
index b13e84b53..ca3eb1eb0 100644
--- a/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
+++ b/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
@@ -475,8 +475,10 @@ LLINT_SLOW_PATH_DECL(slow_path_convert_this)
LLINT_BEGIN();
JSValue v1 = LLINT_OP(1).jsValue();
ASSERT(v1.isPrimitive());
+#if ENABLE(VALUE_PROFILER)
pc[OPCODE_LENGTH(op_convert_this) - 1].u.profile->m_buckets[0] =
JSValue::encode(v1.structureOrUndefined());
+#endif
LLINT_RETURN(v1.toThisObject(exec));
}
@@ -621,64 +623,88 @@ LLINT_SLOW_PATH_DECL(slow_path_add)
LLINT_RETURN(jsAddSlowCase(exec, v1, v2));
}
+// The following arithmetic and bitwise operations need to be sure to run
+// toNumber() on their operands in order. (A call to toNumber() is idempotent
+// if an exception is already set on the ExecState.)
+
LLINT_SLOW_PATH_DECL(slow_path_mul)
{
LLINT_BEGIN();
- LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toNumber(exec) * LLINT_OP_C(3).jsValue().toNumber(exec)));
+ double a = LLINT_OP_C(2).jsValue().toNumber(exec);
+ double b = LLINT_OP_C(3).jsValue().toNumber(exec);
+ LLINT_RETURN(jsNumber(a * b));
}
LLINT_SLOW_PATH_DECL(slow_path_sub)
{
LLINT_BEGIN();
- LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toNumber(exec) - LLINT_OP_C(3).jsValue().toNumber(exec)));
+ double a = LLINT_OP_C(2).jsValue().toNumber(exec);
+ double b = LLINT_OP_C(3).jsValue().toNumber(exec);
+ LLINT_RETURN(jsNumber(a - b));
}
LLINT_SLOW_PATH_DECL(slow_path_div)
{
LLINT_BEGIN();
- LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toNumber(exec) / LLINT_OP_C(3).jsValue().toNumber(exec)));
+ double a = LLINT_OP_C(2).jsValue().toNumber(exec);
+ double b = LLINT_OP_C(3).jsValue().toNumber(exec);
+ LLINT_RETURN(jsNumber(a / b));
}
LLINT_SLOW_PATH_DECL(slow_path_mod)
{
LLINT_BEGIN();
- LLINT_RETURN(jsNumber(fmod(LLINT_OP_C(2).jsValue().toNumber(exec), LLINT_OP_C(3).jsValue().toNumber(exec))));
+ double a = LLINT_OP_C(2).jsValue().toNumber(exec);
+ double b = LLINT_OP_C(3).jsValue().toNumber(exec);
+ LLINT_RETURN(jsNumber(fmod(a, b)));
}
LLINT_SLOW_PATH_DECL(slow_path_lshift)
{
LLINT_BEGIN();
- LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toInt32(exec) << (LLINT_OP_C(3).jsValue().toUInt32(exec) & 31)));
+ int32_t a = LLINT_OP_C(2).jsValue().toInt32(exec);
+ uint32_t b = LLINT_OP_C(3).jsValue().toUInt32(exec);
+ LLINT_RETURN(jsNumber(a << (b & 31)));
}
LLINT_SLOW_PATH_DECL(slow_path_rshift)
{
LLINT_BEGIN();
- LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toInt32(exec) >> (LLINT_OP_C(3).jsValue().toUInt32(exec) & 31)));
+ int32_t a = LLINT_OP_C(2).jsValue().toInt32(exec);
+ uint32_t b = LLINT_OP_C(3).jsValue().toUInt32(exec);
+ LLINT_RETURN(jsNumber(a >> (b & 31)));
}
LLINT_SLOW_PATH_DECL(slow_path_urshift)
{
LLINT_BEGIN();
- LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toUInt32(exec) >> (LLINT_OP_C(3).jsValue().toUInt32(exec) & 31)));
+ uint32_t a = LLINT_OP_C(2).jsValue().toUInt32(exec);
+ uint32_t b = LLINT_OP_C(3).jsValue().toUInt32(exec);
+ LLINT_RETURN(jsNumber(a >> (b & 31)));
}
LLINT_SLOW_PATH_DECL(slow_path_bitand)
{
LLINT_BEGIN();
- LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toInt32(exec) & LLINT_OP_C(3).jsValue().toInt32(exec)));
+ int32_t a = LLINT_OP_C(2).jsValue().toInt32(exec);
+ int32_t b = LLINT_OP_C(3).jsValue().toInt32(exec);
+ LLINT_RETURN(jsNumber(a & b));
}
LLINT_SLOW_PATH_DECL(slow_path_bitor)
{
LLINT_BEGIN();
- LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toInt32(exec) | LLINT_OP_C(3).jsValue().toInt32(exec)));
+ int32_t a = LLINT_OP_C(2).jsValue().toInt32(exec);
+ int32_t b = LLINT_OP_C(3).jsValue().toInt32(exec);
+ LLINT_RETURN(jsNumber(a | b));
}
LLINT_SLOW_PATH_DECL(slow_path_bitxor)
{
LLINT_BEGIN();
- LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toInt32(exec) ^ LLINT_OP_C(3).jsValue().toInt32(exec)));
+ int32_t a = LLINT_OP_C(2).jsValue().toInt32(exec);
+ int32_t b = LLINT_OP_C(3).jsValue().toInt32(exec);
+ LLINT_RETURN(jsNumber(a ^ b));
}
LLINT_SLOW_PATH_DECL(slow_path_check_has_instance)
@@ -832,6 +858,14 @@ LLINT_SLOW_PATH_DECL(slow_path_resolve_with_this)
LLINT_END();
}
+LLINT_SLOW_PATH_DECL(slow_path_put_global_var_check)
+{
+ LLINT_BEGIN();
+ CodeBlock* codeBlock = exec->codeBlock();
+ symbolTablePut(codeBlock->globalObject(), exec, codeBlock->identifier(pc[4].u.operand), LLINT_OP_C(2).jsValue(), true);
+ LLINT_END();
+}
+
LLINT_SLOW_PATH_DECL(slow_path_get_by_id)
{
LLINT_BEGIN();
@@ -902,6 +936,8 @@ LLINT_SLOW_PATH_DECL(slow_path_put_by_id)
if (slot.type() == PutPropertySlot::NewProperty) {
if (!structure->isDictionary() && structure->previousID()->propertyStorageCapacity() == structure->propertyStorageCapacity()) {
+ ASSERT(structure->previousID()->transitionWatchpointSetHasBeenInvalidated());
+
// This is needed because some of the methods we call
// below may GC.
pc[0].u.opcode = bitwise_cast<void*>(&llint_op_put_by_id);
@@ -987,7 +1023,7 @@ LLINT_SLOW_PATH_DECL(slow_path_get_argument_by_val)
exec->uncheckedR(unmodifiedArgumentsRegister(pc[2].u.operand)) = arguments;
}
- LLINT_RETURN(getByVal(exec, arguments, LLINT_OP_C(3).jsValue()));
+ LLINT_RETURN_PROFILED(op_get_argument_by_val, getByVal(exec, arguments, LLINT_OP_C(3).jsValue()));
}
LLINT_SLOW_PATH_DECL(slow_path_get_by_pname)
@@ -1546,14 +1582,16 @@ LLINT_SLOW_PATH_DECL(slow_path_debug)
LLINT_SLOW_PATH_DECL(slow_path_profile_will_call)
{
LLINT_BEGIN();
- (*Profiler::enabledProfilerReference())->willExecute(exec, LLINT_OP(1).jsValue());
+ if (Profiler* profiler = globalData.enabledProfiler())
+ profiler->willExecute(exec, LLINT_OP(1).jsValue());
LLINT_END();
}
LLINT_SLOW_PATH_DECL(slow_path_profile_did_call)
{
LLINT_BEGIN();
- (*Profiler::enabledProfilerReference())->didExecute(exec, LLINT_OP(1).jsValue());
+ if (Profiler* profiler = globalData.enabledProfiler())
+ profiler->didExecute(exec, LLINT_OP(1).jsValue());
LLINT_END();
}
diff --git a/Source/JavaScriptCore/llint/LLIntSlowPaths.h b/Source/JavaScriptCore/llint/LLIntSlowPaths.h
index a91cf797e..2e069d073 100644
--- a/Source/JavaScriptCore/llint/LLIntSlowPaths.h
+++ b/Source/JavaScriptCore/llint/LLIntSlowPaths.h
@@ -78,118 +78,122 @@ extern "C" SlowPathReturnType llint_trace_value(ExecState*, Instruction*, int fr
#define LLINT_SLOW_PATH_DECL(name) \
extern "C" SlowPathReturnType llint_##name(ExecState* exec, Instruction* pc)
-LLINT_SLOW_PATH_DECL(trace_prologue);
-LLINT_SLOW_PATH_DECL(trace_prologue_function_for_call);
-LLINT_SLOW_PATH_DECL(trace_prologue_function_for_construct);
-LLINT_SLOW_PATH_DECL(trace_arityCheck_for_call);
-LLINT_SLOW_PATH_DECL(trace_arityCheck_for_construct);
-LLINT_SLOW_PATH_DECL(trace);
-LLINT_SLOW_PATH_DECL(special_trace);
-LLINT_SLOW_PATH_DECL(entry_osr);
-LLINT_SLOW_PATH_DECL(entry_osr_function_for_call);
-LLINT_SLOW_PATH_DECL(entry_osr_function_for_construct);
-LLINT_SLOW_PATH_DECL(entry_osr_function_for_call_arityCheck);
-LLINT_SLOW_PATH_DECL(entry_osr_function_for_construct_arityCheck);
-LLINT_SLOW_PATH_DECL(loop_osr);
-LLINT_SLOW_PATH_DECL(replace);
-LLINT_SLOW_PATH_DECL(register_file_check);
-LLINT_SLOW_PATH_DECL(slow_path_call_arityCheck);
-LLINT_SLOW_PATH_DECL(slow_path_construct_arityCheck);
-LLINT_SLOW_PATH_DECL(slow_path_create_activation);
-LLINT_SLOW_PATH_DECL(slow_path_create_arguments);
-LLINT_SLOW_PATH_DECL(slow_path_create_this);
-LLINT_SLOW_PATH_DECL(slow_path_convert_this);
-LLINT_SLOW_PATH_DECL(slow_path_new_object);
-LLINT_SLOW_PATH_DECL(slow_path_new_array);
-LLINT_SLOW_PATH_DECL(slow_path_new_array_buffer);
-LLINT_SLOW_PATH_DECL(slow_path_new_regexp);
-LLINT_SLOW_PATH_DECL(slow_path_not);
-LLINT_SLOW_PATH_DECL(slow_path_eq);
-LLINT_SLOW_PATH_DECL(slow_path_neq);
-LLINT_SLOW_PATH_DECL(slow_path_stricteq);
-LLINT_SLOW_PATH_DECL(slow_path_nstricteq);
-LLINT_SLOW_PATH_DECL(slow_path_less);
-LLINT_SLOW_PATH_DECL(slow_path_lesseq);
-LLINT_SLOW_PATH_DECL(slow_path_greater);
-LLINT_SLOW_PATH_DECL(slow_path_greatereq);
-LLINT_SLOW_PATH_DECL(slow_path_pre_inc);
-LLINT_SLOW_PATH_DECL(slow_path_pre_dec);
-LLINT_SLOW_PATH_DECL(slow_path_post_inc);
-LLINT_SLOW_PATH_DECL(slow_path_post_dec);
-LLINT_SLOW_PATH_DECL(slow_path_to_jsnumber);
-LLINT_SLOW_PATH_DECL(slow_path_negate);
-LLINT_SLOW_PATH_DECL(slow_path_add);
-LLINT_SLOW_PATH_DECL(slow_path_mul);
-LLINT_SLOW_PATH_DECL(slow_path_sub);
-LLINT_SLOW_PATH_DECL(slow_path_div);
-LLINT_SLOW_PATH_DECL(slow_path_mod);
-LLINT_SLOW_PATH_DECL(slow_path_lshift);
-LLINT_SLOW_PATH_DECL(slow_path_rshift);
-LLINT_SLOW_PATH_DECL(slow_path_urshift);
-LLINT_SLOW_PATH_DECL(slow_path_bitand);
-LLINT_SLOW_PATH_DECL(slow_path_bitor);
-LLINT_SLOW_PATH_DECL(slow_path_bitxor);
-LLINT_SLOW_PATH_DECL(slow_path_check_has_instance);
-LLINT_SLOW_PATH_DECL(slow_path_instanceof);
-LLINT_SLOW_PATH_DECL(slow_path_typeof);
-LLINT_SLOW_PATH_DECL(slow_path_is_object);
-LLINT_SLOW_PATH_DECL(slow_path_is_function);
-LLINT_SLOW_PATH_DECL(slow_path_in);
-LLINT_SLOW_PATH_DECL(slow_path_resolve);
-LLINT_SLOW_PATH_DECL(slow_path_resolve_skip);
-LLINT_SLOW_PATH_DECL(slow_path_resolve_global);
-LLINT_SLOW_PATH_DECL(slow_path_resolve_global_dynamic);
-LLINT_SLOW_PATH_DECL(slow_path_resolve_for_resolve_global_dynamic);
-LLINT_SLOW_PATH_DECL(slow_path_resolve_base);
-LLINT_SLOW_PATH_DECL(slow_path_ensure_property_exists);
-LLINT_SLOW_PATH_DECL(slow_path_resolve_with_base);
-LLINT_SLOW_PATH_DECL(slow_path_resolve_with_this);
-LLINT_SLOW_PATH_DECL(slow_path_get_by_id);
-LLINT_SLOW_PATH_DECL(slow_path_get_arguments_length);
-LLINT_SLOW_PATH_DECL(slow_path_put_by_id);
-LLINT_SLOW_PATH_DECL(slow_path_del_by_id);
-LLINT_SLOW_PATH_DECL(slow_path_get_by_val);
-LLINT_SLOW_PATH_DECL(slow_path_get_argument_by_val);
-LLINT_SLOW_PATH_DECL(slow_path_get_by_pname);
-LLINT_SLOW_PATH_DECL(slow_path_put_by_val);
-LLINT_SLOW_PATH_DECL(slow_path_del_by_val);
-LLINT_SLOW_PATH_DECL(slow_path_put_by_index);
-LLINT_SLOW_PATH_DECL(slow_path_put_getter_setter);
-LLINT_SLOW_PATH_DECL(slow_path_jmp_scopes);
-LLINT_SLOW_PATH_DECL(slow_path_jtrue);
-LLINT_SLOW_PATH_DECL(slow_path_jfalse);
-LLINT_SLOW_PATH_DECL(slow_path_jless);
-LLINT_SLOW_PATH_DECL(slow_path_jnless);
-LLINT_SLOW_PATH_DECL(slow_path_jgreater);
-LLINT_SLOW_PATH_DECL(slow_path_jngreater);
-LLINT_SLOW_PATH_DECL(slow_path_jlesseq);
-LLINT_SLOW_PATH_DECL(slow_path_jnlesseq);
-LLINT_SLOW_PATH_DECL(slow_path_jgreatereq);
-LLINT_SLOW_PATH_DECL(slow_path_jngreatereq);
-LLINT_SLOW_PATH_DECL(slow_path_switch_imm);
-LLINT_SLOW_PATH_DECL(slow_path_switch_char);
-LLINT_SLOW_PATH_DECL(slow_path_switch_string);
-LLINT_SLOW_PATH_DECL(slow_path_new_func);
-LLINT_SLOW_PATH_DECL(slow_path_new_func_exp);
-LLINT_SLOW_PATH_DECL(slow_path_call);
-LLINT_SLOW_PATH_DECL(slow_path_construct);
-LLINT_SLOW_PATH_DECL(slow_path_call_varargs);
-LLINT_SLOW_PATH_DECL(slow_path_call_eval);
-LLINT_SLOW_PATH_DECL(slow_path_tear_off_activation);
-LLINT_SLOW_PATH_DECL(slow_path_tear_off_arguments);
-LLINT_SLOW_PATH_DECL(slow_path_strcat);
-LLINT_SLOW_PATH_DECL(slow_path_to_primitive);
-LLINT_SLOW_PATH_DECL(slow_path_get_pnames);
-LLINT_SLOW_PATH_DECL(slow_path_next_pname);
-LLINT_SLOW_PATH_DECL(slow_path_push_scope);
-LLINT_SLOW_PATH_DECL(slow_path_pop_scope);
-LLINT_SLOW_PATH_DECL(slow_path_push_new_scope);
-LLINT_SLOW_PATH_DECL(slow_path_throw);
-LLINT_SLOW_PATH_DECL(slow_path_throw_reference_error);
-LLINT_SLOW_PATH_DECL(slow_path_debug);
-LLINT_SLOW_PATH_DECL(slow_path_profile_will_call);
-LLINT_SLOW_PATH_DECL(slow_path_profile_did_call);
-LLINT_SLOW_PATH_DECL(throw_from_native_call);
+#define LLINT_SLOW_PATH_HIDDEN_DECL(name) \
+ LLINT_SLOW_PATH_DECL(name) WTF_INTERNAL
+
+LLINT_SLOW_PATH_HIDDEN_DECL(trace_prologue);
+LLINT_SLOW_PATH_HIDDEN_DECL(trace_prologue_function_for_call);
+LLINT_SLOW_PATH_HIDDEN_DECL(trace_prologue_function_for_construct);
+LLINT_SLOW_PATH_HIDDEN_DECL(trace_arityCheck_for_call);
+LLINT_SLOW_PATH_HIDDEN_DECL(trace_arityCheck_for_construct);
+LLINT_SLOW_PATH_HIDDEN_DECL(trace);
+LLINT_SLOW_PATH_HIDDEN_DECL(special_trace);
+LLINT_SLOW_PATH_HIDDEN_DECL(entry_osr);
+LLINT_SLOW_PATH_HIDDEN_DECL(entry_osr_function_for_call);
+LLINT_SLOW_PATH_HIDDEN_DECL(entry_osr_function_for_construct);
+LLINT_SLOW_PATH_HIDDEN_DECL(entry_osr_function_for_call_arityCheck);
+LLINT_SLOW_PATH_HIDDEN_DECL(entry_osr_function_for_construct_arityCheck);
+LLINT_SLOW_PATH_HIDDEN_DECL(loop_osr);
+LLINT_SLOW_PATH_HIDDEN_DECL(replace);
+LLINT_SLOW_PATH_HIDDEN_DECL(register_file_check);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_call_arityCheck);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_construct_arityCheck);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_create_activation);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_create_arguments);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_create_this);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_convert_this);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_new_object);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_new_array);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_new_array_buffer);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_new_regexp);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_not);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_eq);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_neq);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_stricteq);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_nstricteq);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_less);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_lesseq);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_greater);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_greatereq);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_pre_inc);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_pre_dec);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_post_inc);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_post_dec);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_to_jsnumber);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_negate);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_add);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_mul);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_sub);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_div);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_mod);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_lshift);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_rshift);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_urshift);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_bitand);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_bitor);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_bitxor);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_check_has_instance);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_instanceof);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_typeof);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_is_object);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_is_function);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_in);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_resolve);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_resolve_skip);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_resolve_global);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_resolve_global_dynamic);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_resolve_for_resolve_global_dynamic);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_resolve_base);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_ensure_property_exists);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_resolve_with_base);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_resolve_with_this);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_put_global_var_check);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_get_by_id);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_get_arguments_length);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_put_by_id);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_del_by_id);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_get_by_val);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_get_argument_by_val);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_get_by_pname);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_put_by_val);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_del_by_val);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_put_by_index);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_put_getter_setter);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_jmp_scopes);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_jtrue);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_jfalse);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_jless);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_jnless);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_jgreater);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_jngreater);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_jlesseq);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_jnlesseq);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_jgreatereq);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_jngreatereq);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_switch_imm);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_switch_char);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_switch_string);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_new_func);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_new_func_exp);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_call);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_construct);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_call_varargs);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_call_eval);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_tear_off_activation);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_tear_off_arguments);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_strcat);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_to_primitive);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_get_pnames);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_next_pname);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_push_scope);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_pop_scope);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_push_new_scope);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_throw);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_throw_reference_error);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_debug);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_profile_will_call);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_profile_did_call);
+LLINT_SLOW_PATH_HIDDEN_DECL(throw_from_native_call);
} } // namespace JSC::LLInt
diff --git a/Source/JavaScriptCore/llint/LLIntThunks.cpp b/Source/JavaScriptCore/llint/LLIntThunks.cpp
index b4d026423..6a6a579a3 100644
--- a/Source/JavaScriptCore/llint/LLIntThunks.cpp
+++ b/Source/JavaScriptCore/llint/LLIntThunks.cpp
@@ -36,7 +36,7 @@
namespace JSC { namespace LLInt {
-static MacroAssemblerCodeRef generateThunkWithJumpTo(JSGlobalData* globalData, void (*target)())
+static MacroAssemblerCodeRef generateThunkWithJumpTo(JSGlobalData* globalData, void (*target)(), const char *thunkKind)
{
JSInterfaceJIT jit;
@@ -45,37 +45,37 @@ static MacroAssemblerCodeRef generateThunkWithJumpTo(JSGlobalData* globalData, v
jit.jump(JSInterfaceJIT::regT0);
LinkBuffer patchBuffer(*globalData, &jit, GLOBAL_THUNK_ID);
- return patchBuffer.finalizeCode();
+ return FINALIZE_CODE(patchBuffer, ("LLInt %s prologue thunk", thunkKind));
}
MacroAssemblerCodeRef functionForCallEntryThunkGenerator(JSGlobalData* globalData)
{
- return generateThunkWithJumpTo(globalData, llint_function_for_call_prologue);
+ return generateThunkWithJumpTo(globalData, llint_function_for_call_prologue, "function for call");
}
MacroAssemblerCodeRef functionForConstructEntryThunkGenerator(JSGlobalData* globalData)
{
- return generateThunkWithJumpTo(globalData, llint_function_for_construct_prologue);
+ return generateThunkWithJumpTo(globalData, llint_function_for_construct_prologue, "function for construct");
}
MacroAssemblerCodeRef functionForCallArityCheckThunkGenerator(JSGlobalData* globalData)
{
- return generateThunkWithJumpTo(globalData, llint_function_for_call_arity_check);
+ return generateThunkWithJumpTo(globalData, llint_function_for_call_arity_check, "function for call with arity check");
}
MacroAssemblerCodeRef functionForConstructArityCheckThunkGenerator(JSGlobalData* globalData)
{
- return generateThunkWithJumpTo(globalData, llint_function_for_construct_arity_check);
+ return generateThunkWithJumpTo(globalData, llint_function_for_construct_arity_check, "function for construct with arity check");
}
MacroAssemblerCodeRef evalEntryThunkGenerator(JSGlobalData* globalData)
{
- return generateThunkWithJumpTo(globalData, llint_eval_prologue);
+ return generateThunkWithJumpTo(globalData, llint_eval_prologue, "eval");
}
MacroAssemblerCodeRef programEntryThunkGenerator(JSGlobalData* globalData)
{
- return generateThunkWithJumpTo(globalData, llint_program_prologue);
+ return generateThunkWithJumpTo(globalData, llint_program_prologue, "program");
}
} } // namespace JSC::LLInt
diff --git a/Source/JavaScriptCore/llint/LowLevelInterpreter.asm b/Source/JavaScriptCore/llint/LowLevelInterpreter.asm
index bbfa859f2..e59ddeba4 100644
--- a/Source/JavaScriptCore/llint/LowLevelInterpreter.asm
+++ b/Source/JavaScriptCore/llint/LowLevelInterpreter.asm
@@ -103,7 +103,7 @@ end
# Some common utilities.
macro crash()
- storei 0, 0xbbadbeef[]
+ storei t0, 0xbbadbeef[]
move 0, t0
call t0
end
@@ -727,19 +727,13 @@ _llint_op_throw_reference_error:
_llint_op_profile_will_call:
traceExecution()
- loadp JITStackFrame::enabledProfilerReference[sp], t0
- btpz [t0], .opProfileWillCallDone
callSlowPath(_llint_slow_path_profile_will_call)
-.opProfileWillCallDone:
dispatch(2)
_llint_op_profile_did_call:
traceExecution()
- loadp JITStackFrame::enabledProfilerReference[sp], t0
- btpz [t0], .opProfileWillCallDone
callSlowPath(_llint_slow_path_profile_did_call)
-.opProfileDidCallDone:
dispatch(2)
diff --git a/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm b/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm
index 95b26d42f..d27fd8229 100644
--- a/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm
+++ b/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm
@@ -1039,36 +1039,54 @@ _llint_op_put_scoped_var:
dispatch(4)
-_llint_op_get_global_var:
+macro getGlobalVar(size)
traceExecution()
- loadi 8[PC], t1
+ loadp 8[PC], t0
loadi 4[PC], t3
- loadp CodeBlock[cfr], t0
- loadp CodeBlock::m_globalObject[t0], t0
- loadp JSGlobalObject::m_registers[t0], t0
- loadi TagOffset[t0, t1, 8], t2
- loadi PayloadOffset[t0, t1, 8], t1
+ loadi TagOffset[t0], t2
+ loadi PayloadOffset[t0], t1
storei t2, TagOffset[cfr, t3, 8]
storei t1, PayloadOffset[cfr, t3, 8]
- loadi 12[PC], t3
+ loadi (size - 1) * 4[PC], t3
valueProfile(t2, t1, t3)
- dispatch(4)
+ dispatch(size)
+end
+
+_llint_op_get_global_var:
+ getGlobalVar(4)
+
+
+_llint_op_get_global_var_watchable:
+ getGlobalVar(5)
_llint_op_put_global_var:
traceExecution()
loadi 8[PC], t1
- loadp CodeBlock[cfr], t0
- loadp CodeBlock::m_globalObject[t0], t0
- loadp JSGlobalObject::m_registers[t0], t0
+ loadi 4[PC], t0
loadConstantOrVariable(t1, t2, t3)
- loadi 4[PC], t1
writeBarrier(t2, t3)
- storei t2, TagOffset[t0, t1, 8]
- storei t3, PayloadOffset[t0, t1, 8]
+ storei t2, TagOffset[t0]
+ storei t3, PayloadOffset[t0]
dispatch(3)
+_llint_op_put_global_var_check:
+ traceExecution()
+ loadp 12[PC], t2
+ loadi 8[PC], t1
+ loadi 4[PC], t0
+ btbnz [t2], .opPutGlobalVarCheckSlow
+ loadConstantOrVariable(t1, t2, t3)
+ writeBarrier(t2, t3)
+ storei t2, TagOffset[t0]
+ storei t3, PayloadOffset[t0]
+ dispatch(5)
+.opPutGlobalVarCheckSlow:
+ callSlowPath(_llint_slow_path_put_global_var_check)
+ dispatch(5)
+
+
_llint_op_get_by_id:
traceExecution()
# We only do monomorphic get_by_id caching for now, and we do not modify the
diff --git a/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm b/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm
index 5225bdda9..a153586f4 100644
--- a/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm
+++ b/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm
@@ -893,33 +893,50 @@ _llint_op_put_scoped_var:
dispatch(4)
-_llint_op_get_global_var:
+macro getGlobalVar(size)
traceExecution()
- loadis 16[PB, PC, 8], t1
+ loadp 16[PB, PC, 8], t0
loadis 8[PB, PC, 8], t3
- loadp CodeBlock[cfr], t0
- loadp CodeBlock::m_globalObject[t0], t0
- loadp JSGlobalObject::m_registers[t0], t0
- loadp [t0, t1, 8], t2
- storep t2, [cfr, t3, 8]
- loadp 24[PB, PC, 8], t3
- valueProfile(t2, t3)
- dispatch(4)
+ loadp [t0], t1
+ storep t1, [cfr, t3, 8]
+ loadp (size - 1) * 8[PB, PC, 8], t0
+ valueProfile(t1, t0)
+ dispatch(size)
+end
+
+_llint_op_get_global_var:
+ getGlobalVar(4)
+
+
+_llint_op_get_global_var_watchable:
+ getGlobalVar(5)
_llint_op_put_global_var:
traceExecution()
loadis 16[PB, PC, 8], t1
- loadp CodeBlock[cfr], t0
- loadp CodeBlock::m_globalObject[t0], t0
- loadp JSGlobalObject::m_registers[t0], t0
+ loadp 8[PB, PC, 8], t0
loadConstantOrVariable(t1, t2)
- loadis 8[PB, PC, 8], t1
writeBarrier(t2)
- storep t2, [t0, t1, 8]
+ storep t2, [t0]
dispatch(3)
+_llint_op_put_global_var_check:
+ traceExecution()
+ loadp 24[PB, PC, 8], t2
+ loadis 16[PB, PC, 8], t1
+ loadp 8[PB, PC, 8], t0
+ btbnz [t2], .opPutGlobalVarCheckSlow
+ loadConstantOrVariable(t1, t2)
+ writeBarrier(t2)
+ storep t2, [t0]
+ dispatch(5)
+.opPutGlobalVarCheckSlow:
+ callSlowPath(_llint_slow_path_put_global_var_check)
+ dispatch(5)
+
+
_llint_op_get_by_id:
traceExecution()
# We only do monomorphic get_by_id caching for now, and we do not modify the
diff --git a/Source/JavaScriptCore/offlineasm/asm.rb b/Source/JavaScriptCore/offlineasm/asm.rb
index 12bade022..50f9bc886 100644
--- a/Source/JavaScriptCore/offlineasm/asm.rb
+++ b/Source/JavaScriptCore/offlineasm/asm.rb
@@ -97,7 +97,7 @@ class Assembler
end
def self.labelReference(labelName)
- "\" SYMBOL_STRING(#{labelName}) \""
+ "\" LOCAL_REFERENCE(#{labelName}) \""
end
def self.localLabelReference(labelName)
diff --git a/Source/JavaScriptCore/profiler/Profiler.cpp b/Source/JavaScriptCore/profiler/Profiler.cpp
index 0ecd5b2c9..723393b5c 100644
--- a/Source/JavaScriptCore/profiler/Profiler.cpp
+++ b/Source/JavaScriptCore/profiler/Profiler.cpp
@@ -51,7 +51,6 @@ static unsigned ProfilesUID = 0;
static CallIdentifier createCallIdentifierFromFunctionImp(ExecState*, JSObject*, const UString& defaultSourceURL, int defaultLineNumber);
Profiler* Profiler::s_sharedProfiler = 0;
-Profiler* Profiler::s_sharedEnabledProfilerReference = 0;
Profiler* Profiler::profiler()
{
@@ -74,7 +73,7 @@ void Profiler::startProfiling(ExecState* exec, const UString& title)
return;
}
- s_sharedEnabledProfilerReference = this;
+ exec->globalData().m_enabledProfiler = this;
RefPtr<ProfileGenerator> profileGenerator = ProfileGenerator::create(exec, title, ++ProfilesUID);
m_currentProfiles.append(profileGenerator);
}
@@ -90,7 +89,7 @@ PassRefPtr<Profile> Profiler::stopProfiling(ExecState* exec, const UString& titl
m_currentProfiles.remove(i);
if (!m_currentProfiles.size())
- s_sharedEnabledProfilerReference = 0;
+ exec->globalData().m_enabledProfiler = 0;
return returnProfile;
}
@@ -107,7 +106,7 @@ void Profiler::stopProfiling(JSGlobalObject* origin)
profileGenerator->stopProfiling();
m_currentProfiles.remove(i);
if (!m_currentProfiles.size())
- s_sharedEnabledProfilerReference = 0;
+ origin->globalData().m_enabledProfiler = 0;
}
}
}
diff --git a/Source/JavaScriptCore/profiler/Profiler.h b/Source/JavaScriptCore/profiler/Profiler.h
index 45f91af44..877065eca 100644
--- a/Source/JavaScriptCore/profiler/Profiler.h
+++ b/Source/JavaScriptCore/profiler/Profiler.h
@@ -48,11 +48,6 @@ namespace JSC {
class Profiler {
WTF_MAKE_FAST_ALLOCATED;
public:
- static Profiler** enabledProfilerReference()
- {
- return &s_sharedEnabledProfilerReference;
- }
-
JS_EXPORT_PRIVATE static Profiler* profiler();
static CallIdentifier createCallIdentifier(ExecState* exec, JSValue, const UString& sourceURL, int lineNumber);
@@ -72,7 +67,6 @@ namespace JSC {
private:
Vector<RefPtr<ProfileGenerator> > m_currentProfiles;
static Profiler* s_sharedProfiler;
- static Profiler* s_sharedEnabledProfilerReference;
};
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/Completion.cpp b/Source/JavaScriptCore/runtime/Completion.cpp
index ce620245b..311d660a0 100644
--- a/Source/JavaScriptCore/runtime/Completion.cpp
+++ b/Source/JavaScriptCore/runtime/Completion.cpp
@@ -55,6 +55,8 @@ JSValue evaluate(ExecState* exec, ScopeChainNode* scopeChain, const SourceCode&
{
JSLock lock(exec);
ASSERT(exec->globalData().identifierTable == wtfThreadData().currentIdentifierTable());
+ if (exec->globalData().isCollectorBusy())
+ CRASH();
CodeProfiling profile(source);
diff --git a/Source/JavaScriptCore/runtime/Executable.cpp b/Source/JavaScriptCore/runtime/Executable.cpp
index 0ada2cb0f..73b4b6c4f 100644
--- a/Source/JavaScriptCore/runtime/Executable.cpp
+++ b/Source/JavaScriptCore/runtime/Executable.cpp
@@ -47,7 +47,7 @@ void ExecutableBase::destroy(JSCell* cell)
}
#endif
-inline void ExecutableBase::clearCode()
+void ExecutableBase::clearCode()
{
#if ENABLE(JIT)
m_jitCodeForCall.clear();
@@ -98,11 +98,6 @@ static void jettisonCodeBlock(JSGlobalData& globalData, OwnPtr<T>& codeBlock)
}
#endif
-void NativeExecutable::finalize(JSCell* cell)
-{
- jsCast<NativeExecutable*>(cell)->clearCode();
-}
-
const ClassInfo ScriptExecutable::s_info = { "ScriptExecutable", &ExecutableBase::s_info, 0, 0, CREATE_METHOD_TABLE(ScriptExecutable) };
#if ENABLE(JIT)
@@ -146,8 +141,6 @@ FunctionExecutable::FunctionExecutable(JSGlobalData& globalData, const Identifie
, m_name(name)
, m_inferredName(inferredName.isNull() ? globalData.propertyNames->emptyIdentifier : inferredName)
, m_symbolTable(0)
- , m_next(0)
- , m_prev(0)
{
}
@@ -159,8 +152,6 @@ FunctionExecutable::FunctionExecutable(ExecState* exec, const Identifier& name,
, m_name(name)
, m_inferredName(inferredName.isNull() ? exec->globalData().propertyNames->emptyIdentifier : inferredName)
, m_symbolTable(0)
- , m_next(0)
- , m_prev(0)
{
}
@@ -292,17 +283,9 @@ void EvalExecutable::unlinkCalls()
#endif
}
-void EvalExecutable::finalize(JSCell* cell)
-{
- jsCast<EvalExecutable*>(cell)->clearCode();
-}
-
-inline void EvalExecutable::clearCode()
+void EvalExecutable::clearCode()
{
- if (m_evalCodeBlock) {
- m_evalCodeBlock->clearEvalCache();
- m_evalCodeBlock.clear();
- }
+ m_evalCodeBlock.clear();
Base::clearCode();
}
@@ -424,17 +407,9 @@ void ProgramExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
thisObject->m_programCodeBlock->visitAggregate(visitor);
}
-void ProgramExecutable::finalize(JSCell* cell)
-{
- jsCast<ProgramExecutable*>(cell)->clearCode();
-}
-
-inline void ProgramExecutable::clearCode()
+void ProgramExecutable::clearCode()
{
- if (m_programCodeBlock) {
- m_programCodeBlock->clearEvalCache();
- m_programCodeBlock.clear();
- }
+ m_programCodeBlock.clear();
Base::clearCode();
}
@@ -642,37 +617,17 @@ void FunctionExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
thisObject->m_codeBlockForConstruct->visitAggregate(visitor);
}
-void FunctionExecutable::discardCode()
+void FunctionExecutable::clearCodeIfNotCompiling()
{
-#if ENABLE(JIT)
- // These first two checks are to handle the rare case where
- // we are trying to evict code for a function during its
- // codegen.
- if (!m_jitCodeForCall && m_codeBlockForCall)
- return;
- if (!m_jitCodeForConstruct && m_codeBlockForConstruct)
+ if (isCompiling())
return;
-#endif
clearCode();
}
-void FunctionExecutable::finalize(JSCell* cell)
+void FunctionExecutable::clearCode()
{
- FunctionExecutable* executable = jsCast<FunctionExecutable*>(cell);
- Heap::heap(executable)->removeFunctionExecutable(executable);
- executable->clearCode();
-}
-
-inline void FunctionExecutable::clearCode()
-{
- if (m_codeBlockForCall) {
- m_codeBlockForCall->clearEvalCache();
- m_codeBlockForCall.clear();
- }
- if (m_codeBlockForConstruct) {
- m_codeBlockForConstruct->clearEvalCache();
- m_codeBlockForConstruct.clear();
- }
+ m_codeBlockForCall.clear();
+ m_codeBlockForConstruct.clear();
Base::clearCode();
}
diff --git a/Source/JavaScriptCore/runtime/Executable.h b/Source/JavaScriptCore/runtime/Executable.h
index e999d3a08..e5f6de438 100644
--- a/Source/JavaScriptCore/runtime/Executable.h
+++ b/Source/JavaScriptCore/runtime/Executable.h
@@ -54,7 +54,8 @@ namespace JSC {
return false;
}
- class ExecutableBase : public JSCell {
+ class ExecutableBase : public JSCell, public DoublyLinkedListNode<ExecutableBase> {
+ friend class WTF::DoublyLinkedListNode<ExecutableBase>;
friend class JIT;
protected:
@@ -80,6 +81,11 @@ namespace JSC {
static void destroy(JSCell*);
#endif
+ bool isFunctionExecutable()
+ {
+ return structure()->typeInfo().type() == FunctionExecutableType;
+ }
+
bool isHostFunction() const
{
ASSERT((m_numParametersForCall == NUM_PARAMETERS_IS_HOST) == (m_numParametersForConstruct == NUM_PARAMETERS_IS_HOST));
@@ -88,6 +94,8 @@ namespace JSC {
static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(globalData, globalObject, proto, TypeInfo(CompoundType, StructureFlags), &s_info); }
+ void clearCode();
+
static JS_EXPORTDATA const ClassInfo s_info;
protected:
@@ -95,8 +103,10 @@ namespace JSC {
int m_numParametersForCall;
int m_numParametersForConstruct;
-#if ENABLE(JIT)
public:
+ static void clearCodeVirtual(ExecutableBase*);
+
+#if ENABLE(JIT)
JITCode& generatedJITCodeForCall()
{
ASSERT(m_jitCodeForCall);
@@ -166,14 +176,18 @@ namespace JSC {
return intrinsic();
return NoIntrinsic;
}
+#endif
protected:
+ ExecutableBase* m_prev;
+ ExecutableBase* m_next;
+
+#if ENABLE(JIT)
JITCode m_jitCodeForCall;
JITCode m_jitCodeForConstruct;
MacroAssemblerCodePtr m_jitCodeForCallWithArityCheck;
MacroAssemblerCodePtr m_jitCodeForConstructWithArityCheck;
#endif
- void clearCode();
};
class NativeExecutable : public ExecutableBase {
@@ -194,7 +208,6 @@ namespace JSC {
executable = new (NotNull, allocateCell<NativeExecutable>(globalData.heap)) NativeExecutable(globalData, function, constructor);
executable->finishCreation(globalData, JITCode::HostFunction(callThunk), JITCode::HostFunction(constructThunk), intrinsic);
}
- globalData.heap.addFinalizer(executable, &finalize);
return executable;
}
#endif
@@ -205,7 +218,6 @@ namespace JSC {
ASSERT(!globalData.canUseJIT());
NativeExecutable* executable = new (NotNull, allocateCell<NativeExecutable>(globalData.heap)) NativeExecutable(globalData, function, constructor);
executable->finishCreation(globalData);
- globalData.heap.addFinalizer(executable, &finalize);
return executable;
}
#endif
@@ -246,8 +258,6 @@ namespace JSC {
}
#endif
- static void finalize(JSCell*);
-
private:
NativeExecutable(JSGlobalData& globalData, NativeFunction function, NativeFunction constructor)
: ExecutableBase(globalData, globalData.nativeExecutableStructure.get(), NUM_PARAMETERS_IS_HOST)
@@ -303,6 +313,8 @@ namespace JSC {
void finishCreation(JSGlobalData& globalData)
{
Base::finishCreation(globalData);
+ globalData.heap.addCompiledCode(this); // Balanced by Heap::deleteUnmarkedCompiledCode().
+
#if ENABLE(CODEBLOCK_SAMPLING)
if (SamplingTool* sampler = globalData.interpreter->sampler())
sampler->notifyOfScope(globalData, this);
@@ -358,7 +370,6 @@ namespace JSC {
{
EvalExecutable* executable = new (NotNull, allocateCell<EvalExecutable>(*exec->heap())) EvalExecutable(exec, source, isInStrictContext);
executable->finishCreation(exec->globalData());
- exec->globalData().heap.addFinalizer(executable, &finalize);
return executable;
}
@@ -377,9 +388,7 @@ namespace JSC {
void unlinkCalls();
- protected:
void clearCode();
- static void finalize(JSCell*);
private:
static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
@@ -400,7 +409,6 @@ namespace JSC {
{
ProgramExecutable* executable = new (NotNull, allocateCell<ProgramExecutable>(*exec->heap())) ProgramExecutable(exec, source);
executable->finishCreation(exec->globalData());
- exec->globalData().heap.addFinalizer(executable, &finalize);
return executable;
}
@@ -447,9 +455,7 @@ namespace JSC {
void unlinkCalls();
- protected:
void clearCode();
- static void finalize(JSCell*);
private:
static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
@@ -461,10 +467,9 @@ namespace JSC {
OwnPtr<ProgramCodeBlock> m_programCodeBlock;
};
- class FunctionExecutable : public ScriptExecutable, public DoublyLinkedListNode<FunctionExecutable> {
+ class FunctionExecutable : public ScriptExecutable {
friend class JIT;
friend class LLIntOffsetsExtractor;
- friend class WTF::DoublyLinkedListNode<FunctionExecutable>;
public:
typedef ScriptExecutable Base;
@@ -472,8 +477,6 @@ namespace JSC {
{
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.addFunctionExecutable(executable);
- exec->globalData().heap.addFinalizer(executable, &finalize);
return executable;
}
@@ -481,8 +484,6 @@ namespace JSC {
{
FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(globalData.heap)) FunctionExecutable(globalData, name, inferredName, source, forceUsesArguments, parameters, isInStrictContext);
executable->finishCreation(globalData, name, firstLine, lastLine);
- globalData.heap.addFunctionExecutable(executable);
- globalData.heap.addFinalizer(executable, &finalize);
return executable;
}
@@ -639,7 +640,7 @@ namespace JSC {
UString paramString() const;
SharedSymbolTable* symbolTable() const { return m_symbolTable; }
- void discardCode();
+ void clearCodeIfNotCompiling();
static void visitChildren(JSCell*, SlotVisitor&);
static FunctionExecutable* fromGlobalCode(const Identifier&, ExecState*, Debugger*, const SourceCode&, JSObject** exception);
static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto)
@@ -651,10 +652,9 @@ namespace JSC {
void unlinkCalls();
- protected:
void clearCode();
- static void finalize(JSCell*);
+ protected:
void finishCreation(JSGlobalData& globalData, const Identifier& name, int firstLine, int lastLine)
{
Base::finishCreation(globalData);
@@ -677,7 +677,18 @@ namespace JSC {
ASSERT(kind == CodeForConstruct);
return m_codeBlockForConstruct;
}
-
+
+ bool isCompiling()
+ {
+#if ENABLE(JIT)
+ if (!m_jitCodeForCall && m_codeBlockForCall)
+ return true;
+ if (!m_jitCodeForConstruct && m_codeBlockForConstruct)
+ return true;
+#endif
+ return false;
+ }
+
static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
unsigned m_numCapturedVariables : 31;
bool m_forceUsesArguments : 1;
@@ -689,8 +700,6 @@ namespace JSC {
Identifier m_inferredName;
WriteBarrier<JSString> m_nameValue;
SharedSymbolTable* m_symbolTable;
- FunctionExecutable* m_next;
- FunctionExecutable* m_prev;
};
inline FunctionExecutable* JSFunction::jsExecutable() const
@@ -725,6 +734,20 @@ namespace JSC {
return function->nativeFunction() == nativeFunction;
}
+ inline void ExecutableBase::clearCodeVirtual(ExecutableBase* executable)
+ {
+ switch (executable->structure()->typeInfo().type()) {
+ case EvalExecutableType:
+ return jsCast<EvalExecutable*>(executable)->clearCode();
+ case ProgramExecutableType:
+ return jsCast<ProgramExecutable*>(executable)->clearCode();
+ case FunctionExecutableType:
+ return jsCast<FunctionExecutable*>(executable)->clearCode();
+ default:
+ return jsCast<NativeExecutable*>(executable)->clearCode();
+ }
+ }
+
inline void ScriptExecutable::unlinkCalls()
{
switch (structure()->typeInfo().type()) {
diff --git a/Source/JavaScriptCore/runtime/GCActivityCallback.cpp b/Source/JavaScriptCore/runtime/GCActivityCallback.cpp
index 6ec538f72..794d1545e 100644
--- a/Source/JavaScriptCore/runtime/GCActivityCallback.cpp
+++ b/Source/JavaScriptCore/runtime/GCActivityCallback.cpp
@@ -29,28 +29,108 @@
#include "config.h"
#include "GCActivityCallback.h"
+#include "APIShims.h"
+#include "Heap.h"
+#include "JSGlobalData.h"
+#include "JSLock.h"
+#include "JSObject.h"
+#include "ScopeChain.h"
+#include <wtf/RetainPtr.h>
+#include <wtf/WTFThreadData.h>
+
namespace JSC {
-struct DefaultGCActivityCallbackPlatformData {
-};
+#if USE(CF)
+
+const double gcTimeSlicePerMB = 0.01; // Percentage of CPU time we will spend to reclaim 1 MB
+const double maxGCTimeSlice = 0.05; // The maximum amount of CPU time we want to use for opportunistic timer-triggered collections.
+const double timerSlop = 2.0; // Fudge factor to avoid performance cost of resetting timer.
+const double pagingTimeOut = 0.1; // Time in seconds to allow opportunistic timer to iterate over all blocks to see if the Heap is paged out.
+const CFTimeInterval hour = 60 * 60;
-DefaultGCActivityCallback::DefaultGCActivityCallback(Heap*)
+DefaultGCActivityCallback::DefaultGCActivityCallback(Heap* heap)
+ : GCActivityCallback(heap->globalData(), CFRunLoopGetCurrent())
+ , m_delay(s_decade)
{
}
-DefaultGCActivityCallback::~DefaultGCActivityCallback()
+DefaultGCActivityCallback::DefaultGCActivityCallback(Heap* heap, CFRunLoopRef runLoop)
+ : GCActivityCallback(heap->globalData(), runLoop)
+ , m_delay(s_decade)
{
}
-void DefaultGCActivityCallback::didAllocate(size_t)
+void DefaultGCActivityCallback::doWork()
+{
+ Heap* heap = &m_globalData->heap;
+ if (!isEnabled())
+ return;
+
+ APIEntryShim shim(m_globalData);
+#if !PLATFORM(IOS)
+ double startTime = WTF::monotonicallyIncreasingTime();
+ if (heap->isPagedOut(startTime + pagingTimeOut)) {
+ heap->activityCallback()->cancel();
+ heap->increaseLastGCLength(pagingTimeOut);
+ return;
+ }
+#endif
+ heap->collectAllGarbage();
+}
+
+void DefaultGCActivityCallback::scheduleTimer(double newDelay)
+{
+ if (newDelay * timerSlop > m_delay)
+ return;
+ double delta = m_delay - newDelay;
+ m_delay = newDelay;
+ CFRunLoopTimerSetNextFireDate(m_timer.get(), CFRunLoopTimerGetNextFireDate(m_timer.get()) - delta);
+}
+
+void DefaultGCActivityCallback::cancelTimer()
+{
+ m_delay = s_decade;
+ CFRunLoopTimerSetNextFireDate(m_timer.get(), CFAbsoluteTimeGetCurrent() + s_decade);
+}
+
+void DefaultGCActivityCallback::didAllocate(size_t bytes)
{
+ // The first byte allocated in an allocation cycle will report 0 bytes to didAllocate.
+ // We pretend it's one byte so that we don't ignore this allocation entirely.
+ if (!bytes)
+ bytes = 1;
+ Heap* heap = static_cast<Heap*>(&m_globalData->heap);
+ double gcTimeSlice = std::min((static_cast<double>(bytes) / MB) * gcTimeSlicePerMB, maxGCTimeSlice);
+ double newDelay = heap->lastGCLength() / gcTimeSlice;
+ scheduleTimer(newDelay);
}
void DefaultGCActivityCallback::willCollect()
{
+ cancelTimer();
+}
+
+void DefaultGCActivityCallback::cancel()
+{
+ cancelTimer();
+}
+
+#else
+
+DefaultGCActivityCallback::DefaultGCActivityCallback(Heap* heap)
+ : GCActivityCallback(heap->globalData())
+{
+}
+
+void DefaultGCActivityCallback::doWork()
+{
}
-void DefaultGCActivityCallback::synchronize()
+void DefaultGCActivityCallback::didAllocate(size_t)
+{
+}
+
+void DefaultGCActivityCallback::willCollect()
{
}
@@ -58,5 +138,7 @@ void DefaultGCActivityCallback::cancel()
{
}
+#endif
+
}
diff --git a/Source/JavaScriptCore/runtime/GCActivityCallback.h b/Source/JavaScriptCore/runtime/GCActivityCallback.h
index 32077f2b0..18bbd31e0 100644
--- a/Source/JavaScriptCore/runtime/GCActivityCallback.h
+++ b/Source/JavaScriptCore/runtime/GCActivityCallback.h
@@ -29,6 +29,7 @@
#ifndef GCActivityCallback_h
#define GCActivityCallback_h
+#include "HeapTimer.h"
#include <wtf/OwnPtr.h>
#include <wtf/PassOwnPtr.h>
@@ -40,47 +41,54 @@ namespace JSC {
class Heap;
-class GCActivityCallback {
+class GCActivityCallback : public HeapTimer {
public:
- virtual ~GCActivityCallback() { }
virtual void didAllocate(size_t) { }
virtual void willCollect() { }
- virtual void synchronize() { }
virtual void cancel() { }
bool isEnabled() const { return m_enabled; }
void setEnabled(bool enabled) { m_enabled = enabled; }
protected:
- GCActivityCallback()
- : m_enabled(true)
+#if USE(CF)
+ GCActivityCallback(JSGlobalData* globalData, CFRunLoopRef runLoop)
+ : HeapTimer(globalData, runLoop)
+ , m_enabled(true)
+ {
+ }
+# else
+ GCActivityCallback(JSGlobalData* globalData)
+ : HeapTimer(globalData)
+ , m_enabled(true)
{
}
+#endif
bool m_enabled;
};
-struct DefaultGCActivityCallbackPlatformData;
-
class DefaultGCActivityCallback : public GCActivityCallback {
public:
static PassOwnPtr<DefaultGCActivityCallback> create(Heap*);
DefaultGCActivityCallback(Heap*);
- virtual ~DefaultGCActivityCallback();
virtual void didAllocate(size_t);
virtual void willCollect();
- virtual void synchronize();
virtual void cancel();
+
+ virtual void doWork();
#if USE(CF)
protected:
DefaultGCActivityCallback(Heap*, CFRunLoopRef);
- void commonConstructor(Heap*, CFRunLoopRef);
-#endif
-
+
+ void cancelTimer();
+ void scheduleTimer(double);
+
private:
- OwnPtr<DefaultGCActivityCallbackPlatformData> d;
+ double m_delay;
+#endif
};
inline PassOwnPtr<DefaultGCActivityCallback> DefaultGCActivityCallback::create(Heap* heap)
diff --git a/Source/JavaScriptCore/runtime/GCActivityCallbackBlackBerry.cpp b/Source/JavaScriptCore/runtime/GCActivityCallbackBlackBerry.cpp
new file mode 100644
index 000000000..3b0b5a751
--- /dev/null
+++ b/Source/JavaScriptCore/runtime/GCActivityCallbackBlackBerry.cpp
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2012 Research In Motion Limited. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+#include "GCActivityCallback.h"
+
+#include "Heap.h"
+#include <BlackBerryPlatformMemory.h>
+
+namespace JSC {
+
+DefaultGCActivityCallback::DefaultGCActivityCallback(Heap* heap)
+ : GCActivityCallback(heap->globalData())
+{
+}
+
+DefaultGCActivityCallback::doWork()
+{
+}
+
+void DefaultGCActivityCallback::didAllocate(size_t bytesAllocated)
+{
+ if (!BlackBerry::Platform::isMemoryLow())
+ return;
+
+ if (bytesAllocated < 1 * 1024 * 1024)
+ return;
+
+ if (m_globalData->heap.isBusy() || !m_globalData->heap.isSafeToCollect())
+ return;
+
+ m_globalData->heap.collect(Heap::DoNotSweep);
+}
+
+void DefaultGCActivityCallback::willCollect()
+{
+}
+
+void DefaultGCActivityCallback::cancel()
+{
+}
+
+}
diff --git a/Source/JavaScriptCore/runtime/GCActivityCallbackCF.cpp b/Source/JavaScriptCore/runtime/GCActivityCallbackCF.cpp
deleted file mode 100644
index d82403a6b..000000000
--- a/Source/JavaScriptCore/runtime/GCActivityCallbackCF.cpp
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright (C) 2010 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.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE 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 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 "GCActivityCallback.h"
-
-#include "APIShims.h"
-#include "Heap.h"
-#include "JSGlobalData.h"
-#include "JSLock.h"
-#include "JSObject.h"
-#include "ScopeChain.h"
-#include <wtf/RetainPtr.h>
-#include <wtf/WTFThreadData.h>
-
-#if !USE(CF)
-#error "This file should only be used on CF platforms."
-#endif
-
-namespace JSC {
-
-struct DefaultGCActivityCallbackPlatformData {
- static void timerDidFire(CFRunLoopTimerRef, void *info);
-
- RetainPtr<CFRunLoopTimerRef> timer;
- RetainPtr<CFRunLoopRef> runLoop;
- CFRunLoopTimerContext context;
- double delay;
-};
-
-const double gcTimeSlicePerMB = 0.01; // Percentage of CPU time we will spend to reclaim 1 MB
-const double maxGCTimeSlice = 0.05; // The maximum amount of CPU time we want to use for opportunistic timer-triggered collections.
-const double timerSlop = 2.0; // Fudge factor to avoid performance cost of resetting timer.
-const double pagingTimeOut = 0.1; // Time in seconds to allow opportunistic timer to iterate over all blocks to see if the Heap is paged out.
-const CFTimeInterval decade = 60 * 60 * 24 * 365 * 10;
-const CFTimeInterval hour = 60 * 60;
-
-void DefaultGCActivityCallbackPlatformData::timerDidFire(CFRunLoopTimerRef, void *info)
-{
- Heap* heap = static_cast<Heap*>(info);
- if (!heap->activityCallback()->isEnabled())
- return;
-
- APIEntryShim shim(heap->globalData());
-#if !PLATFORM(IOS)
- double startTime = WTF::monotonicallyIncreasingTime();
- if (heap->isPagedOut(startTime + pagingTimeOut)) {
- heap->activityCallback()->cancel();
- heap->increaseLastGCLength(pagingTimeOut);
- return;
- }
-#endif
- heap->collectAllGarbage();
-}
-
-DefaultGCActivityCallback::DefaultGCActivityCallback(Heap* heap)
-{
- commonConstructor(heap, CFRunLoopGetCurrent());
-}
-
-DefaultGCActivityCallback::DefaultGCActivityCallback(Heap* heap, CFRunLoopRef runLoop)
-{
- commonConstructor(heap, runLoop);
-}
-
-DefaultGCActivityCallback::~DefaultGCActivityCallback()
-{
- CFRunLoopRemoveTimer(d->runLoop.get(), d->timer.get(), kCFRunLoopCommonModes);
- CFRunLoopTimerInvalidate(d->timer.get());
-}
-
-void DefaultGCActivityCallback::commonConstructor(Heap* heap, CFRunLoopRef runLoop)
-{
- d = adoptPtr(new DefaultGCActivityCallbackPlatformData);
-
- memset(&d->context, 0, sizeof(CFRunLoopTimerContext));
- d->context.info = heap;
- d->runLoop = runLoop;
- d->timer.adoptCF(CFRunLoopTimerCreate(0, decade, decade, 0, 0, DefaultGCActivityCallbackPlatformData::timerDidFire, &d->context));
- d->delay = decade;
- CFRunLoopAddTimer(d->runLoop.get(), d->timer.get(), kCFRunLoopCommonModes);
-}
-
-static void scheduleTimer(DefaultGCActivityCallbackPlatformData* d, double newDelay)
-{
- if (newDelay * timerSlop > d->delay)
- return;
- double delta = d->delay - newDelay;
- d->delay = newDelay;
- CFRunLoopTimerSetNextFireDate(d->timer.get(), CFRunLoopTimerGetNextFireDate(d->timer.get()) - delta);
-}
-
-static void cancelTimer(DefaultGCActivityCallbackPlatformData* d)
-{
- d->delay = decade;
- CFRunLoopTimerSetNextFireDate(d->timer.get(), CFAbsoluteTimeGetCurrent() + decade);
-}
-
-void DefaultGCActivityCallback::didAllocate(size_t bytes)
-{
- // The first byte allocated in an allocation cycle will report 0 bytes to didAllocate.
- // We pretend it's one byte so that we don't ignore this allocation entirely.
- if (!bytes)
- bytes = 1;
- Heap* heap = static_cast<Heap*>(d->context.info);
- double gcTimeSlice = std::min((static_cast<double>(bytes) / MB) * gcTimeSlicePerMB, maxGCTimeSlice);
- double newDelay = heap->lastGCLength() / gcTimeSlice;
- scheduleTimer(d.get(), newDelay);
-}
-
-void DefaultGCActivityCallback::willCollect()
-{
- cancelTimer(d.get());
-}
-
-void DefaultGCActivityCallback::synchronize()
-{
- if (CFRunLoopGetCurrent() == d->runLoop.get())
- return;
- CFRunLoopRemoveTimer(d->runLoop.get(), d->timer.get(), kCFRunLoopCommonModes);
- d->runLoop = CFRunLoopGetCurrent();
- CFRunLoopAddTimer(d->runLoop.get(), d->timer.get(), kCFRunLoopCommonModes);
-}
-
-void DefaultGCActivityCallback::cancel()
-{
- cancelTimer(d.get());
-}
-
-}
diff --git a/Source/JavaScriptCore/runtime/JSArray.cpp b/Source/JavaScriptCore/runtime/JSArray.cpp
index 9e7aaba51..96cc44780 100644
--- a/Source/JavaScriptCore/runtime/JSArray.cpp
+++ b/Source/JavaScriptCore/runtime/JSArray.cpp
@@ -1371,6 +1371,8 @@ void JSArray::visitChildren(JSCell* cell, SlotVisitor& visitor)
JSNonFinalObject::visitChildren(thisObject, visitor);
if (thisObject->m_storage) {
+ MARK_LOG_MESSAGE1("[%u]: ", thisObject->length());
+
ArrayStorage* storage = thisObject->m_storage;
void* baseStorage = storage->m_allocBase;
diff --git a/Source/JavaScriptCore/runtime/JSCell.cpp b/Source/JavaScriptCore/runtime/JSCell.cpp
index 06c1f7c4d..61e8549ee 100644
--- a/Source/JavaScriptCore/runtime/JSCell.cpp
+++ b/Source/JavaScriptCore/runtime/JSCell.cpp
@@ -184,6 +184,11 @@ UString JSCell::className(const JSObject*)
return UString();
}
+const char* JSCell::className()
+{
+ return classInfo()->className;
+}
+
void JSCell::getPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode)
{
ASSERT_NOT_REACHED();
diff --git a/Source/JavaScriptCore/runtime/JSCell.h b/Source/JavaScriptCore/runtime/JSCell.h
index 0233f0fec..cdd409706 100644
--- a/Source/JavaScriptCore/runtime/JSCell.h
+++ b/Source/JavaScriptCore/runtime/JSCell.h
@@ -84,6 +84,8 @@ namespace JSC {
void setStructure(JSGlobalData&, Structure*);
void clearStructure() { m_structure.clear(); }
+ const char* className();
+
// Extracting the value.
JS_EXPORT_PRIVATE bool getString(ExecState* exec, UString&) const;
JS_EXPORT_PRIVATE UString getString(ExecState* exec) const; // null string if not a string
@@ -197,6 +199,8 @@ namespace JSC {
inline void JSCell::visitChildren(JSCell* cell, SlotVisitor& visitor)
{
+ MARK_LOG_PARENT(visitor, cell);
+
visitor.append(&cell->m_structure);
}
diff --git a/Source/JavaScriptCore/runtime/JSGlobalData.cpp b/Source/JavaScriptCore/runtime/JSGlobalData.cpp
index a13eb79c5..1fb90df40 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalData.cpp
+++ b/Source/JavaScriptCore/runtime/JSGlobalData.cpp
@@ -54,6 +54,7 @@
#include "RegExpObject.h"
#include "StrictEvalActivation.h"
#include "StrongInlines.h"
+#include <wtf/RetainPtr.h>
#include <wtf/Threading.h>
#include <wtf/WTFThreadData.h>
@@ -100,13 +101,10 @@ static bool enableAssembler(ExecutableAllocator& executableAllocator)
return false;
#if USE(CF)
- CFStringRef canUseJITKey = CFStringCreateWithCString(0 , "JavaScriptCoreUseJIT", kCFStringEncodingMacRoman);
- CFBooleanRef canUseJIT = (CFBooleanRef)CFPreferencesCopyAppValue(canUseJITKey, kCFPreferencesCurrentApplication);
- if (canUseJIT) {
- return kCFBooleanTrue == canUseJIT;
- CFRelease(canUseJIT);
- }
- CFRelease(canUseJITKey);
+ RetainPtr<CFStringRef> canUseJITKey(AdoptCF, CFStringCreateWithCString(0 , "JavaScriptCoreUseJIT", kCFStringEncodingMacRoman));
+ RetainPtr<CFBooleanRef> canUseJIT(AdoptCF, (CFBooleanRef)CFPreferencesCopyAppValue(canUseJITKey.get(), kCFPreferencesCurrentApplication));
+ if (canUseJIT)
+ return kCFBooleanTrue == canUseJIT.get();
#endif
#if USE(CF) || OS(UNIX)
@@ -159,6 +157,7 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType thread
, dynamicGlobalObject(0)
, cachedUTCOffset(std::numeric_limits<double>::quiet_NaN())
, maxReentryDepth(threadStackType == ThreadStackTypeSmall ? MaxSmallThreadReentryDepth : MaxLargeThreadReentryDepth)
+ , m_enabledProfiler(0)
, m_regExpCache(new RegExpCache(this))
#if ENABLE(REGEXP_TRACING)
, m_rtTraceList(new RTTraceList())
@@ -418,7 +417,7 @@ struct StackPreservingRecompiler : public MarkedBlock::VoidFunctor {
FunctionExecutable* executable = jsCast<FunctionExecutable*>(cell);
if (currentlyExecutingFunctions.contains(executable))
return;
- executable->discardCode();
+ executable->clearCodeIfNotCompiling();
}
};
diff --git a/Source/JavaScriptCore/runtime/JSGlobalData.h b/Source/JavaScriptCore/runtime/JSGlobalData.h
index c39a01920..f8833104a 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalData.h
+++ b/Source/JavaScriptCore/runtime/JSGlobalData.h
@@ -70,6 +70,7 @@ namespace JSC {
class LLIntOffsetsExtractor;
class NativeExecutable;
class ParserArena;
+ class Profiler;
class RegExpCache;
class Stringifier;
class Structure;
@@ -255,6 +256,11 @@ namespace JSC {
return m_inDefineOwnProperty;
}
+ Profiler* enabledProfiler()
+ {
+ return m_enabledProfiler;
+ }
+
#if ENABLE(ASSEMBLER)
ExecutableAllocator executableAllocator;
#endif
@@ -346,6 +352,7 @@ namespace JSC {
int maxReentryDepth;
+ Profiler* m_enabledProfiler;
RegExpCache* m_regExpCache;
BumpPointerAllocator m_regExpAllocator;
diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
index 86186b7e1..7b6109599 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
+++ b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
@@ -79,7 +79,7 @@
namespace JSC {
-const ClassInfo JSGlobalObject::s_info = { "GlobalObject", &JSVariableObject::s_info, 0, ExecState::globalObjectTable, CREATE_METHOD_TABLE(JSGlobalObject) };
+const ClassInfo JSGlobalObject::s_info = { "GlobalObject", &JSSegmentedVariableObject::s_info, 0, ExecState::globalObjectTable, CREATE_METHOD_TABLE(JSGlobalObject) };
const GlobalObjectMethodTable JSGlobalObject::s_globalObjectMethodTable = { &allowsAccessFrom, &supportsProfiling, &supportsRichSourceInfo, &shouldInterruptScript, &javaScriptExperimentsEnabled };
@@ -119,10 +119,8 @@ JSGlobalObject::~JSGlobalObject()
if (m_debugger)
m_debugger->detach(this);
- Profiler** profiler = Profiler::enabledProfilerReference();
- if (UNLIKELY(*profiler != 0)) {
- (*profiler)->stopProfiling(this);
- }
+ if (Profiler* profiler = globalData().enabledProfiler())
+ profiler->stopProfiling(this);
}
void JSGlobalObject::destroy(JSCell* cell)
@@ -150,9 +148,9 @@ void JSGlobalObject::put(JSCell* cell, ExecState* exec, PropertyName propertyNam
JSGlobalObject* thisObject = jsCast<JSGlobalObject*>(cell);
ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(thisObject));
- if (thisObject->symbolTablePut(exec, propertyName, value, slot.isStrictMode()))
+ if (symbolTablePut(thisObject, exec, propertyName, value, slot.isStrictMode()))
return;
- JSVariableObject::put(thisObject, exec, propertyName, value, slot);
+ JSSegmentedVariableObject::put(thisObject, exec, propertyName, value, slot);
}
void JSGlobalObject::putDirectVirtual(JSObject* object, ExecState* exec, PropertyName propertyName, JSValue value, unsigned attributes)
@@ -160,12 +158,12 @@ void JSGlobalObject::putDirectVirtual(JSObject* object, ExecState* exec, Propert
JSGlobalObject* thisObject = jsCast<JSGlobalObject*>(object);
ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(thisObject));
- if (thisObject->symbolTablePutWithAttributes(exec->globalData(), propertyName, value, attributes))
+ if (symbolTablePutWithAttributes(thisObject, exec->globalData(), propertyName, value, attributes))
return;
JSValue valueBefore = thisObject->getDirect(exec->globalData(), propertyName);
PutPropertySlot slot;
- JSVariableObject::put(thisObject, exec, propertyName, value, slot);
+ JSSegmentedVariableObject::put(thisObject, exec, propertyName, value, slot);
if (!valueBefore) {
JSValue valueAfter = thisObject->getDirect(exec->globalData(), propertyName);
if (valueAfter)
@@ -178,7 +176,7 @@ bool JSGlobalObject::defineOwnProperty(JSObject* object, ExecState* exec, Proper
JSGlobalObject* thisObject = jsCast<JSGlobalObject*>(object);
PropertySlot slot;
// silently ignore attempts to add accessors aliasing vars.
- if (descriptor.isAccessorDescriptor() && thisObject->symbolTableGet(propertyName, slot))
+ if (descriptor.isAccessorDescriptor() && symbolTableGet(thisObject, propertyName, slot))
return false;
return Base::defineOwnProperty(thisObject, exec, propertyName, descriptor, shouldThrow);
}
@@ -347,7 +345,7 @@ void JSGlobalObject::visitChildren(JSCell* cell, SlotVisitor& visitor)
ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);
COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
- JSVariableObject::visitChildren(thisObject, visitor);
+ JSSegmentedVariableObject::visitChildren(thisObject, visitor);
visitIfNeeded(visitor, &thisObject->m_globalScopeChain);
visitIfNeeded(visitor, &thisObject->m_methodCallDummy);
@@ -395,17 +393,6 @@ void JSGlobalObject::visitChildren(JSCell* cell, SlotVisitor& visitor)
visitIfNeeded(visitor, &thisObject->m_regExpStructure);
visitIfNeeded(visitor, &thisObject->m_stringObjectStructure);
visitIfNeeded(visitor, &thisObject->m_internalFunctionStructure);
-
- if (thisObject->m_registerArray) {
- // Outside the execution of global code, when our variables are torn off,
- // we can mark the torn-off array.
- visitor.appendValues(thisObject->m_registerArray.get(), thisObject->m_registerArraySize);
- } else if (thisObject->m_registers) {
- // During execution of global code, when our variables are in the register file,
- // the symbol table tells us how many variables there are, and registers
- // points to where they end, and the registers used for execution begin.
- visitor.appendValues(thisObject->m_registers - thisObject->symbolTable().size(), thisObject->symbolTable().size());
- }
}
ExecState* JSGlobalObject::globalExec()
@@ -413,26 +400,9 @@ ExecState* JSGlobalObject::globalExec()
return CallFrame::create(m_globalCallFrame + RegisterFile::CallFrameHeaderSize);
}
-void JSGlobalObject::resizeRegisters(size_t newSize)
-{
- // Previous duplicate symbols may have created spare capacity in m_registerArray.
- if (newSize <= m_registerArraySize)
- return;
-
- size_t oldSize = m_registerArraySize;
- OwnArrayPtr<WriteBarrier<Unknown> > registerArray = adoptArrayPtr(new WriteBarrier<Unknown>[newSize]);
- for (size_t i = 0; i < oldSize; ++i)
- registerArray[i].set(globalData(), this, m_registerArray[i].get());
- for (size_t i = oldSize; i < newSize; ++i)
- registerArray[i].setUndefined();
-
- WriteBarrier<Unknown>* registers = registerArray.get();
- setRegisters(registers, registerArray.release(), newSize);
-}
-
void JSGlobalObject::addStaticGlobals(GlobalPropertyInfo* globals, int count)
{
- resizeRegisters(symbolTable().size() + count);
+ addRegisters(count);
for (int i = 0; i < count; ++i) {
GlobalPropertyInfo& global = globals[i];
@@ -448,17 +418,17 @@ void JSGlobalObject::addStaticGlobals(GlobalPropertyInfo* globals, int count)
bool JSGlobalObject::getOwnPropertySlot(JSCell* cell, ExecState* exec, PropertyName propertyName, PropertySlot& slot)
{
JSGlobalObject* thisObject = jsCast<JSGlobalObject*>(cell);
- if (getStaticFunctionSlot<JSVariableObject>(exec, ExecState::globalObjectTable(exec), thisObject, propertyName, slot))
+ if (getStaticFunctionSlot<JSSegmentedVariableObject>(exec, ExecState::globalObjectTable(exec), thisObject, propertyName, slot))
return true;
- return thisObject->symbolTableGet(propertyName, slot);
+ return symbolTableGet(thisObject, propertyName, slot);
}
bool JSGlobalObject::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, PropertyName propertyName, PropertyDescriptor& descriptor)
{
JSGlobalObject* thisObject = jsCast<JSGlobalObject*>(object);
- if (getStaticFunctionDescriptor<JSVariableObject>(exec, ExecState::globalObjectTable(exec), thisObject, propertyName, descriptor))
+ if (getStaticFunctionDescriptor<JSSegmentedVariableObject>(exec, ExecState::globalObjectTable(exec), thisObject, propertyName, descriptor))
return true;
- return thisObject->symbolTableGet(propertyName, descriptor);
+ return symbolTableGet(thisObject, propertyName, descriptor);
}
void JSGlobalObject::clearRareData(JSCell* cell)
@@ -473,7 +443,7 @@ DynamicGlobalObjectScope::DynamicGlobalObjectScope(JSGlobalData& globalData, JSG
if (!m_dynamicGlobalObjectSlot) {
#if ENABLE(ASSEMBLER)
if (ExecutableAllocator::underMemoryPressure())
- globalData.heap.discardAllCompiledCode();
+ globalData.heap.deleteAllCompiledCode();
#endif
m_dynamicGlobalObjectSlot = dynamicGlobalObject;
diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.h b/Source/JavaScriptCore/runtime/JSGlobalObject.h
index 1e75b7267..2396142b1 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalObject.h
+++ b/Source/JavaScriptCore/runtime/JSGlobalObject.h
@@ -25,7 +25,7 @@
#include "JSArray.h"
#include "JSGlobalData.h"
#include "JSGlobalThis.h"
-#include "JSVariableObject.h"
+#include "JSSegmentedVariableObject.h"
#include "JSWeakObjectMapRefInternal.h"
#include "NumberPrototype.h"
#include "StringPrototype.h"
@@ -74,7 +74,7 @@ namespace JSC {
JavaScriptExperimentsEnabledFunctionPtr javaScriptExperimentsEnabled;
};
- class JSGlobalObject : public JSVariableObject {
+ class JSGlobalObject : public JSSegmentedVariableObject {
private:
typedef HashSet<RefPtr<OpaqueJSWeakObjectMap> > WeakMapSet;
@@ -90,7 +90,6 @@ namespace JSC {
protected:
- size_t m_registerArraySize;
Register m_globalCallFrame[RegisterFile::CallFrameHeaderSize];
WriteBarrier<ScopeChainNode> m_globalScopeChain;
@@ -164,7 +163,7 @@ namespace JSC {
}
public:
- typedef JSVariableObject Base;
+ typedef JSSegmentedVariableObject Base;
static JSGlobalObject* create(JSGlobalData& globalData, Structure* structure)
{
@@ -177,8 +176,7 @@ namespace JSC {
protected:
explicit JSGlobalObject(JSGlobalData& globalData, Structure* structure, const GlobalObjectMethodTable* globalObjectMethodTable = 0)
- : JSVariableObject(globalData, structure, &m_symbolTable, 0)
- , m_registerArraySize(0)
+ : JSSegmentedVariableObject(globalData, structure, &m_symbolTable)
, m_globalScopeChain()
, m_weakRandom(static_cast<unsigned>(randomNumber() * (std::numeric_limits<unsigned>::max() + 1.0)))
, m_evalEnabled(true)
@@ -308,8 +306,6 @@ namespace JSC {
void setEvalEnabled(bool enabled) { m_evalEnabled = enabled; }
bool evalEnabled() { return m_evalEnabled; }
- void resizeRegisters(size_t newSize);
-
void resetPrototype(JSGlobalData&, JSValue prototype);
JSGlobalData& globalData() const { return *Heap::heap(this)->globalData(); }
@@ -334,7 +330,7 @@ namespace JSC {
double weakRandomNumber() { return m_weakRandom.get(); }
protected:
- static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesVisitChildren | OverridesGetPropertyNames | JSVariableObject::StructureFlags;
+ static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesVisitChildren | OverridesGetPropertyNames | JSSegmentedVariableObject::StructureFlags;
struct GlobalPropertyInfo {
GlobalPropertyInfo(const Identifier& i, JSValue v, unsigned a)
@@ -359,7 +355,6 @@ namespace JSC {
void createThrowTypeError(ExecState*);
- void setRegisters(WriteBarrier<Unknown>* registers, PassOwnArrayPtr<WriteBarrier<Unknown> > registerArray, size_t count);
JS_EXPORT_PRIVATE static void clearRareData(JSCell*);
};
@@ -371,19 +366,13 @@ namespace JSC {
return jsCast<JSGlobalObject*>(asObject(value));
}
- inline void JSGlobalObject::setRegisters(WriteBarrier<Unknown>* registers, PassOwnArrayPtr<WriteBarrier<Unknown> > registerArray, size_t count)
- {
- JSVariableObject::setRegisters(registers, registerArray);
- m_registerArraySize = count;
- }
-
inline bool JSGlobalObject::hasOwnPropertyForWrite(ExecState* exec, PropertyName propertyName)
{
PropertySlot slot;
- if (JSVariableObject::getOwnPropertySlot(this, exec, propertyName, slot))
+ if (JSSegmentedVariableObject::getOwnPropertySlot(this, exec, propertyName, slot))
return true;
bool slotIsWriteable;
- return symbolTableGet(propertyName, slot, slotIsWriteable);
+ return symbolTableGet(this, propertyName, slot, slotIsWriteable);
}
inline bool JSGlobalObject::symbolTableHasProperty(PropertyName propertyName)
@@ -392,13 +381,18 @@ namespace JSC {
return !entry.isNull();
}
- inline JSValue Structure::prototypeForLookup(ExecState* exec) const
+ inline JSValue Structure::prototypeForLookup(JSGlobalObject* globalObject) const
{
if (isObject())
return m_prototype.get();
ASSERT(typeInfo().type() == StringType);
- return exec->lexicalGlobalObject()->stringPrototype();
+ return globalObject->stringPrototype();
+ }
+
+ inline JSValue Structure::prototypeForLookup(ExecState* exec) const
+ {
+ return prototypeForLookup(exec->lexicalGlobalObject());
}
inline StructureChain* Structure::prototypeChain(ExecState* exec) const
diff --git a/Source/JavaScriptCore/runtime/JSObject.cpp b/Source/JavaScriptCore/runtime/JSObject.cpp
index 8d9e4a96b..aa71b8a7b 100644
--- a/Source/JavaScriptCore/runtime/JSObject.cpp
+++ b/Source/JavaScriptCore/runtime/JSObject.cpp
@@ -56,7 +56,7 @@ const ClassInfo JSObject::s_info = { "Object", 0, 0, 0, CREATE_METHOD_TABLE(JSOb
const ClassInfo JSFinalObject::s_info = { "Object", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(JSFinalObject) };
-static inline void getClassPropertyNames(ExecState* exec, const ClassInfo* classInfo, PropertyNameArray& propertyNames, EnumerationMode mode)
+static inline void getClassPropertyNames(ExecState* exec, const ClassInfo* classInfo, PropertyNameArray& propertyNames, EnumerationMode mode, bool didReify)
{
// Add properties from the static hashtables of properties
for (; classInfo; classInfo = classInfo->parentClass) {
@@ -69,7 +69,7 @@ static inline void getClassPropertyNames(ExecState* exec, const ClassInfo* class
int hashSizeMask = table->compactSize - 1;
const HashEntry* entry = table->table;
for (int i = 0; i <= hashSizeMask; ++i, ++entry) {
- if (entry->key() && (!(entry->attributes() & DontEnum) || (mode == IncludeDontEnumProperties)))
+ if (entry->key() && (!(entry->attributes() & DontEnum) || (mode == IncludeDontEnumProperties)) && !((entry->attributes() & Function) && didReify))
propertyNames.add(entry->key());
}
}
@@ -417,9 +417,8 @@ void JSObject::getPropertyNames(JSObject* object, ExecState* exec, PropertyNameA
void JSObject::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
{
+ getClassPropertyNames(exec, object->classInfo(), propertyNames, mode, object->staticFunctionsReified());
object->structure()->getPropertyNamesFromStructure(exec->globalData(), propertyNames, mode);
- if (!object->staticFunctionsReified())
- getClassPropertyNames(exec, object->classInfo(), propertyNames, mode);
}
double JSObject::toNumber(ExecState* exec) const
@@ -505,22 +504,25 @@ void JSObject::reifyStaticFunctionsForDelete(ExecState* exec)
structure()->setStaticFunctionsReified();
}
-void JSObject::removeDirect(JSGlobalData& globalData, PropertyName propertyName)
+bool JSObject::removeDirect(JSGlobalData& globalData, PropertyName propertyName)
{
if (structure()->get(globalData, propertyName) == WTF::notFound)
- return;
+ return false;
size_t offset;
if (structure()->isUncacheableDictionary()) {
offset = structure()->removePropertyWithoutTransition(globalData, propertyName);
- if (offset != WTF::notFound)
- putUndefinedAtDirectOffset(offset);
- return;
+ if (offset == WTF::notFound)
+ return false;
+ putUndefinedAtDirectOffset(offset);
+ return true;
}
setStructure(globalData, Structure::removePropertyTransition(globalData, structure(), propertyName, offset));
- if (offset != WTF::notFound)
- putUndefinedAtDirectOffset(offset);
+ if (offset == WTF::notFound)
+ return false;
+ putUndefinedAtDirectOffset(offset);
+ return true;
}
NEVER_INLINE void JSObject::fillGetterPropertySlot(PropertySlot& slot, WriteBarrierBase<Unknown>* location)
diff --git a/Source/JavaScriptCore/runtime/JSObject.h b/Source/JavaScriptCore/runtime/JSObject.h
index 67aa1516c..ac8601deb 100644
--- a/Source/JavaScriptCore/runtime/JSObject.h
+++ b/Source/JavaScriptCore/runtime/JSObject.h
@@ -176,7 +176,7 @@ namespace JSC {
void transitionTo(JSGlobalData&, Structure*);
- void removeDirect(JSGlobalData&, PropertyName);
+ bool removeDirect(JSGlobalData&, PropertyName); // Return true if anything is removed.
bool hasCustomProperties() { return structure()->didTransition(); }
bool hasGetterSetterProperties() { return structure()->hasGetterSetterProperties(); }
diff --git a/Source/JavaScriptCore/runtime/JSSegmentedVariableObject.cpp b/Source/JavaScriptCore/runtime/JSSegmentedVariableObject.cpp
new file mode 100644
index 000000000..c65d2b1b9
--- /dev/null
+++ b/Source/JavaScriptCore/runtime/JSSegmentedVariableObject.cpp
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE 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 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 "JSSegmentedVariableObject.h"
+
+namespace JSC {
+
+int JSSegmentedVariableObject::findRegisterIndex(void* registerAddress)
+{
+ for (int i = m_registers.size(); i--;) {
+ if (&m_registers[i] != registerAddress)
+ continue;
+ return i;
+ }
+ CRASH();
+ return -1;
+}
+
+int JSSegmentedVariableObject::addRegisters(int numberOfRegistersToAdd)
+{
+ ASSERT(numberOfRegistersToAdd >= 0);
+
+ size_t oldSize = m_registers.size();
+ m_registers.grow(oldSize + numberOfRegistersToAdd);
+
+ for (size_t i = numberOfRegistersToAdd; i--;)
+ m_registers[oldSize + i].setWithoutWriteBarrier(jsUndefined());
+
+ return static_cast<int>(oldSize);
+}
+
+void JSSegmentedVariableObject::visitChildren(JSCell* cell, SlotVisitor& slotVisitor)
+{
+ JSSegmentedVariableObject* thisObject = jsCast<JSSegmentedVariableObject*>(cell);
+ ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);
+ COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+ ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
+ JSSymbolTableObject::visitChildren(thisObject, slotVisitor);
+
+ for (unsigned i = thisObject->m_registers.size(); i--;)
+ slotVisitor.append(&thisObject->m_registers[i]);
+}
+
+} // namespace JSC
+
diff --git a/Source/JavaScriptCore/runtime/JSSegmentedVariableObject.h b/Source/JavaScriptCore/runtime/JSSegmentedVariableObject.h
new file mode 100644
index 000000000..f1fe0483d
--- /dev/null
+++ b/Source/JavaScriptCore/runtime/JSSegmentedVariableObject.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.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE 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 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 JSSegmentedVariableObject_h
+#define JSSegmentedVariableObject_h
+
+#include "JSObject.h"
+#include "JSSymbolTableObject.h"
+#include "Register.h"
+#include "SymbolTable.h"
+#include <wtf/OwnArrayPtr.h>
+#include <wtf/SegmentedVector.h>
+#include <wtf/UnusedParam.h>
+
+namespace JSC {
+
+class LLIntOffsetsExtractor;
+class Register;
+
+// This is a mostly drop-in replacement for JSVariableObject, except that it preserves
+// the invariant that after a variable is created, its address in memory will not change
+// so long as the JSSegmentedVariableObject is alive. This allows optimizations based
+// on getting the address of the variable and remembering it. As well, unlike a
+// JSVariableObject, this will manage the memory for the registers itself and neither
+// requires nor allows for the subclasses to manage that memory. Finally,
+// JSSegmentedVariableObject has its own GC tracing functionality, since it knows the
+// exact dimensions of the variables array at all times.
+
+class JSSegmentedVariableObject : public JSSymbolTableObject {
+ friend class JIT;
+ friend class LLIntOffsetsExtractor;
+
+public:
+ typedef JSSymbolTableObject Base;
+
+ WriteBarrier<Unknown>& registerAt(int index) { return m_registers[index]; }
+
+ // This is a slow method call, which searches the register bank to find the index
+ // given a pointer. It will CRASH() if it does not find the register. Only use this
+ // in debug code (like bytecode dumping).
+ JS_EXPORT_PRIVATE int findRegisterIndex(void*);
+
+ WriteBarrier<Unknown>* assertRegisterIsInThisObject(WriteBarrier<Unknown>* registerPointer)
+ {
+#if !ASSERT_DISABLED
+ findRegisterIndex(registerPointer);
+#endif
+ return registerPointer;
+ }
+
+ // Adds numberOfRegistersToAdd registers, initializes them to Undefined, and returns
+ // the index of the first one added.
+ JS_EXPORT_PRIVATE int addRegisters(int numberOfRegistersToAdd);
+
+ JS_EXPORT_PRIVATE static void visitChildren(JSCell*, SlotVisitor&);
+
+protected:
+ static const unsigned StructureFlags = OverridesVisitChildren | JSSymbolTableObject::StructureFlags;
+
+ JSSegmentedVariableObject(JSGlobalData& globalData, Structure* structure, SymbolTable* symbolTable)
+ : JSSymbolTableObject(globalData, structure, symbolTable)
+ {
+ }
+
+ void finishCreation(JSGlobalData& globalData)
+ {
+ Base::finishCreation(globalData);
+ }
+
+ SegmentedVector<WriteBarrier<Unknown>, 16> m_registers;
+};
+
+} // namespace JSC
+
+#endif // JSSegmentedVariableObject_h
+
diff --git a/Source/JavaScriptCore/runtime/JSStaticScopeObject.cpp b/Source/JavaScriptCore/runtime/JSStaticScopeObject.cpp
index e5e65673c..14187f422 100644
--- a/Source/JavaScriptCore/runtime/JSStaticScopeObject.cpp
+++ b/Source/JavaScriptCore/runtime/JSStaticScopeObject.cpp
@@ -66,13 +66,13 @@ void JSStaticScopeObject::put(JSCell* cell, ExecState* exec, PropertyName proper
// a pointer compare.
PropertySlot slot;
bool isWritable = true;
- thisObject->symbolTableGet(propertyName, slot, isWritable);
+ symbolTableGet(thisObject, propertyName, slot, isWritable);
if (!isWritable) {
throwError(exec, createTypeError(exec, StrictModeReadonlyPropertyWriteError));
return;
}
}
- if (thisObject->symbolTablePut(exec, propertyName, value, slot.isStrictMode()))
+ if (symbolTablePut(thisObject, exec, propertyName, value, slot.isStrictMode()))
return;
ASSERT_NOT_REACHED();
@@ -81,7 +81,7 @@ void JSStaticScopeObject::put(JSCell* cell, ExecState* exec, PropertyName proper
void JSStaticScopeObject::putDirectVirtual(JSObject* object, ExecState* exec, PropertyName propertyName, JSValue value, unsigned attributes)
{
JSStaticScopeObject* thisObject = jsCast<JSStaticScopeObject*>(object);
- if (thisObject->symbolTablePutWithAttributes(exec->globalData(), propertyName, value, attributes))
+ if (symbolTablePutWithAttributes(thisObject, exec->globalData(), propertyName, value, attributes))
return;
ASSERT_NOT_REACHED();
@@ -89,7 +89,7 @@ void JSStaticScopeObject::putDirectVirtual(JSObject* object, ExecState* exec, Pr
bool JSStaticScopeObject::getOwnPropertySlot(JSCell* cell, ExecState*, PropertyName propertyName, PropertySlot& slot)
{
- return jsCast<JSStaticScopeObject*>(cell)->symbolTableGet(propertyName, slot);
+ return symbolTableGet(jsCast<JSStaticScopeObject*>(cell), propertyName, slot);
}
}
diff --git a/Source/JavaScriptCore/runtime/JSString.cpp b/Source/JavaScriptCore/runtime/JSString.cpp
index 180c64b8b..4eb2a5297 100644
--- a/Source/JavaScriptCore/runtime/JSString.cpp
+++ b/Source/JavaScriptCore/runtime/JSString.cpp
@@ -56,6 +56,19 @@ void JSString::visitChildren(JSCell* cell, SlotVisitor& visitor)
JSString* thisObject = jsCast<JSString*>(cell);
Base::visitChildren(thisObject, visitor);
+ MARK_LOG_MESSAGE1("[%u]: ", thisObject->length());
+
+#if ENABLE(OBJECT_MARK_LOGGING)
+ if (!thisObject->isRope()) {
+ WTF::StringImpl* ourImpl = thisObject->m_value.impl();
+ if (ourImpl->is8Bit())
+ MARK_LOG_MESSAGE1("[8 %p]", ourImpl->characters8());
+ else
+ MARK_LOG_MESSAGE1("[16 %p]", ourImpl->characters16());
+ } else
+ MARK_LOG_MESSAGE0("[rope]: ");
+#endif
+
if (thisObject->isRope())
static_cast<JSRopeString*>(thisObject)->visitFibers(visitor);
}
diff --git a/Source/JavaScriptCore/runtime/JSString.h b/Source/JavaScriptCore/runtime/JSString.h
index 111853c39..4fb157c8b 100644
--- a/Source/JavaScriptCore/runtime/JSString.h
+++ b/Source/JavaScriptCore/runtime/JSString.h
@@ -67,6 +67,7 @@ namespace JSC {
friend class JSGlobalData;
friend class SpecializedThunkJIT;
friend class JSRopeString;
+ friend class SlotVisitor;
friend struct ThunkHelpers;
typedef JSCell Base;
diff --git a/Source/JavaScriptCore/runtime/JSSymbolTableObject.cpp b/Source/JavaScriptCore/runtime/JSSymbolTableObject.cpp
new file mode 100644
index 000000000..927ad25cf
--- /dev/null
+++ b/Source/JavaScriptCore/runtime/JSSymbolTableObject.cpp
@@ -0,0 +1,88 @@
+/*
+ * 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.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE 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 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 "JSSymbolTableObject.h"
+
+#include "JSActivation.h"
+#include "JSGlobalObject.h"
+#include "JSStaticScopeObject.h"
+#include "PropertyNameArray.h"
+
+namespace JSC {
+
+void JSSymbolTableObject::destroy(JSCell* cell)
+{
+ static_cast<JSSymbolTableObject*>(cell)->JSSymbolTableObject::~JSSymbolTableObject();
+}
+
+bool JSSymbolTableObject::deleteProperty(JSCell* cell, ExecState* exec, PropertyName propertyName)
+{
+ JSSymbolTableObject* thisObject = jsCast<JSSymbolTableObject*>(cell);
+ if (thisObject->symbolTable().contains(propertyName.publicName()))
+ return false;
+
+ return JSObject::deleteProperty(thisObject, exec, propertyName);
+}
+
+void JSSymbolTableObject::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
+{
+ JSSymbolTableObject* thisObject = jsCast<JSSymbolTableObject*>(object);
+ SymbolTable::const_iterator end = thisObject->symbolTable().end();
+ for (SymbolTable::const_iterator it = thisObject->symbolTable().begin(); it != end; ++it) {
+ if (!(it->second.getAttributes() & DontEnum) || (mode == IncludeDontEnumProperties))
+ propertyNames.add(Identifier(exec, it->first.get()));
+ }
+
+ JSObject::getOwnPropertyNames(thisObject, exec, propertyNames, mode);
+}
+
+void JSSymbolTableObject::putDirectVirtual(JSObject*, ExecState*, PropertyName, JSValue, unsigned)
+{
+ ASSERT_NOT_REACHED();
+}
+
+bool JSSymbolTableObject::isDynamicScope(bool& requiresDynamicChecks) const
+{
+ switch (structure()->typeInfo().type()) {
+ case GlobalObjectType:
+ return static_cast<const JSGlobalObject*>(this)->isDynamicScope(requiresDynamicChecks);
+ case ActivationObjectType:
+ return static_cast<const JSActivation*>(this)->isDynamicScope(requiresDynamicChecks);
+ case StaticScopeObjectType:
+ return static_cast<const JSStaticScopeObject*>(this)->isDynamicScope(requiresDynamicChecks);
+ default:
+ ASSERT_NOT_REACHED();
+ break;
+ }
+
+ return false;
+}
+
+} // namespace JSC
+
diff --git a/Source/JavaScriptCore/runtime/JSSymbolTableObject.h b/Source/JavaScriptCore/runtime/JSSymbolTableObject.h
new file mode 100644
index 000000000..2bbe21d06
--- /dev/null
+++ b/Source/JavaScriptCore/runtime/JSSymbolTableObject.h
@@ -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.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE 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 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 JSSymbolTableObject_h
+#define JSSymbolTableObject_h
+
+#include "JSObject.h"
+#include "PropertyDescriptor.h"
+#include "SymbolTable.h"
+
+namespace JSC {
+
+class JSSymbolTableObject : public JSNonFinalObject {
+public:
+ typedef JSNonFinalObject Base;
+
+ SymbolTable& symbolTable() const { return *m_symbolTable; }
+
+ JS_EXPORT_PRIVATE static void destroy(JSCell*);
+
+ static NO_RETURN_DUE_TO_ASSERT void putDirectVirtual(JSObject*, ExecState*, PropertyName, JSValue, unsigned attributes);
+
+ JS_EXPORT_PRIVATE static bool deleteProperty(JSCell*, ExecState*, PropertyName);
+ JS_EXPORT_PRIVATE static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
+
+ bool isDynamicScope(bool& requiresDynamicChecks) const;
+
+protected:
+ static const unsigned StructureFlags = OverridesGetPropertyNames | JSNonFinalObject::StructureFlags;
+
+ JSSymbolTableObject(JSGlobalData& globalData, Structure* structure, SymbolTable* symbolTable)
+ : JSNonFinalObject(globalData, structure)
+ , m_symbolTable(symbolTable)
+ {
+ }
+
+ void finishCreation(JSGlobalData& globalData)
+ {
+ Base::finishCreation(globalData);
+ ASSERT(m_symbolTable);
+ }
+
+ SymbolTable* m_symbolTable;
+};
+
+template<typename SymbolTableObjectType>
+inline bool symbolTableGet(
+ SymbolTableObjectType* object, PropertyName propertyName, PropertySlot& slot)
+{
+ SymbolTable& symbolTable = object->symbolTable();
+ SymbolTable::iterator iter = symbolTable.find(propertyName.publicName());
+ if (iter == symbolTable.end())
+ return false;
+ SymbolTableEntry::Fast entry = iter->second;
+ ASSERT(!entry.isNull());
+ slot.setValue(object->registerAt(entry.getIndex()).get());
+ return true;
+}
+
+template<typename SymbolTableObjectType>
+inline bool symbolTableGet(
+ SymbolTableObjectType* object, PropertyName propertyName, PropertyDescriptor& descriptor)
+{
+ SymbolTable& symbolTable = object->symbolTable();
+ SymbolTable::iterator iter = symbolTable.find(propertyName.publicName());
+ if (iter == symbolTable.end())
+ return false;
+ SymbolTableEntry::Fast entry = iter->second;
+ ASSERT(!entry.isNull());
+ descriptor.setDescriptor(
+ object->registerAt(entry.getIndex()).get(), entry.getAttributes() | DontDelete);
+ return true;
+}
+
+template<typename SymbolTableObjectType>
+inline bool symbolTableGet(
+ SymbolTableObjectType* object, PropertyName propertyName, PropertySlot& slot,
+ bool& slotIsWriteable)
+{
+ SymbolTable& symbolTable = object->symbolTable();
+ SymbolTable::iterator iter = symbolTable.find(propertyName.publicName());
+ if (iter == symbolTable.end())
+ return false;
+ SymbolTableEntry::Fast entry = iter->second;
+ ASSERT(!entry.isNull());
+ slot.setValue(object->registerAt(entry.getIndex()).get());
+ slotIsWriteable = !entry.isReadOnly();
+ return true;
+}
+
+template<typename SymbolTableObjectType>
+inline bool symbolTablePut(
+ SymbolTableObjectType* object, ExecState* exec, PropertyName propertyName, JSValue value,
+ bool shouldThrow)
+{
+ JSGlobalData& globalData = exec->globalData();
+ ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(object));
+
+ SymbolTable& symbolTable = object->symbolTable();
+ SymbolTable::iterator iter = symbolTable.find(propertyName.publicName());
+ if (iter == symbolTable.end())
+ return false;
+ bool wasFat;
+ SymbolTableEntry::Fast fastEntry = iter->second.getFast(wasFat);
+ ASSERT(!fastEntry.isNull());
+ if (fastEntry.isReadOnly()) {
+ if (shouldThrow)
+ throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
+ return true;
+ }
+ if (UNLIKELY(wasFat))
+ iter->second.notifyWrite();
+ object->registerAt(fastEntry.getIndex()).set(globalData, object, value);
+ return true;
+}
+
+template<typename SymbolTableObjectType>
+inline bool symbolTablePutWithAttributes(
+ SymbolTableObjectType* object, JSGlobalData& globalData, PropertyName propertyName,
+ JSValue value, unsigned attributes)
+{
+ ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(object));
+
+ SymbolTable::iterator iter = object->symbolTable().find(propertyName.publicName());
+ if (iter == object->symbolTable().end())
+ return false;
+ SymbolTableEntry& entry = iter->second;
+ ASSERT(!entry.isNull());
+ entry.notifyWrite();
+ entry.setAttributes(attributes);
+ object->registerAt(entry.getIndex()).set(globalData, object, value);
+ return true;
+}
+
+} // namespace JSC
+
+#endif // JSSymbolTableObject_h
+
diff --git a/Source/JavaScriptCore/runtime/JSVariableObject.cpp b/Source/JavaScriptCore/runtime/JSVariableObject.cpp
index 9dcbead34..7210c9b90 100644
--- a/Source/JavaScriptCore/runtime/JSVariableObject.cpp
+++ b/Source/JavaScriptCore/runtime/JSVariableObject.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007, 2008, 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
@@ -29,12 +29,6 @@
#include "config.h"
#include "JSVariableObject.h"
-#include "JSActivation.h"
-#include "JSGlobalObject.h"
-#include "JSStaticScopeObject.h"
-#include "PropertyNameArray.h"
-#include "PropertyDescriptor.h"
-
namespace JSC {
void JSVariableObject::destroy(JSCell* cell)
@@ -42,57 +36,4 @@ void JSVariableObject::destroy(JSCell* cell)
static_cast<JSVariableObject*>(cell)->JSVariableObject::~JSVariableObject();
}
-bool JSVariableObject::deleteProperty(JSCell* cell, ExecState* exec, PropertyName propertyName)
-{
- JSVariableObject* thisObject = jsCast<JSVariableObject*>(cell);
- if (thisObject->symbolTable().contains(propertyName.publicName()))
- return false;
-
- return JSObject::deleteProperty(thisObject, exec, propertyName);
-}
-
-void JSVariableObject::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
-{
- JSVariableObject* thisObject = jsCast<JSVariableObject*>(object);
- SymbolTable::const_iterator end = thisObject->symbolTable().end();
- for (SymbolTable::const_iterator it = thisObject->symbolTable().begin(); it != end; ++it) {
- if (!(it->second.getAttributes() & DontEnum) || (mode == IncludeDontEnumProperties))
- propertyNames.add(Identifier(exec, it->first.get()));
- }
-
- JSObject::getOwnPropertyNames(thisObject, exec, propertyNames, mode);
-}
-
-bool JSVariableObject::symbolTableGet(PropertyName propertyName, PropertyDescriptor& descriptor)
-{
- SymbolTableEntry entry = symbolTable().inlineGet(propertyName.publicName());
- if (!entry.isNull()) {
- descriptor.setDescriptor(registerAt(entry.getIndex()).get(), entry.getAttributes() | DontDelete);
- return true;
- }
- return false;
-}
-
-void JSVariableObject::putDirectVirtual(JSObject*, ExecState*, PropertyName, JSValue, unsigned)
-{
- ASSERT_NOT_REACHED();
-}
-
-bool JSVariableObject::isDynamicScope(bool& requiresDynamicChecks) const
-{
- switch (structure()->typeInfo().type()) {
- case GlobalObjectType:
- return static_cast<const JSGlobalObject*>(this)->isDynamicScope(requiresDynamicChecks);
- case ActivationObjectType:
- return static_cast<const JSActivation*>(this)->isDynamicScope(requiresDynamicChecks);
- case StaticScopeObjectType:
- return static_cast<const JSStaticScopeObject*>(this)->isDynamicScope(requiresDynamicChecks);
- default:
- ASSERT_NOT_REACHED();
- break;
- }
-
- return false;
-}
-
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/JSVariableObject.h b/Source/JavaScriptCore/runtime/JSVariableObject.h
index ea2798457..46fe72684 100644
--- a/Source/JavaScriptCore/runtime/JSVariableObject.h
+++ b/Source/JavaScriptCore/runtime/JSVariableObject.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007, 2008, 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
@@ -30,6 +30,7 @@
#define JSVariableObject_h
#include "JSObject.h"
+#include "JSSymbolTableObject.h"
#include "Register.h"
#include "SymbolTable.h"
#include <wtf/UnusedParam.h>
@@ -41,40 +42,25 @@ namespace JSC {
class LLIntOffsetsExtractor;
class Register;
- class JSVariableObject : public JSNonFinalObject {
+ class JSVariableObject : public JSSymbolTableObject {
friend class JIT;
friend class LLIntOffsetsExtractor;
public:
- typedef JSNonFinalObject Base;
-
- SymbolTable& symbolTable() const { return *m_symbolTable; }
-
- JS_EXPORT_PRIVATE static void destroy(JSCell*);
-
- static NO_RETURN_DUE_TO_ASSERT void putDirectVirtual(JSObject*, ExecState*, PropertyName, JSValue, unsigned attributes);
-
- JS_EXPORT_PRIVATE static bool deleteProperty(JSCell*, ExecState*, PropertyName);
- JS_EXPORT_PRIVATE static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
-
- bool isDynamicScope(bool& requiresDynamicChecks) const;
+ typedef JSSymbolTableObject Base;
WriteBarrier<Unknown>& registerAt(int index) const { return m_registers[index]; }
WriteBarrier<Unknown>* const * addressOfRegisters() const { return &m_registers; }
static size_t offsetOfRegisters() { return OBJECT_OFFSETOF(JSVariableObject, m_registers); }
- static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
- {
- return Structure::create(globalData, globalObject, prototype, TypeInfo(VariableObjectType, StructureFlags), &s_info);
- }
-
+ JS_EXPORT_PRIVATE static void destroy(JSCell*);
+
protected:
- static const unsigned StructureFlags = OverridesGetPropertyNames | JSNonFinalObject::StructureFlags;
+ static const unsigned StructureFlags = JSSymbolTableObject::StructureFlags;
JSVariableObject(JSGlobalData& globalData, Structure* structure, SymbolTable* symbolTable, Register* registers)
- : JSNonFinalObject(globalData, structure)
- , m_symbolTable(symbolTable)
+ : JSSymbolTableObject(globalData, structure, symbolTable)
, m_registers(reinterpret_cast<WriteBarrier<Unknown>*>(registers))
{
}
@@ -82,76 +68,16 @@ namespace JSC {
void finishCreation(JSGlobalData& globalData)
{
Base::finishCreation(globalData);
- ASSERT(m_symbolTable);
COMPILE_ASSERT(sizeof(WriteBarrier<Unknown>) == sizeof(Register), Register_should_be_same_size_as_WriteBarrier);
}
PassOwnArrayPtr<WriteBarrier<Unknown> > copyRegisterArray(JSGlobalData&, WriteBarrier<Unknown>* src, size_t count, size_t callframeStarts);
void setRegisters(WriteBarrier<Unknown>* registers, PassOwnArrayPtr<WriteBarrier<Unknown> > registerArray);
- bool symbolTableGet(PropertyName, PropertySlot&);
- JS_EXPORT_PRIVATE bool symbolTableGet(PropertyName, PropertyDescriptor&);
- bool symbolTableGet(PropertyName, PropertySlot&, bool& slotIsWriteable);
- bool symbolTablePut(ExecState*, PropertyName, JSValue, bool shouldThrow);
- bool symbolTablePutWithAttributes(JSGlobalData&, PropertyName, JSValue, unsigned attributes);
-
- SymbolTable* m_symbolTable; // Maps name -> offset from "r" in register file.
WriteBarrier<Unknown>* m_registers; // "r" in the register file.
OwnArrayPtr<WriteBarrier<Unknown> > m_registerArray; // Independent copy of registers, used when a variable object copies its registers out of the register file.
};
- inline bool JSVariableObject::symbolTableGet(PropertyName propertyName, PropertySlot& slot)
- {
- SymbolTableEntry entry = symbolTable().inlineGet(propertyName.publicName());
- if (!entry.isNull()) {
- slot.setValue(registerAt(entry.getIndex()).get());
- return true;
- }
- return false;
- }
-
- inline bool JSVariableObject::symbolTableGet(PropertyName propertyName, PropertySlot& slot, bool& slotIsWriteable)
- {
- SymbolTableEntry entry = symbolTable().inlineGet(propertyName.publicName());
- if (!entry.isNull()) {
- slot.setValue(registerAt(entry.getIndex()).get());
- slotIsWriteable = !entry.isReadOnly();
- return true;
- }
- return false;
- }
-
- inline bool JSVariableObject::symbolTablePut(ExecState* exec, PropertyName propertyName, JSValue value, bool shouldThrow)
- {
- JSGlobalData& globalData = exec->globalData();
- ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
-
- SymbolTableEntry entry = symbolTable().inlineGet(propertyName.publicName());
- if (entry.isNull())
- return false;
- if (entry.isReadOnly()) {
- if (shouldThrow)
- throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
- return true;
- }
- registerAt(entry.getIndex()).set(globalData, this, value);
- return true;
- }
-
- inline bool JSVariableObject::symbolTablePutWithAttributes(JSGlobalData& globalData, PropertyName propertyName, JSValue value, unsigned attributes)
- {
- ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
-
- SymbolTable::iterator iter = symbolTable().find(propertyName.publicName());
- if (iter == symbolTable().end())
- return false;
- SymbolTableEntry& entry = iter->second;
- ASSERT(!entry.isNull());
- entry.setAttributes(attributes);
- registerAt(entry.getIndex()).set(globalData, this, value);
- return true;
- }
-
inline PassOwnArrayPtr<WriteBarrier<Unknown> > JSVariableObject::copyRegisterArray(JSGlobalData& globalData, WriteBarrier<Unknown>* src, size_t count, size_t callframeStarts)
{
OwnArrayPtr<WriteBarrier<Unknown> > registerArray = adoptArrayPtr(new WriteBarrier<Unknown>[count]);
diff --git a/Source/JavaScriptCore/runtime/Lookup.h b/Source/JavaScriptCore/runtime/Lookup.h
index a75b521cd..ccb08128d 100644
--- a/Source/JavaScriptCore/runtime/Lookup.h
+++ b/Source/JavaScriptCore/runtime/Lookup.h
@@ -114,6 +114,13 @@ namespace JSC {
const HashTableValue* values; // Fixed values generated by script.
mutable const HashEntry* table; // Table allocated at runtime.
+ ALWAYS_INLINE HashTable copy() const
+ {
+ // Don't copy dynamic table since it's thread specific.
+ HashTable result = { compactSize, compactHashSizeMask, values, 0 };
+ return result;
+ }
+
ALWAYS_INLINE void initializeIfNeeded(JSGlobalData* globalData) const
{
if (!table)
diff --git a/Source/JavaScriptCore/runtime/MathObject.cpp b/Source/JavaScriptCore/runtime/MathObject.cpp
index 9d83290a5..2a550a38b 100644
--- a/Source/JavaScriptCore/runtime/MathObject.cpp
+++ b/Source/JavaScriptCore/runtime/MathObject.cpp
@@ -202,6 +202,43 @@ EncodedJSValue JSC_HOST_CALL mathProtoFuncMin(ExecState* exec)
return JSValue::encode(jsNumber(result));
}
+#if PLATFORM(IOS) && CPU(ARM_THUMB2)
+
+static double fdlibmPow(double x, double y);
+
+static ALWAYS_INLINE bool isDenormal(double x)
+{
+ static const uint64_t signbit = 0x8000000000000000ULL;
+ static const uint64_t minNormal = 0x0001000000000000ULL;
+ return (bitwise_cast<uint64_t>(x) & ~signbit) - 1 < minNormal - 1;
+}
+
+static ALWAYS_INLINE bool isEdgeCase(double x)
+{
+ static const uint64_t signbit = 0x8000000000000000ULL;
+ static const uint64_t infinity = 0x7fffffffffffffffULL;
+ return (bitwise_cast<uint64_t>(x) & ~signbit) - 1 >= infinity - 1;
+}
+
+static ALWAYS_INLINE double mathPow(double x, double y)
+{
+ if (!isDenormal(x) && !isDenormal(y)) {
+ double libmResult = pow(x,y);
+ if (libmResult || isEdgeCase(x) || isEdgeCase(y))
+ return libmResult;
+ }
+ return fdlibmPow(x,y);
+}
+
+#else
+
+ALWAYS_INLINE double mathPow(double x, double y)
+{
+ return pow(x, y);
+}
+
+#endif
+
EncodedJSValue JSC_HOST_CALL mathProtoFuncPow(ExecState* exec)
{
// ECMA 15.8.2.1.13
@@ -213,7 +250,7 @@ EncodedJSValue JSC_HOST_CALL mathProtoFuncPow(ExecState* exec)
return JSValue::encode(jsNaN());
if (isinf(arg2) && fabs(arg) == 1)
return JSValue::encode(jsNaN());
- return JSValue::encode(jsNumber(pow(arg, arg2)));
+ return JSValue::encode(jsNumber(mathPow(arg, arg2)));
}
EncodedJSValue JSC_HOST_CALL mathProtoFuncRandom(ExecState* exec)
@@ -243,4 +280,353 @@ EncodedJSValue JSC_HOST_CALL mathProtoFuncTan(ExecState* exec)
return JSValue::encode(jsDoubleNumber(tan(exec->argument(0).toNumber(exec))));
}
+#if PLATFORM(IOS) && CPU(ARM_THUMB2)
+
+// The following code is taken from netlib.org:
+// http://www.netlib.org/fdlibm/fdlibm.h
+// http://www.netlib.org/fdlibm/e_pow.c
+// http://www.netlib.org/fdlibm/s_scalbn.c
+//
+// And was originally distributed under the following license:
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+/*
+ * ====================================================
+ * Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* __ieee754_pow(x,y) return x**y
+ *
+ * n
+ * Method: Let x = 2 * (1+f)
+ * 1. Compute and return log2(x) in two pieces:
+ * log2(x) = w1 + w2,
+ * where w1 has 53-24 = 29 bit trailing zeros.
+ * 2. Perform y*log2(x) = n+y' by simulating muti-precision
+ * arithmetic, where |y'|<=0.5.
+ * 3. Return x**y = 2**n*exp(y'*log2)
+ *
+ * Special cases:
+ * 1. (anything) ** 0 is 1
+ * 2. (anything) ** 1 is itself
+ * 3. (anything) ** NAN is NAN
+ * 4. NAN ** (anything except 0) is NAN
+ * 5. +-(|x| > 1) ** +INF is +INF
+ * 6. +-(|x| > 1) ** -INF is +0
+ * 7. +-(|x| < 1) ** +INF is +0
+ * 8. +-(|x| < 1) ** -INF is +INF
+ * 9. +-1 ** +-INF is NAN
+ * 10. +0 ** (+anything except 0, NAN) is +0
+ * 11. -0 ** (+anything except 0, NAN, odd integer) is +0
+ * 12. +0 ** (-anything except 0, NAN) is +INF
+ * 13. -0 ** (-anything except 0, NAN, odd integer) is +INF
+ * 14. -0 ** (odd integer) = -( +0 ** (odd integer) )
+ * 15. +INF ** (+anything except 0,NAN) is +INF
+ * 16. +INF ** (-anything except 0,NAN) is +0
+ * 17. -INF ** (anything) = -0 ** (-anything)
+ * 18. (-anything) ** (integer) is (-1)**(integer)*(+anything**integer)
+ * 19. (-anything except 0 and inf) ** (non-integer) is NAN
+ *
+ * Accuracy:
+ * pow(x,y) returns x**y nearly rounded. In particular
+ * pow(integer,integer)
+ * always returns the correct integer provided it is
+ * representable.
+ *
+ * Constants :
+ * The hexadecimal values are the intended ones for the following
+ * constants. The decimal values may be used, provided that the
+ * compiler will convert from decimal to binary accurately enough
+ * to produce the hexadecimal values shown.
+ */
+
+#define __HI(x) *(1+(int*)&x)
+#define __LO(x) *(int*)&x
+
+static const double
+bp[] = {1.0, 1.5,},
+dp_h[] = { 0.0, 5.84962487220764160156e-01,}, /* 0x3FE2B803, 0x40000000 */
+dp_l[] = { 0.0, 1.35003920212974897128e-08,}, /* 0x3E4CFDEB, 0x43CFD006 */
+zero = 0.0,
+one = 1.0,
+two = 2.0,
+two53 = 9007199254740992.0, /* 0x43400000, 0x00000000 */
+huge = 1.0e300,
+tiny = 1.0e-300,
+ /* for scalbn */
+two54 = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */
+twom54 = 5.55111512312578270212e-17, /* 0x3C900000, 0x00000000 */
+ /* poly coefs for (3/2)*(log(x)-2s-2/3*s**3 */
+L1 = 5.99999999999994648725e-01, /* 0x3FE33333, 0x33333303 */
+L2 = 4.28571428578550184252e-01, /* 0x3FDB6DB6, 0xDB6FABFF */
+L3 = 3.33333329818377432918e-01, /* 0x3FD55555, 0x518F264D */
+L4 = 2.72728123808534006489e-01, /* 0x3FD17460, 0xA91D4101 */
+L5 = 2.30660745775561754067e-01, /* 0x3FCD864A, 0x93C9DB65 */
+L6 = 2.06975017800338417784e-01, /* 0x3FCA7E28, 0x4A454EEF */
+P1 = 1.66666666666666019037e-01, /* 0x3FC55555, 0x5555553E */
+P2 = -2.77777777770155933842e-03, /* 0xBF66C16C, 0x16BEBD93 */
+P3 = 6.61375632143793436117e-05, /* 0x3F11566A, 0xAF25DE2C */
+P4 = -1.65339022054652515390e-06, /* 0xBEBBBD41, 0xC5D26BF1 */
+P5 = 4.13813679705723846039e-08, /* 0x3E663769, 0x72BEA4D0 */
+lg2 = 6.93147180559945286227e-01, /* 0x3FE62E42, 0xFEFA39EF */
+lg2_h = 6.93147182464599609375e-01, /* 0x3FE62E43, 0x00000000 */
+lg2_l = -1.90465429995776804525e-09, /* 0xBE205C61, 0x0CA86C39 */
+ovt = 8.0085662595372944372e-0017, /* -(1024-log2(ovfl+.5ulp)) */
+cp = 9.61796693925975554329e-01, /* 0x3FEEC709, 0xDC3A03FD =2/(3ln2) */
+cp_h = 9.61796700954437255859e-01, /* 0x3FEEC709, 0xE0000000 =(float)cp */
+cp_l = -7.02846165095275826516e-09, /* 0xBE3E2FE0, 0x145B01F5 =tail of cp_h*/
+ivln2 = 1.44269504088896338700e+00, /* 0x3FF71547, 0x652B82FE =1/ln2 */
+ivln2_h = 1.44269502162933349609e+00, /* 0x3FF71547, 0x60000000 =24b 1/ln2*/
+ivln2_l = 1.92596299112661746887e-08; /* 0x3E54AE0B, 0xF85DDF44 =1/ln2 tail*/
+
+inline double fdlibmScalbn (double x, int n)
+{
+ int k,hx,lx;
+ hx = __HI(x);
+ lx = __LO(x);
+ k = (hx&0x7ff00000)>>20; /* extract exponent */
+ if (k==0) { /* 0 or subnormal x */
+ if ((lx|(hx&0x7fffffff))==0) return x; /* +-0 */
+ x *= two54;
+ hx = __HI(x);
+ k = ((hx&0x7ff00000)>>20) - 54;
+ if (n< -50000) return tiny*x; /*underflow*/
+ }
+ if (k==0x7ff) return x+x; /* NaN or Inf */
+ k = k+n;
+ if (k > 0x7fe) return huge*copysign(huge,x); /* overflow */
+ if (k > 0) /* normal result */
+ {__HI(x) = (hx&0x800fffff)|(k<<20); return x;}
+ if (k <= -54) {
+ if (n > 50000) /* in case integer overflow in n+k */
+ return huge*copysign(huge,x); /*overflow*/
+ else return tiny*copysign(tiny,x); /*underflow*/
+ }
+ k += 54; /* subnormal result */
+ __HI(x) = (hx&0x800fffff)|(k<<20);
+ return x*twom54;
+}
+
+double fdlibmPow(double x, double y)
+{
+ double z,ax,z_h,z_l,p_h,p_l;
+ double y1,t1,t2,r,s,t,u,v,w;
+ int i0,i1,i,j,k,yisint,n;
+ int hx,hy,ix,iy;
+ unsigned lx,ly;
+
+ i0 = ((*(int*)&one)>>29)^1; i1=1-i0;
+ hx = __HI(x); lx = __LO(x);
+ hy = __HI(y); ly = __LO(y);
+ ix = hx&0x7fffffff; iy = hy&0x7fffffff;
+
+ /* y==zero: x**0 = 1 */
+ if((iy|ly)==0) return one;
+
+ /* +-NaN return x+y */
+ if(ix > 0x7ff00000 || ((ix==0x7ff00000)&&(lx!=0)) ||
+ iy > 0x7ff00000 || ((iy==0x7ff00000)&&(ly!=0)))
+ return x+y;
+
+ /* determine if y is an odd int when x < 0
+ * yisint = 0 ... y is not an integer
+ * yisint = 1 ... y is an odd int
+ * yisint = 2 ... y is an even int
+ */
+ yisint = 0;
+ if(hx<0) {
+ if(iy>=0x43400000) yisint = 2; /* even integer y */
+ else if(iy>=0x3ff00000) {
+ k = (iy>>20)-0x3ff; /* exponent */
+ if(k>20) {
+ j = ly>>(52-k);
+ if(static_cast<unsigned>(j<<(52-k))==ly) yisint = 2-(j&1);
+ } else if(ly==0) {
+ j = iy>>(20-k);
+ if((j<<(20-k))==iy) yisint = 2-(j&1);
+ }
+ }
+ }
+
+ /* special value of y */
+ if(ly==0) {
+ if (iy==0x7ff00000) { /* y is +-inf */
+ if(((ix-0x3ff00000)|lx)==0)
+ return y - y; /* inf**+-1 is NaN */
+ else if (ix >= 0x3ff00000)/* (|x|>1)**+-inf = inf,0 */
+ return (hy>=0)? y: zero;
+ else /* (|x|<1)**-,+inf = inf,0 */
+ return (hy<0)?-y: zero;
+ }
+ if(iy==0x3ff00000) { /* y is +-1 */
+ if(hy<0) return one/x; else return x;
+ }
+ if(hy==0x40000000) return x*x; /* y is 2 */
+ if(hy==0x3fe00000) { /* y is 0.5 */
+ if(hx>=0) /* x >= +0 */
+ return sqrt(x);
+ }
+ }
+
+ ax = fabs(x);
+ /* special value of x */
+ if(lx==0) {
+ if(ix==0x7ff00000||ix==0||ix==0x3ff00000){
+ z = ax; /*x is +-0,+-inf,+-1*/
+ if(hy<0) z = one/z; /* z = (1/|x|) */
+ if(hx<0) {
+ if(((ix-0x3ff00000)|yisint)==0) {
+ z = (z-z)/(z-z); /* (-1)**non-int is NaN */
+ } else if(yisint==1)
+ z = -z; /* (x<0)**odd = -(|x|**odd) */
+ }
+ return z;
+ }
+ }
+
+ n = (hx>>31)+1;
+
+ /* (x<0)**(non-int) is NaN */
+ if((n|yisint)==0) return (x-x)/(x-x);
+
+ s = one; /* s (sign of result -ve**odd) = -1 else = 1 */
+ if((n|(yisint-1))==0) s = -one;/* (-ve)**(odd int) */
+
+ /* |y| is huge */
+ if(iy>0x41e00000) { /* if |y| > 2**31 */
+ if(iy>0x43f00000){ /* if |y| > 2**64, must o/uflow */
+ if(ix<=0x3fefffff) return (hy<0)? huge*huge:tiny*tiny;
+ if(ix>=0x3ff00000) return (hy>0)? huge*huge:tiny*tiny;
+ }
+ /* over/underflow if x is not close to one */
+ if(ix<0x3fefffff) return (hy<0)? s*huge*huge:s*tiny*tiny;
+ if(ix>0x3ff00000) return (hy>0)? s*huge*huge:s*tiny*tiny;
+ /* now |1-x| is tiny <= 2**-20, suffice to compute
+ log(x) by x-x^2/2+x^3/3-x^4/4 */
+ t = ax-one; /* t has 20 trailing zeros */
+ w = (t*t)*(0.5-t*(0.3333333333333333333333-t*0.25));
+ u = ivln2_h*t; /* ivln2_h has 21 sig. bits */
+ v = t*ivln2_l-w*ivln2;
+ t1 = u+v;
+ __LO(t1) = 0;
+ t2 = v-(t1-u);
+ } else {
+ double ss,s2,s_h,s_l,t_h,t_l;
+ n = 0;
+ /* take care subnormal number */
+ if(ix<0x00100000)
+ {ax *= two53; n -= 53; ix = __HI(ax); }
+ n += ((ix)>>20)-0x3ff;
+ j = ix&0x000fffff;
+ /* determine interval */
+ ix = j|0x3ff00000; /* normalize ix */
+ if(j<=0x3988E) k=0; /* |x|<sqrt(3/2) */
+ else if(j<0xBB67A) k=1; /* |x|<sqrt(3) */
+ else {k=0;n+=1;ix -= 0x00100000;}
+ __HI(ax) = ix;
+
+ /* compute ss = s_h+s_l = (x-1)/(x+1) or (x-1.5)/(x+1.5) */
+ u = ax-bp[k]; /* bp[0]=1.0, bp[1]=1.5 */
+ v = one/(ax+bp[k]);
+ ss = u*v;
+ s_h = ss;
+ __LO(s_h) = 0;
+ /* t_h=ax+bp[k] High */
+ t_h = zero;
+ __HI(t_h)=((ix>>1)|0x20000000)+0x00080000+(k<<18);
+ t_l = ax - (t_h-bp[k]);
+ s_l = v*((u-s_h*t_h)-s_h*t_l);
+ /* compute log(ax) */
+ s2 = ss*ss;
+ r = s2*s2*(L1+s2*(L2+s2*(L3+s2*(L4+s2*(L5+s2*L6)))));
+ r += s_l*(s_h+ss);
+ s2 = s_h*s_h;
+ t_h = 3.0+s2+r;
+ __LO(t_h) = 0;
+ t_l = r-((t_h-3.0)-s2);
+ /* u+v = ss*(1+...) */
+ u = s_h*t_h;
+ v = s_l*t_h+t_l*ss;
+ /* 2/(3log2)*(ss+...) */
+ p_h = u+v;
+ __LO(p_h) = 0;
+ p_l = v-(p_h-u);
+ z_h = cp_h*p_h; /* cp_h+cp_l = 2/(3*log2) */
+ z_l = cp_l*p_h+p_l*cp+dp_l[k];
+ /* log2(ax) = (ss+..)*2/(3*log2) = n + dp_h + z_h + z_l */
+ t = (double)n;
+ t1 = (((z_h+z_l)+dp_h[k])+t);
+ __LO(t1) = 0;
+ t2 = z_l-(((t1-t)-dp_h[k])-z_h);
+ }
+
+ /* split up y into y1+y2 and compute (y1+y2)*(t1+t2) */
+ y1 = y;
+ __LO(y1) = 0;
+ p_l = (y-y1)*t1+y*t2;
+ p_h = y1*t1;
+ z = p_l+p_h;
+ j = __HI(z);
+ i = __LO(z);
+ if (j>=0x40900000) { /* z >= 1024 */
+ if(((j-0x40900000)|i)!=0) /* if z > 1024 */
+ return s*huge*huge; /* overflow */
+ else {
+ if(p_l+ovt>z-p_h) return s*huge*huge; /* overflow */
+ }
+ } else if((j&0x7fffffff)>=0x4090cc00 ) { /* z <= -1075 */
+ if(((j-0xc090cc00)|i)!=0) /* z < -1075 */
+ return s*tiny*tiny; /* underflow */
+ else {
+ if(p_l<=z-p_h) return s*tiny*tiny; /* underflow */
+ }
+ }
+ /*
+ * compute 2**(p_h+p_l)
+ */
+ i = j&0x7fffffff;
+ k = (i>>20)-0x3ff;
+ n = 0;
+ if(i>0x3fe00000) { /* if |z| > 0.5, set n = [z+0.5] */
+ n = j+(0x00100000>>(k+1));
+ k = ((n&0x7fffffff)>>20)-0x3ff; /* new k for n */
+ t = zero;
+ __HI(t) = (n&~(0x000fffff>>k));
+ n = ((n&0x000fffff)|0x00100000)>>(20-k);
+ if(j<0) n = -n;
+ p_h -= t;
+ }
+ t = p_l+p_h;
+ __LO(t) = 0;
+ u = t*lg2_h;
+ v = (p_l-(t-p_h))*lg2+t*lg2_l;
+ z = u+v;
+ w = v-(z-u);
+ t = z*z;
+ t1 = z - t*(P1+t*(P2+t*(P3+t*(P4+t*P5))));
+ r = (z*t1)/(t1-two)-(w+z*w);
+ z = one-(r-z);
+ j = __HI(z);
+ j += (n<<20);
+ if((j>>20)<=0) z = fdlibmScalbn(z,n); /* subnormal output */
+ else __HI(z) += (n<<20);
+ return s*z;
+}
+
+#endif
+
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/Options.cpp b/Source/JavaScriptCore/runtime/Options.cpp
index 8f5a05067..ec228f82a 100644
--- a/Source/JavaScriptCore/runtime/Options.cpp
+++ b/Source/JavaScriptCore/runtime/Options.cpp
@@ -47,6 +47,8 @@ namespace JSC { namespace Options {
bool useJIT;
+bool showDisassembly;
+
unsigned maximumOptimizationCandidateInstructionCount;
unsigned maximumFunctionForCallInlineCandidateInstructionCount;
@@ -89,9 +91,6 @@ double doubleVoteRatioForDoubleFormat;
unsigned minimumNumberOfScansBetweenRebalance;
unsigned gcMarkStackSegmentSize;
-unsigned minimumNumberOfCellsToKeep;
-unsigned maximumNumberOfSharedSegments;
-unsigned sharedStackWakeupThreshold;
unsigned numberOfGCMarkers;
unsigned opaqueRootMergeThreshold;
@@ -145,10 +144,28 @@ void setHeuristic(T& variable, const char* name, U value)
#define SET(variable, value) variable = value
#endif
+static unsigned computeNumberOfGCMarkers(int maxNumberOfGCMarkers)
+{
+ int cpusToUse = 1;
+
+#if ENABLE(PARALLEL_GC)
+ cpusToUse = std::min(WTF::numberOfProcessorCores(), maxNumberOfGCMarkers);
+
+ // Be paranoid, it is the OS we're dealing with, after all.
+ ASSERT(cpusToUse >= 1);
+ if (cpusToUse < 1)
+ cpusToUse = 1;
+#endif
+
+ return cpusToUse;
+}
+
void initializeOptions()
{
SET(useJIT, true);
+ SET(showDisassembly, false);
+
SET(maximumOptimizationCandidateInstructionCount, 10000);
SET(maximumFunctionForCallInlineCandidateInstructionCount, 180);
@@ -188,25 +205,10 @@ void initializeOptions()
SET(doubleVoteRatioForDoubleFormat, 2);
- SET(minimumNumberOfScansBetweenRebalance, 10000);
+ SET(minimumNumberOfScansBetweenRebalance, 100);
SET(gcMarkStackSegmentSize, pageSize());
- SET(minimumNumberOfCellsToKeep, 10);
- SET(maximumNumberOfSharedSegments, 3);
- SET(sharedStackWakeupThreshold, 1);
SET(opaqueRootMergeThreshold, 1000);
-
- int cpusToUse = 1;
-#if ENABLE(PARALLEL_GC)
- cpusToUse = WTF::numberOfProcessorCores();
-#endif
- // We don't scale so well beyond 4.
- if (cpusToUse > 4)
- cpusToUse = 4;
- // Be paranoid, it is the OS we're dealing with, after all.
- if (cpusToUse < 1)
- cpusToUse = 1;
-
- SET(numberOfGCMarkers, cpusToUse);
+ SET(numberOfGCMarkers, computeNumberOfGCMarkers(7)); // We don't scale so well beyond 7.
ASSERT(thresholdForOptimizeAfterLongWarmUp >= thresholdForOptimizeAfterWarmUp);
ASSERT(thresholdForOptimizeAfterWarmUp >= thresholdForOptimizeSoon);
diff --git a/Source/JavaScriptCore/runtime/Options.h b/Source/JavaScriptCore/runtime/Options.h
index d1ad2ca87..e5cc99590 100644
--- a/Source/JavaScriptCore/runtime/Options.h
+++ b/Source/JavaScriptCore/runtime/Options.h
@@ -32,6 +32,8 @@ namespace JSC { namespace Options {
extern bool useJIT;
+extern bool showDisassembly;
+
extern unsigned maximumOptimizationCandidateInstructionCount;
extern unsigned maximumFunctionForCallInlineCandidateInstructionCount;
@@ -75,9 +77,6 @@ extern double doubleVoteRatioForDoubleFormat;
extern unsigned minimumNumberOfScansBetweenRebalance;
extern unsigned gcMarkStackSegmentSize;
-extern unsigned minimumNumberOfCellsToKeep;
-extern unsigned maximumNumberOfSharedSegments;
-extern unsigned sharedStackWakeupThreshold;
JS_EXPORTDATA extern unsigned numberOfGCMarkers;
JS_EXPORTDATA extern unsigned opaqueRootMergeThreshold;
diff --git a/Source/JavaScriptCore/runtime/Structure.cpp b/Source/JavaScriptCore/runtime/Structure.cpp
index dc4239799..569126147 100644
--- a/Source/JavaScriptCore/runtime/Structure.cpp
+++ b/Source/JavaScriptCore/runtime/Structure.cpp
@@ -155,6 +155,7 @@ Structure::Structure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSV
, m_globalObject(globalData, this, globalObject, WriteBarrier<JSGlobalObject>::MayBeNull)
, m_prototype(globalData, this, prototype)
, m_classInfo(classInfo)
+ , m_transitionWatchpointSet(InitializedWatching)
, m_propertyStorageCapacity(typeInfo.isFinalObject() ? JSFinalObject_inlineStorageCapacity : JSNonFinalObject_inlineStorageCapacity)
, m_offset(noOffset)
, m_dictionaryKind(NoneDictionaryKind)
@@ -177,6 +178,7 @@ Structure::Structure(JSGlobalData& globalData)
, m_typeInfo(CompoundType, OverridesVisitChildren)
, m_prototype(globalData, this, jsNull())
, m_classInfo(&s_info)
+ , m_transitionWatchpointSet(InitializedWatching)
, m_propertyStorageCapacity(0)
, m_offset(noOffset)
, m_dictionaryKind(NoneDictionaryKind)
@@ -197,6 +199,7 @@ Structure::Structure(JSGlobalData& globalData, const Structure* previous)
, m_typeInfo(previous->typeInfo())
, m_prototype(globalData, this, previous->storedPrototype())
, m_classInfo(previous->m_classInfo)
+ , m_transitionWatchpointSet(InitializedWatching)
, m_propertyStorageCapacity(previous->m_propertyStorageCapacity)
, m_offset(noOffset)
, m_dictionaryKind(previous->m_dictionaryKind)
@@ -210,6 +213,7 @@ Structure::Structure(JSGlobalData& globalData, const Structure* previous)
, m_didTransition(true)
, m_staticFunctionReified(previous->m_staticFunctionReified)
{
+ previous->notifyTransitionFromThisStructure();
if (previous->m_globalObject)
m_globalObject.set(globalData, this, previous->m_globalObject.get());
}
diff --git a/Source/JavaScriptCore/runtime/Structure.h b/Source/JavaScriptCore/runtime/Structure.h
index f67c4e7f7..448a81c27 100644
--- a/Source/JavaScriptCore/runtime/Structure.h
+++ b/Source/JavaScriptCore/runtime/Structure.h
@@ -37,6 +37,7 @@
#include "StructureTransitionTable.h"
#include "JSTypeInfo.h"
#include "UString.h"
+#include "Watchpoint.h"
#include "Weak.h"
#include <wtf/PassOwnPtr.h>
#include <wtf/PassRefPtr.h>
@@ -127,6 +128,8 @@ namespace JSC {
JSValue storedPrototype() const { return m_prototype.get(); }
JSValue prototypeForLookup(ExecState*) const;
+ JSValue prototypeForLookup(JSGlobalObject*) const;
+ JSValue prototypeForLookup(CodeBlock*) const;
StructureChain* prototypeChain(ExecState*) const;
static void visitChildren(JSCell*, SlotVisitor&);
@@ -208,6 +211,27 @@ namespace JSC {
return structure;
}
+ bool transitionWatchpointSetHasBeenInvalidated() const
+ {
+ return m_transitionWatchpointSet.hasBeenInvalidated();
+ }
+
+ bool transitionWatchpointSetIsStillValid() const
+ {
+ return m_transitionWatchpointSet.isStillValid();
+ }
+
+ void addTransitionWatchpoint(Watchpoint* watchpoint) const
+ {
+ ASSERT(transitionWatchpointSetIsStillValid());
+ m_transitionWatchpointSet.add(watchpoint);
+ }
+
+ void notifyTransitionFromThisStructure() const
+ {
+ m_transitionWatchpointSet.notifyWrite();
+ }
+
static JS_EXPORTDATA const ClassInfo s_info;
private:
@@ -291,9 +315,11 @@ namespace JSC {
OwnPtr<PropertyTable> m_propertyTable;
- uint32_t m_propertyStorageCapacity;
-
WriteBarrier<JSString> m_objectToStringValue;
+
+ mutable InlineWatchpointSet m_transitionWatchpointSet;
+
+ uint32_t m_propertyStorageCapacity;
// m_offset does not account for anonymous slots
int m_offset;
@@ -363,6 +389,9 @@ namespace JSC {
{
ASSERT(structure->typeInfo().overridesVisitChildren() == this->structure()->typeInfo().overridesVisitChildren());
ASSERT(structure->classInfo() == m_structure->classInfo());
+ ASSERT(!m_structure
+ || m_structure->transitionWatchpointSetHasBeenInvalidated()
+ || m_structure.get() == structure);
m_structure.set(globalData, this, structure);
}
@@ -382,10 +411,13 @@ namespace JSC {
#if ENABLE(GC_VALIDATION)
validate(cell);
#endif
- m_visitCount++;
if (Heap::testAndSetMarked(cell) || !cell->structure())
return;
+
+ m_visitCount++;
+ MARK_LOG_CHILD(*this, cell);
+
// Should never attempt to mark something that is zapped.
ASSERT(!cell->isZapped());
diff --git a/Source/JavaScriptCore/runtime/SymbolTable.cpp b/Source/JavaScriptCore/runtime/SymbolTable.cpp
new file mode 100644
index 000000000..2a9d71629
--- /dev/null
+++ b/Source/JavaScriptCore/runtime/SymbolTable.cpp
@@ -0,0 +1,94 @@
+/*
+ * 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.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE 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 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 "SymbolTable.h"
+
+namespace JSC {
+
+SymbolTableEntry& SymbolTableEntry::copySlow(const SymbolTableEntry& other)
+{
+ ASSERT(other.isFat());
+ FatEntry* newFatEntry = new FatEntry(*other.fatEntry());
+ freeFatEntry();
+ m_bits = bitwise_cast<intptr_t>(newFatEntry) | FatFlag;
+ return *this;
+}
+
+void SymbolTableEntry::freeFatEntrySlow()
+{
+ ASSERT(isFat());
+ delete fatEntry();
+}
+
+bool SymbolTableEntry::couldBeWatched()
+{
+ if (!isFat())
+ return false;
+ WatchpointSet* watchpoints = fatEntry()->m_watchpoints.get();
+ if (!watchpoints)
+ return false;
+ return watchpoints->isStillValid();
+}
+
+void SymbolTableEntry::attemptToWatch()
+{
+ FatEntry* entry = inflate();
+ if (!entry->m_watchpoints)
+ entry->m_watchpoints = adoptRef(new WatchpointSet(InitializedWatching));
+}
+
+bool* SymbolTableEntry::addressOfIsWatched()
+{
+ ASSERT(couldBeWatched());
+ return fatEntry()->m_watchpoints->addressOfIsWatched();
+}
+
+void SymbolTableEntry::addWatchpoint(Watchpoint* watchpoint)
+{
+ ASSERT(couldBeWatched());
+ fatEntry()->m_watchpoints->add(watchpoint);
+}
+
+void SymbolTableEntry::notifyWriteSlow()
+{
+ WatchpointSet* watchpoints = fatEntry()->m_watchpoints.get();
+ if (!watchpoints)
+ return;
+ watchpoints->notifyWrite();
+}
+
+SymbolTableEntry::FatEntry* SymbolTableEntry::inflateSlow()
+{
+ FatEntry* entry = new FatEntry(m_bits);
+ m_bits = bitwise_cast<intptr_t>(entry) | FatFlag;
+ return entry;
+}
+
+} // namespace JSC
+
diff --git a/Source/JavaScriptCore/runtime/SymbolTable.h b/Source/JavaScriptCore/runtime/SymbolTable.h
index f540a12c7..9ddc32c8c 100644
--- a/Source/JavaScriptCore/runtime/SymbolTable.h
+++ b/Source/JavaScriptCore/runtime/SymbolTable.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007, 2008, 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
@@ -31,53 +31,163 @@
#include "JSObject.h"
#include "UString.h"
+#include "Watchpoint.h"
#include <wtf/AlwaysInline.h>
#include <wtf/HashTraits.h>
namespace JSC {
+ class Watchpoint;
+ class WatchpointSet;
+
static ALWAYS_INLINE int missingSymbolMarker() { return std::numeric_limits<int>::max(); }
// The bit twiddling in this class assumes that every register index is a
// reasonably small positive or negative number, and therefore has its high
// four bits all set or all unset.
+ // In addition to implementing semantics-mandated variable attributes and
+ // implementation-mandated variable indexing, this class also implements
+ // watchpoints to be used for JIT optimizations. Because watchpoints are
+ // meant to be relatively rare, this class optimizes heavily for the case
+ // that they are not being used. To that end, this class uses the thin-fat
+ // idiom: either it is thin, in which case it contains an in-place encoded
+ // word that consists of attributes, the index, and a bit saying that it is
+ // thin; or it is fat, in which case it contains a pointer to a malloc'd
+ // data structure and a bit saying that it is fat. The malloc'd data
+ // structure will be malloced a second time upon copy, to preserve the
+ // property that in-place edits to SymbolTableEntry do not manifest in any
+ // copies. However, the malloc'd FatEntry data structure contains a ref-
+ // counted pointer to a shared WatchpointSet. Thus, in-place edits of the
+ // WatchpointSet will manifest in all copies. Here's a picture:
+ //
+ // SymbolTableEntry --> FatEntry --> WatchpointSet
+ //
+ // If you make a copy of a SymbolTableEntry, you will have:
+ //
+ // original: SymbolTableEntry --> FatEntry --> WatchpointSet
+ // copy: SymbolTableEntry --> FatEntry -----^
+
struct SymbolTableEntry {
+ // Use the SymbolTableEntry::Fast class, either via implicit cast or by calling
+ // getFast(), when you (1) only care about isNull(), getIndex(), and isReadOnly(),
+ // and (2) you are in a hot path where you need to minimize the number of times
+ // that you branch on isFat() when getting the bits().
+ class Fast {
+ public:
+ Fast()
+ : m_bits(0)
+ {
+ }
+
+ ALWAYS_INLINE Fast(const SymbolTableEntry& entry)
+ : m_bits(entry.bits())
+ {
+ }
+
+ bool isNull() const
+ {
+ return !m_bits;
+ }
+
+ int getIndex() const
+ {
+ return static_cast<int>(m_bits >> FlagBits);
+ }
+
+ bool isReadOnly() const
+ {
+ return m_bits & ReadOnlyFlag;
+ }
+
+ unsigned getAttributes() const
+ {
+ unsigned attributes = 0;
+ if (m_bits & ReadOnlyFlag)
+ attributes |= ReadOnly;
+ if (m_bits & DontEnumFlag)
+ attributes |= DontEnum;
+ return attributes;
+ }
+
+ bool isFat() const
+ {
+ return m_bits & FatFlag;
+ }
+
+ private:
+ friend struct SymbolTableEntry;
+ intptr_t m_bits;
+ };
+
SymbolTableEntry()
: m_bits(0)
{
}
SymbolTableEntry(int index)
+ : m_bits(0)
{
ASSERT(isValidIndex(index));
pack(index, false, false);
}
SymbolTableEntry(int index, unsigned attributes)
+ : m_bits(0)
{
ASSERT(isValidIndex(index));
pack(index, attributes & ReadOnly, attributes & DontEnum);
}
+ ~SymbolTableEntry()
+ {
+ freeFatEntry();
+ }
+
+ SymbolTableEntry(const SymbolTableEntry& other)
+ : m_bits(0)
+ {
+ *this = other;
+ }
+
+ SymbolTableEntry& operator=(const SymbolTableEntry& other)
+ {
+ if (UNLIKELY(other.isFat()))
+ return copySlow(other);
+ freeFatEntry();
+ m_bits = other.m_bits;
+ return *this;
+ }
+
bool isNull() const
{
- return !m_bits;
+ return !bits();
}
int getIndex() const
{
- return m_bits >> FlagBits;
+ return static_cast<int>(bits() >> FlagBits);
}
-
+
+ ALWAYS_INLINE Fast getFast() const
+ {
+ return Fast(*this);
+ }
+
+ ALWAYS_INLINE Fast getFast(bool& wasFat) const
+ {
+ Fast result;
+ wasFat = isFat();
+ if (wasFat)
+ result.m_bits = fatEntry()->m_bits;
+ else
+ result.m_bits = m_bits;
+ return result;
+ }
+
unsigned getAttributes() const
{
- unsigned attributes = 0;
- if (m_bits & ReadOnlyFlag)
- attributes |= ReadOnly;
- if (m_bits & DontEnumFlag)
- attributes |= DontEnum;
- return attributes;
+ return getFast().getAttributes();
}
void setAttributes(unsigned attributes)
@@ -87,30 +197,125 @@ namespace JSC {
bool isReadOnly() const
{
- return m_bits & ReadOnlyFlag;
+ return bits() & ReadOnlyFlag;
}
-
+
+ bool couldBeWatched();
+
+ // Notify an opportunity to create a watchpoint for a variable. This is
+ // idempotent and fail-silent. It is idempotent in the sense that if
+ // a watchpoint set had already been created, then another one will not
+ // be created. Hence two calls to this method have the same effect as
+ // one call. It is also fail-silent, in the sense that if a watchpoint
+ // set had been created and had already been invalidated, then this will
+ // just return. This means that couldBeWatched() may return false even
+ // immediately after a call to attemptToWatch().
+ void attemptToWatch();
+
+ bool* addressOfIsWatched();
+
+ void addWatchpoint(Watchpoint*);
+
+ WatchpointSet* watchpointSet()
+ {
+ return fatEntry()->m_watchpoints.get();
+ }
+
+ ALWAYS_INLINE void notifyWrite()
+ {
+ if (LIKELY(!isFat()))
+ return;
+ notifyWriteSlow();
+ }
+
private:
- static const unsigned ReadOnlyFlag = 0x1;
- static const unsigned DontEnumFlag = 0x2;
- static const unsigned NotNullFlag = 0x4;
- static const unsigned FlagBits = 3;
+ static const intptr_t FatFlag = 0x1;
+ static const intptr_t ReadOnlyFlag = 0x2;
+ static const intptr_t DontEnumFlag = 0x4;
+ static const intptr_t NotNullFlag = 0x8;
+ static const intptr_t FlagBits = 4;
+
+ class FatEntry {
+ WTF_MAKE_FAST_ALLOCATED;
+ public:
+ FatEntry(intptr_t bits)
+ : m_bits(bits | FatFlag)
+ {
+ }
+
+ intptr_t m_bits; // always has FatFlag set and exactly matches what the bits would have been if this wasn't fat.
+
+ RefPtr<WatchpointSet> m_watchpoints;
+ };
+
+ SymbolTableEntry& copySlow(const SymbolTableEntry&);
+ JS_EXPORT_PRIVATE void notifyWriteSlow();
+
+ bool isFat() const
+ {
+ return m_bits & FatFlag;
+ }
+
+ const FatEntry* fatEntry() const
+ {
+ ASSERT(isFat());
+ return bitwise_cast<const FatEntry*>(m_bits & ~FatFlag);
+ }
+
+ FatEntry* fatEntry()
+ {
+ ASSERT(isFat());
+ return bitwise_cast<FatEntry*>(m_bits & ~FatFlag);
+ }
+
+ FatEntry* inflate()
+ {
+ if (LIKELY(isFat()))
+ return fatEntry();
+ return inflateSlow();
+ }
+
+ FatEntry* inflateSlow();
+
+ ALWAYS_INLINE intptr_t bits() const
+ {
+ if (isFat())
+ return fatEntry()->m_bits;
+ return m_bits;
+ }
+
+ ALWAYS_INLINE intptr_t& bits()
+ {
+ if (isFat())
+ return fatEntry()->m_bits;
+ return m_bits;
+ }
+
+ void freeFatEntry()
+ {
+ if (LIKELY(!isFat()))
+ return;
+ freeFatEntrySlow();
+ }
+
+ void freeFatEntrySlow();
void pack(int index, bool readOnly, bool dontEnum)
{
- m_bits = (index << FlagBits) | NotNullFlag;
+ intptr_t& bitsRef = bits();
+ bitsRef = (static_cast<intptr_t>(index) << FlagBits) | NotNullFlag;
if (readOnly)
- m_bits |= ReadOnlyFlag;
+ bitsRef |= ReadOnlyFlag;
if (dontEnum)
- m_bits |= DontEnumFlag;
+ bitsRef |= DontEnumFlag;
}
bool isValidIndex(int index)
{
- return ((index << FlagBits) >> FlagBits) == index;
+ return ((static_cast<intptr_t>(index) << FlagBits) >> FlagBits) == static_cast<intptr_t>(index);
}
- int m_bits;
+ intptr_t m_bits;
};
struct SymbolTableIndexHashTraits : HashTraits<SymbolTableEntry> {
diff --git a/Source/JavaScriptCore/runtime/WriteBarrier.h b/Source/JavaScriptCore/runtime/WriteBarrier.h
index 05f3bc5bb..9784a921e 100644
--- a/Source/JavaScriptCore/runtime/WriteBarrier.h
+++ b/Source/JavaScriptCore/runtime/WriteBarrier.h
@@ -177,6 +177,9 @@ public:
return u.slot;
}
+ int32_t* tagPointer() { return &bitwise_cast<EncodedValueDescriptor*>(&m_value)->asBits.tag; }
+ int32_t* payloadPointer() { return &bitwise_cast<EncodedValueDescriptor*>(&m_value)->asBits.payload; }
+
typedef JSValue (WriteBarrierBase::*UnspecifiedBoolType);
operator UnspecifiedBoolType*() const { return get() ? reinterpret_cast<UnspecifiedBoolType*>(1) : 0; }
bool operator!() const { return !get(); }
diff --git a/Source/JavaScriptCore/shell/CMakeLists.txt b/Source/JavaScriptCore/shell/CMakeLists.txt
index 85ad89a88..561d779dd 100644
--- a/Source/JavaScriptCore/shell/CMakeLists.txt
+++ b/Source/JavaScriptCore/shell/CMakeLists.txt
@@ -19,10 +19,6 @@ IF (JSC_LINK_FLAGS)
ADD_TARGET_PROPERTIES(${JSC_EXECUTABLE_NAME} LINK_FLAGS "${JSC_LINK_FLAGS}")
ENDIF ()
-IF ("${PORT}" STREQUAL "Efl")
- SET_TARGET_PROPERTIES(${JSC_EXECUTABLE_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
-ENDIF ()
-
IF (SHOULD_INSTALL_JS_SHELL)
INSTALL(TARGETS ${JSC_EXECUTABLE_NAME} DESTINATION bin)
ENDIF ()
diff --git a/Source/JavaScriptCore/yarr/YarrJIT.cpp b/Source/JavaScriptCore/yarr/YarrJIT.cpp
index 60519ebd8..eb9861fed 100644
--- a/Source/JavaScriptCore/yarr/YarrJIT.cpp
+++ b/Source/JavaScriptCore/yarr/YarrJIT.cpp
@@ -2611,14 +2611,14 @@ public:
if (compileMode == MatchOnly) {
if (m_charSize == Char8)
- jitObject.set8BitCodeMatchOnly(linkBuffer.finalizeCode());
+ jitObject.set8BitCodeMatchOnly(FINALIZE_CODE(linkBuffer, ("Match-only 8-bit regular expression")));
else
- jitObject.set16BitCodeMatchOnly(linkBuffer.finalizeCode());
+ jitObject.set16BitCodeMatchOnly(FINALIZE_CODE(linkBuffer, ("Match-only 16-bit regular expression")));
} else {
if (m_charSize == Char8)
- jitObject.set8BitCode(linkBuffer.finalizeCode());
+ jitObject.set8BitCode(FINALIZE_CODE(linkBuffer, ("8-bit regular expression")));
else
- jitObject.set16BitCode(linkBuffer.finalizeCode());
+ jitObject.set16BitCode(FINALIZE_CODE(linkBuffer, ("16-bit regular expression")));
}
jitObject.setFallBack(m_shouldFallBack);
}