summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore
diff options
context:
space:
mode:
Diffstat (limited to 'Source/JavaScriptCore')
-rw-r--r--Source/JavaScriptCore/CMakeLists.txt2
-rw-r--r--Source/JavaScriptCore/ChangeLog485
-rw-r--r--Source/JavaScriptCore/Configurations/Base.xcconfig24
-rw-r--r--Source/JavaScriptCore/GNUmakefile.list.am5
-rw-r--r--Source/JavaScriptCore/JavaScriptCore.pri6
-rwxr-xr-xSource/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def3
-rw-r--r--Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj16
-rw-r--r--Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj16
-rw-r--r--Source/JavaScriptCore/Target.pri3
-rw-r--r--Source/JavaScriptCore/assembler/ARMv7Assembler.h50
-rw-r--r--Source/JavaScriptCore/assembler/AbstractMacroAssembler.h2
-rw-r--r--Source/JavaScriptCore/assembler/MIPSAssembler.h27
-rw-r--r--Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h14
-rw-r--r--Source/JavaScriptCore/bytecode/CallLinkInfo.cpp5
-rw-r--r--Source/JavaScriptCore/bytecode/CallLinkInfo.h2
-rw-r--r--Source/JavaScriptCore/bytecode/CodeBlock.cpp62
-rw-r--r--Source/JavaScriptCore/bytecode/CodeBlock.h14
-rw-r--r--Source/JavaScriptCore/bytecode/CodeOrigin.h8
-rw-r--r--Source/JavaScriptCore/bytecode/StructureStubClearingWatchpoint.cpp80
-rw-r--r--Source/JavaScriptCore/bytecode/StructureStubClearingWatchpoint.h109
-rw-r--r--Source/JavaScriptCore/bytecode/StructureStubInfo.h10
-rw-r--r--Source/JavaScriptCore/bytecode/Watchpoint.cpp59
-rw-r--r--Source/JavaScriptCore/bytecode/Watchpoint.h65
-rw-r--r--Source/JavaScriptCore/dfg/DFGAbstractState.cpp5
-rw-r--r--Source/JavaScriptCore/dfg/DFGAssemblyHelpers.h11
-rw-r--r--Source/JavaScriptCore/dfg/DFGBasicBlock.h2
-rw-r--r--Source/JavaScriptCore/dfg/DFGCCallHelpers.h2
-rw-r--r--Source/JavaScriptCore/dfg/DFGCFAPhase.cpp6
-rw-r--r--Source/JavaScriptCore/dfg/DFGCFGSimplificationPhase.cpp12
-rw-r--r--Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp227
-rw-r--r--Source/JavaScriptCore/dfg/DFGGPRInfo.h3
-rw-r--r--Source/JavaScriptCore/dfg/DFGJITCompiler.cpp9
-rw-r--r--Source/JavaScriptCore/dfg/DFGJITCompiler.h96
-rw-r--r--Source/JavaScriptCore/dfg/DFGOperations.cpp28
-rw-r--r--Source/JavaScriptCore/dfg/DFGRepatch.cpp81
-rw-r--r--Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h9
-rw-r--r--Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp44
-rw-r--r--Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp32
-rw-r--r--Source/JavaScriptCore/dfg/DFGThunks.cpp212
-rw-r--r--Source/JavaScriptCore/dfg/DFGThunks.h8
-rw-r--r--Source/JavaScriptCore/dfg/DFGVariableEventStream.cpp4
-rw-r--r--Source/JavaScriptCore/heap/HeapTimer.cpp32
-rw-r--r--Source/JavaScriptCore/heap/HeapTimer.h6
-rw-r--r--Source/JavaScriptCore/heap/MachineStackMarker.cpp14
-rw-r--r--Source/JavaScriptCore/heap/MachineStackMarker.h4
-rw-r--r--Source/JavaScriptCore/jit/JIT.cpp6
-rw-r--r--Source/JavaScriptCore/jit/JITStubs.cpp26
-rw-r--r--Source/JavaScriptCore/jit/JumpReplacementWatchpoint.cpp56
-rw-r--r--Source/JavaScriptCore/jit/JumpReplacementWatchpoint.h73
-rw-r--r--Source/JavaScriptCore/jsc.cpp58
-rw-r--r--Source/JavaScriptCore/llint/LLIntOfflineAsmConfig.h6
-rw-r--r--Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm4
-rw-r--r--Source/JavaScriptCore/llint/LowLevelInterpreter64.asm4
-rw-r--r--Source/JavaScriptCore/offlineasm/armv7.rb51
-rw-r--r--Source/JavaScriptCore/offlineasm/asm.rb70
-rw-r--r--Source/JavaScriptCore/offlineasm/ast.rb9
-rw-r--r--Source/JavaScriptCore/offlineasm/backends.rb1
-rw-r--r--Source/JavaScriptCore/offlineasm/config.rb76
-rw-r--r--Source/JavaScriptCore/offlineasm/generate_offset_extractor.rb1
-rw-r--r--Source/JavaScriptCore/offlineasm/instructions.rb2
-rw-r--r--Source/JavaScriptCore/offlineasm/offsets.rb1
-rw-r--r--Source/JavaScriptCore/offlineasm/opt.rb1
-rw-r--r--Source/JavaScriptCore/offlineasm/parser.rb25
-rw-r--r--Source/JavaScriptCore/offlineasm/registers.rb2
-rw-r--r--Source/JavaScriptCore/offlineasm/self_hash.rb1
-rw-r--r--Source/JavaScriptCore/offlineasm/settings.rb1
-rw-r--r--Source/JavaScriptCore/offlineasm/transform.rb1
-rw-r--r--Source/JavaScriptCore/offlineasm/x86.rb8
-rw-r--r--Source/JavaScriptCore/runtime/Executable.h24
-rw-r--r--Source/JavaScriptCore/runtime/GCActivityCallbackBlackBerry.cpp19
-rw-r--r--Source/JavaScriptCore/runtime/JSValue.h22
-rw-r--r--Source/JavaScriptCore/wscript5
72 files changed, 1983 insertions, 484 deletions
diff --git a/Source/JavaScriptCore/CMakeLists.txt b/Source/JavaScriptCore/CMakeLists.txt
index 412be293f..4b030ca40 100644
--- a/Source/JavaScriptCore/CMakeLists.txt
+++ b/Source/JavaScriptCore/CMakeLists.txt
@@ -56,6 +56,7 @@ SET(JavaScriptCore_SOURCES
bytecode/PutByIdStatus.cpp
bytecode/ResolveGlobalStatus.cpp
bytecode/SamplingTool.cpp
+ bytecode/StructureStubClearingWatchpoint.cpp
bytecode/StructureStubInfo.cpp
bytecode/Watchpoint.cpp
@@ -143,6 +144,7 @@ SET(JavaScriptCore_SOURCES
jit/JITPropertyAccess.cpp
jit/JITStubRoutine.cpp
jit/JITStubs.cpp
+ jit/JumpReplacementWatchpoint.cpp
jit/ThunkGenerators.cpp
parser/Lexer.cpp
diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog
index f0e93b012..2697bbb8f 100644
--- a/Source/JavaScriptCore/ChangeLog
+++ b/Source/JavaScriptCore/ChangeLog
@@ -1,20 +1,479 @@
-2012-06-13 Patrick Gansterer <paroga@webkit.org>
+2012-07-13 Mark Lam <mark.lam@apple.com>
- [WIN] Remove dependency on pthread from MachineStackMarker
- https://bugs.webkit.org/show_bug.cgi?id=68429
+ OfflineASM Pretty printing and commenting enhancements.
+ https://bugs.webkit.org/show_bug.cgi?id=91281
- Reviewed by NOBODY (OOPS!).
+ Reviewed by Filip Pizlo.
- Implement pthread TLS functionality with native windows functions.
+ Added some minor pretty printing in the OfflineASM.
+ Also added infrastruture for adding multiple types of comments and
+ annotations with the ability to enable/disable them in the generated
+ output as desired.
- * heap/MachineStackMarker.cpp: Use the new functions instead of pthread directly.
- * heap/MachineStackMarker.h:
- * wtf/ThreadSpecific.h:
- (WTF::ThreadSpecificKeyCreate): Added wrapper around pthread_key_create.
- (WTF::ThreadSpecificKeyDelete): Added wrapper around pthread_key_delete.
- (WTF::ThreadSpecificSet): Added wrapper around pthread_setspecific.
- (WTF::ThreadSpecificGet): Added wrapper around pthread_getspecific.
- * wtf/ThreadSpecificWin.cpp:
+ * GNUmakefile.list.am: add new file config.rb.
+ * llint/LLIntOfflineAsmConfig.h:
+ Added OFFLINE_ASM_BEGIN, OFFLINE_ASM_END, and OFFLINE_ASM_LOCAL_LABEL macros.
+ This will allow us to redefine these for other backends later.
+ * llint/LowLevelInterpreter32_64.asm:
+ Add a small example of instruction annotations for now.
+ * llint/LowLevelInterpreter64.asm:
+ Add a small example of instruction annotations for now.
+ * offlineasm/armv7.rb: Added handling of annotations.
+ * offlineasm/asm.rb:
+ Added machinery to dump the new comments and annotations.
+ Also added some indentations to make the output a little prettier.
+ * offlineasm/ast.rb: Added annotation field in class Instruction.
+ * offlineasm/backends.rb:
+ * offlineasm/config.rb: Added.
+ Currently only contains commenting options. This file is meant to be
+ a centralized place for build config values much like config.h for
+ JavaScriptCore.
+ * offlineasm/generate_offset_extractor.rb:
+ * offlineasm/instructions.rb:
+ * offlineasm/offsets.rb:
+ * offlineasm/opt.rb:
+ * offlineasm/parser.rb: Parse and record annotations.
+ * offlineasm/registers.rb:
+ * offlineasm/self_hash.rb:
+ * offlineasm/settings.rb:
+ * offlineasm/transform.rb:
+ * offlineasm/x86.rb: Added handling of annotations.
+
+2012-07-13 Filip Pizlo <fpizlo@apple.com>
+
+ ASSERTION FAILED: use.useKind() != DoubleUse
+ https://bugs.webkit.org/show_bug.cgi?id=91082
+
+ Reviewed by Geoffrey Garen.
+
+ The implementation of Branch() was unwisely relying on register allocation state
+ to decide what speculations to perform. That's never correct.
+
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+
+2012-07-13 Sheriff Bot <webkit.review.bot@gmail.com>
+
+ Unreviewed, rolling out r122640.
+ http://trac.webkit.org/changeset/122640
+ https://bugs.webkit.org/show_bug.cgi?id=91298
+
+ LLInt apparently does not expect to mark these (Requested by
+ olliej on #webkit).
+
+ * bytecode/CodeBlock.cpp:
+ (JSC::CodeBlock::visitStructures):
+ (JSC::CodeBlock::stronglyVisitStrongReferences):
+
+2012-07-13 Oliver Hunt <oliver@apple.com>
+
+ LLInt fails to mark structures stored in the bytecode
+ https://bugs.webkit.org/show_bug.cgi?id=91296
+
+ Reviewed by Geoffrey Garen.
+
+ LLInt stores structures in the bytecode, so we need to visit the appropriate
+ instructions as we would if we were running in the classic interpreter.
+ This requires adding additional checks for the LLInt specific opcodes, and
+ the lint specific variants of operand ordering.
+
+ * bytecode/CodeBlock.cpp:
+ (JSC::CodeBlock::visitStructures):
+ (JSC::CodeBlock::stronglyVisitStrongReferences):
+
+2012-07-13 Yong Li <yoli@rim.com>
+
+ [BlackBerry] Implement GCActivityCallback with platform timer
+ https://bugs.webkit.org/show_bug.cgi?id=90175
+
+ Reviewed by Rob Buis.
+
+ Implement GCActivityCallback and HeapTimer for BlackBerry port.
+
+ * heap/HeapTimer.cpp:
+ (JSC):
+ (JSC::HeapTimer::HeapTimer):
+ (JSC::HeapTimer::~HeapTimer):
+ (JSC::HeapTimer::timerDidFire):
+ (JSC::HeapTimer::synchronize):
+ (JSC::HeapTimer::invalidate):
+ (JSC::HeapTimer::didStartVMShutdown):
+ * heap/HeapTimer.h:
+ (HeapTimer):
+ * runtime/GCActivityCallbackBlackBerry.cpp:
+ (JSC):
+ (JSC::DefaultGCActivityCallback::doWork):
+ (JSC::DefaultGCActivityCallback::didAllocate):
+ (JSC::DefaultGCActivityCallback::willCollect):
+ (JSC::DefaultGCActivityCallback::cancel):
+
+2012-07-13 Patrick Gansterer <paroga@webkit.org>
+
+ [WIN] Fix compilation of DFGRepatch.cpp
+ https://bugs.webkit.org/show_bug.cgi?id=91241
+
+ Reviewed by Geoffrey Garen.
+
+ Use intptr_t instead of uintptr_t when calling CodeLocationCommon::dataLabelPtrAtOffset(int)
+ to fix MSVC "unary minus operator applied to unsigned type, result still unsigned" warning.
+
+ * dfg/DFGRepatch.cpp:
+ (JSC::DFG::dfgResetGetByID):
+ (JSC::DFG::dfgResetPutByID):
+
+2012-07-13 Patrick Gansterer <paroga@webkit.org>
+
+ Fix ARM_TRADITIONAL JIT for COMPILER(MSVC) and COMPILER(RVCT) after r121885
+ https://bugs.webkit.org/show_bug.cgi?id=91238
+
+ Reviewed by Zoltan Herczeg.
+
+ r121885 changed the assembler instruction only for COMPILER(GCC).
+ Use the same instructions for the other compilers too.
+
+ * jit/JITStubs.cpp:
+ (JSC::ctiTrampoline):
+ (JSC::ctiTrampolineEnd):
+ (JSC::ctiVMThrowTrampoline):
+
+2012-07-12 Filip Pizlo <fpizlo@apple.com>
+
+ DFG property access stubs should use structure transition watchpoints
+ https://bugs.webkit.org/show_bug.cgi?id=91135
+
+ Reviewed by Geoffrey Garen.
+
+ This adds a Watchpoint subclass that will clear a structure stub (i.e.
+ a property access stub) when fired. The DFG stub generation code now
+ uses this optimization.
+
+ * CMakeLists.txt:
+ * GNUmakefile.list.am:
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * Target.pri:
+ * bytecode/CodeBlock.cpp:
+ (JSC):
+ (JSC::CodeBlock::finalizeUnconditionally):
+ (JSC::CodeBlock::resetStub):
+ (JSC::CodeBlock::resetStubInternal):
+ * bytecode/CodeBlock.h:
+ (JSC):
+ (CodeBlock):
+ * bytecode/StructureStubClearingWatchpoint.cpp: Added.
+ (JSC):
+ (JSC::StructureStubClearingWatchpoint::~StructureStubClearingWatchpoint):
+ (JSC::StructureStubClearingWatchpoint::push):
+ (JSC::StructureStubClearingWatchpoint::fireInternal):
+ (JSC::WatchpointsOnStructureStubInfo::~WatchpointsOnStructureStubInfo):
+ (JSC::WatchpointsOnStructureStubInfo::addWatchpoint):
+ (JSC::WatchpointsOnStructureStubInfo::ensureReferenceAndAddWatchpoint):
+ * bytecode/StructureStubClearingWatchpoint.h: Added.
+ (JSC):
+ (StructureStubClearingWatchpoint):
+ (JSC::StructureStubClearingWatchpoint::StructureStubClearingWatchpoint):
+ (WatchpointsOnStructureStubInfo):
+ (JSC::WatchpointsOnStructureStubInfo::WatchpointsOnStructureStubInfo):
+ (JSC::WatchpointsOnStructureStubInfo::codeBlock):
+ (JSC::WatchpointsOnStructureStubInfo::stubInfo):
+ * bytecode/StructureStubInfo.h:
+ (JSC::StructureStubInfo::reset):
+ (JSC::StructureStubInfo::addWatchpoint):
+ (StructureStubInfo):
+ * dfg/DFGRepatch.cpp:
+ (JSC::DFG::addStructureTransitionCheck):
+ (DFG):
+ (JSC::DFG::generateProtoChainAccessStub):
+ (JSC::DFG::emitPutTransitionStub):
+ * jit/JumpReplacementWatchpoint.h:
+
+2012-07-12 Filip Pizlo <fpizlo@apple.com>
+
+ DFG CFA may get overzealous in loops that have code that must exit
+ https://bugs.webkit.org/show_bug.cgi?id=91188
+
+ Reviewed by Gavin Barraclough.
+
+ Ensure that if the CFA assumes that an operation must exit, then it will always exit
+ no matter what happens after. That's necessary to preserve soundness.
+
+ Remove a broken fixup done by the DFG simplifier, where it was trying to say that the
+ variable-at-head was the first access in the second block in the merge, if the first
+ block did not read the variable. That's totally wrong, if the first block was in fact
+ doing a phantom read. I removed that fixup and instead hardened the rest of the
+ compiler.
+
+ * dfg/DFGAbstractState.cpp:
+ (JSC::DFG::AbstractState::endBasicBlock):
+ * dfg/DFGBasicBlock.h:
+ (JSC::DFG::BasicBlock::BasicBlock):
+ (BasicBlock):
+ * dfg/DFGCFAPhase.cpp:
+ (JSC::DFG::CFAPhase::performBlockCFA):
+ * dfg/DFGCFGSimplificationPhase.cpp:
+ (JSC::DFG::CFGSimplificationPhase::mergeBlocks):
+ * dfg/DFGConstantFoldingPhase.cpp:
+ (JSC::DFG::ConstantFoldingPhase::ConstantFoldingPhase):
+ (JSC::DFG::ConstantFoldingPhase::run):
+ (ConstantFoldingPhase):
+ (JSC::DFG::ConstantFoldingPhase::foldConstants):
+ (JSC::DFG::ConstantFoldingPhase::paintUnreachableCode):
+ * dfg/DFGVariableEventStream.cpp:
+ (JSC::DFG::VariableEventStream::reconstruct):
+
+2012-07-12 Allan Sandfeld Jensen <allan.jensen@nokia.com>
+
+ [Qt] Implement MemoryUsageSupport
+ https://bugs.webkit.org/show_bug.cgi?id=91094
+
+ Reviewed by Adam Barth.
+
+ Compile in MemoryStatistics so we can make use of the interface.
+
+ * Target.pri:
+
+2012-07-12 Csaba Osztrogonác <ossy@webkit.org>
+
+ Remove dead code after r122392.
+ https://bugs.webkit.org/show_bug.cgi?id=91049
+
+ Reviewed by Filip Pizlo.
+
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::emitCall):
+
+2012-07-11 Adenilson Cavalcanti <cavalcantii@gmail.com>
+
+ Build fix + remove dead code
+ https://bugs.webkit.org/show_bug.cgi?id=91039
+
+ Reviewed by Filip Pizlo.
+
+ An unused variable was breaking compilation (thanks to warnings being treated as errors).
+
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::emitCall):
+
+2012-07-11 Mark Rowe <mrowe@apple.com>
+
+ <http://webkit.org/b/91024> Build against the latest SDK when targeting older OS X versions.
+
+ Reviewed by Dan Bernstein.
+
+ The deployment target is already set to the version that we're targeting, and it's that setting
+ which determines which functionality from the SDK is available to us.
+
+ * Configurations/Base.xcconfig:
+
+2012-07-11 Filip Pizlo <fpizlo@apple.com>
+
+ DFG should have fast virtual calls
+ https://bugs.webkit.org/show_bug.cgi?id=90924
+
+ Reviewed by Gavin Barraclough.
+
+ Implements virtual call support in the style of the old JIT, with the
+ caveat that we still use the same slow path for both InternalFunction
+ calls and JSFunction calls. Also rationalized the way that our
+ CodeOrigin indices tie into exception checks (previously it was a
+ strange one-to-one mapping with fairly limited assertions; now it's a
+ one-to-many mapping for CodeOrigins to exception checks, respectively).
+ I also took the opportunity to clean up
+ CallLinkInfo::callReturnLocation, which previously was either a Call or
+ a NearCall. Now it's just a NearCall. As well, exceptions during slow
+ path call resolution are now handled by returning an exception throwing
+ thunk rather than returning null. And finally, I made a few things
+ public that were previously private-with-lots-of-friends, because I
+ truly despise the thought of listing each thunk generating function as
+ a friend of JSValue and friends.
+
+ * bytecode/CallLinkInfo.cpp:
+ (JSC::CallLinkInfo::unlink):
+ * bytecode/CallLinkInfo.h:
+ (CallLinkInfo):
+ * bytecode/CodeOrigin.h:
+ (JSC::CodeOrigin::CodeOrigin):
+ (JSC::CodeOrigin::isSet):
+ * dfg/DFGAssemblyHelpers.h:
+ (JSC::DFG::AssemblyHelpers::AssemblyHelpers):
+ * dfg/DFGCCallHelpers.h:
+ (JSC::DFG::CCallHelpers::CCallHelpers):
+ * dfg/DFGGPRInfo.h:
+ (GPRInfo):
+ * dfg/DFGJITCompiler.cpp:
+ (JSC::DFG::JITCompiler::link):
+ (JSC::DFG::JITCompiler::compileFunction):
+ * dfg/DFGJITCompiler.h:
+ (JSC::DFG::CallBeginToken::CallBeginToken):
+ (JSC::DFG::CallBeginToken::~CallBeginToken):
+ (CallBeginToken):
+ (JSC::DFG::CallBeginToken::set):
+ (JSC::DFG::CallBeginToken::registerWithExceptionCheck):
+ (JSC::DFG::CallBeginToken::codeOrigin):
+ (JSC::DFG::CallExceptionRecord::CallExceptionRecord):
+ (CallExceptionRecord):
+ (JSC::DFG::JITCompiler::currentCodeOriginIndex):
+ (JITCompiler):
+ (JSC::DFG::JITCompiler::beginCall):
+ (JSC::DFG::JITCompiler::notifyCall):
+ (JSC::DFG::JITCompiler::prepareForExceptionCheck):
+ (JSC::DFG::JITCompiler::addExceptionCheck):
+ (JSC::DFG::JITCompiler::addFastExceptionCheck):
+ * dfg/DFGOperations.cpp:
+ * dfg/DFGRepatch.cpp:
+ (JSC::DFG::dfgLinkFor):
+ * dfg/DFGSpeculativeJIT.h:
+ (JSC::DFG::SpeculativeJIT::appendCallWithExceptionCheck):
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::emitCall):
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::emitCall):
+ * dfg/DFGThunks.cpp:
+ (JSC::DFG::emitPointerValidation):
+ (DFG):
+ (JSC::DFG::throwExceptionFromCallSlowPathGenerator):
+ (JSC::DFG::slowPathFor):
+ (JSC::DFG::linkForThunkGenerator):
+ (JSC::DFG::linkCallThunkGenerator):
+ (JSC::DFG::linkConstructThunkGenerator):
+ (JSC::DFG::virtualForThunkGenerator):
+ (JSC::DFG::virtualCallThunkGenerator):
+ (JSC::DFG::virtualConstructThunkGenerator):
+ * dfg/DFGThunks.h:
+ (DFG):
+ * jit/JIT.cpp:
+ (JSC::JIT::privateCompile):
+ (JSC::JIT::linkFor):
+ * runtime/Executable.h:
+ (ExecutableBase):
+ (JSC::ExecutableBase::offsetOfJITCodeFor):
+ (JSC::ExecutableBase::offsetOfNumParametersFor):
+ * runtime/JSValue.h:
+ (JSValue):
+
+2012-07-11 Filip Pizlo <fpizlo@apple.com>
+
+ Accidentally used the wrong license (3-clause instead of 2-clause) in some
+ files I just committed.
+
+ Rubber stamped by Oliver Hunt.
+
+ * bytecode/Watchpoint.cpp:
+ * bytecode/Watchpoint.h:
+ * jit/JumpReplacementWatchpoint.cpp:
+ * jit/JumpReplacementWatchpoint.h:
+
+2012-07-11 Filip Pizlo <fpizlo@apple.com>
+
+ Watchpoints and jump replacement should be decoupled
+ https://bugs.webkit.org/show_bug.cgi?id=91016
+
+ Reviewed by Oliver Hunt.
+
+ * CMakeLists.txt:
+ * GNUmakefile.list.am:
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * Target.pri:
+ * assembler/AbstractMacroAssembler.h:
+ (JSC):
+ (Label):
+ * bytecode/CodeBlock.h:
+ (JSC::CodeBlock::appendWatchpoint):
+ (JSC::CodeBlock::watchpoint):
+ (DFGData):
+ * bytecode/Watchpoint.cpp:
+ (JSC):
+ * bytecode/Watchpoint.h:
+ (JSC::Watchpoint::Watchpoint):
+ (Watchpoint):
+ (JSC::Watchpoint::fire):
+ * dfg/DFGSpeculativeJIT.h:
+ (JSC::DFG::SpeculativeJIT::speculationWatchpoint):
+ * jit/JumpReplacementWatchpoint.cpp: Added.
+ (JSC):
+ (JSC::JumpReplacementWatchpoint::correctLabels):
+ (JSC::JumpReplacementWatchpoint::fireInternal):
+ * jit/JumpReplacementWatchpoint.h: Added.
+ (JSC):
+ (JumpReplacementWatchpoint):
+ (JSC::JumpReplacementWatchpoint::JumpReplacementWatchpoint):
+ (JSC::JumpReplacementWatchpoint::setDestination):
+
+2012-07-11 Kevin Ollivier <kevino@theolliviers.com>
+
+ [wx] Unreviewed build fix. Don't try to build udis86_itab.c since it's included by
+ another file.
+
+ * wscript:
+
+2012-07-11 Chao-ying Fu <fu@mips.com>
+
+ Add MIPS convertibleLoadPtr and other functions
+ https://bugs.webkit.org/show_bug.cgi?id=90714
+
+ Reviewed by Oliver Hunt.
+
+ * assembler/MIPSAssembler.h:
+ (JSC::MIPSAssembler::labelIgnoringWatchpoints):
+ (MIPSAssembler):
+ (JSC::MIPSAssembler::replaceWithLoad):
+ (JSC::MIPSAssembler::replaceWithAddressComputation):
+ * assembler/MacroAssemblerMIPS.h:
+ (JSC::MacroAssemblerMIPS::convertibleLoadPtr):
+ (MacroAssemblerMIPS):
+
+2012-07-11 Anders Carlsson <andersca@apple.com>
+
+ Add -Wtautological-compare and -Wsign-compare warning flags
+ https://bugs.webkit.org/show_bug.cgi?id=90994
+
+ Reviewed by Mark Rowe.
+
+ * Configurations/Base.xcconfig:
+
+2012-07-11 Benjamin Poulain <bpoulain@apple.com>
+
+ Simplify the copying of JSC ARMv7's LinkRecord
+ https://bugs.webkit.org/show_bug.cgi?id=90930
+
+ Reviewed by Filip Pizlo.
+
+ The class LinkRecord is used by value everywhere in ARMv7Assembler. The compiler uses
+ memmove() to move the objects.
+
+ The problem is memmove() is overkill for this object, moving the value can be done with
+ 3 load-store. This patch adds an operator= to the class doing more efficient copying.
+ This reduces the link time by 19%.
+
+ * assembler/ARMv7Assembler.h:
+ (JSC::ARMv7Assembler::LinkRecord::LinkRecord):
+ (JSC::ARMv7Assembler::LinkRecord::operator=):
+ (JSC::ARMv7Assembler::LinkRecord::from):
+ (JSC::ARMv7Assembler::LinkRecord::setFrom):
+ (JSC::ARMv7Assembler::LinkRecord::to):
+ (JSC::ARMv7Assembler::LinkRecord::type):
+ (JSC::ARMv7Assembler::LinkRecord::linkType):
+ (JSC::ARMv7Assembler::LinkRecord::setLinkType):
+ (JSC::ARMv7Assembler::LinkRecord::condition):
+
+2012-07-11 Andy Wingo <wingo@igalia.com>
+
+ jsc: Parse options before creating global data
+ https://bugs.webkit.org/show_bug.cgi?id=90975
+
+ Reviewed by Filip Pizlo.
+
+ This patch moves the options parsing in "jsc" before the creation
+ of the JSGlobalData, so that --useJIT=no has a chance to take
+ effect.
+
+ * jsc.cpp:
+ (CommandLine::parseArguments): Refactor to be a class, and take
+ argc and argv as constructor arguments.
+ (jscmain): Move arg parsing before JSGlobalData creation.
2012-07-10 Filip Pizlo <fpizlo@apple.com>
diff --git a/Source/JavaScriptCore/Configurations/Base.xcconfig b/Source/JavaScriptCore/Configurations/Base.xcconfig
index 96e9a356f..47c8f7382 100644
--- a/Source/JavaScriptCore/Configurations/Base.xcconfig
+++ b/Source/JavaScriptCore/Configurations/Base.xcconfig
@@ -24,7 +24,7 @@
#include "CompilerVersion.xcconfig"
COMPILER_SPECIFIC_WARNING_CFLAGS = $(COMPILER_SPECIFIC_WARNING_CFLAGS_$(TARGET_GCC_VERSION));
-COMPILER_SPECIFIC_WARNING_CFLAGS_LLVM_COMPILER = -Wglobal-constructors -Wexit-time-destructors;
+COMPILER_SPECIFIC_WARNING_CFLAGS_LLVM_COMPILER = -Wexit-time-destructors -Wglobal-constructors -Wtautological-compare;
CLANG_WARN_CXX0X_EXTENSIONS = NO;
DEBUG_INFORMATION_FORMAT = dwarf-with-dsym;
@@ -54,6 +54,7 @@ GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO;
GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES;
+GCC_WARN_SIGN_COMPARE = YES;
LINKER_DISPLAYS_MANGLED_NAMES = YES;
PREBINDING = NO;
VALID_ARCHS = $(VALID_ARCHS_$(REAL_PLATFORM_NAME));
@@ -126,18 +127,15 @@ DEAD_CODE_STRIPPING = $(DEAD_CODE_STRIPPING_$(CURRENT_VARIANT));
SECTORDER_FLAGS = -Wl,-order_file,JavaScriptCore.order;
-// If the target Mac OS X version does not match the current Mac OS X version then we'll want to build using the target version's SDK.
-SDKROOT = $(SDKROOT_$(MAC_OS_X_VERSION_MAJOR)_$(TARGET_MAC_OS_X_VERSION_MAJOR));
-SDKROOT_1060_1050 = macosx10.5;
-SDKROOT_1070_1050 = macosx10.5;
-SDKROOT_1080_1050 = macosx10.5;
-SDKROOT_1090_1050 = macosx10.5;
-SDKROOT_1070_1060 = macosx10.6;
-SDKROOT_1080_1060 = macosx10.6;
-SDKROOT_1090_1060 = macosx10.6;
-SDKROOT_1080_1070 = macosx10.7;
-SDKROOT_1090_1070 = macosx10.7;
-SDKROOT_1090_1080 = macosx10.8;
+TARGETING_SAME_OS_X_VERSION = $(TARGETING_SAME_OS_X_VERSION_$(MAC_OS_X_VERSION_MAJOR)_$(TARGET_MAC_OS_X_VERSION_MAJOR));
+TARGETING_SAME_OS_X_VERSION_1060_1060 = YES;
+TARGETING_SAME_OS_X_VERSION_1070_1070 = YES;
+TARGETING_SAME_OS_X_VERSION_1080_1080 = YES;
+TARGETING_SAME_OS_X_VERSION_1090_1090 = YES;
+
+// Don't build against an SDK unless we're targeting an older OS version.
+SDKROOT = $(SDKROOT_TARGETING_SAME_OS_X_VERSION_$(TARGETING_SAME_OS_X_VERSION));
+SDKROOT_TARGETING_SAME_OS_X_VERSION_ = macosx;
// HAVE_DTRACE is disabled on Leopard due to <rdar://problem/5628149>
diff --git a/Source/JavaScriptCore/GNUmakefile.list.am b/Source/JavaScriptCore/GNUmakefile.list.am
index 7e6056e97..751d5657a 100644
--- a/Source/JavaScriptCore/GNUmakefile.list.am
+++ b/Source/JavaScriptCore/GNUmakefile.list.am
@@ -134,6 +134,8 @@ javascriptcore_sources += \
Source/JavaScriptCore/bytecode/StructureSet.h \
Source/JavaScriptCore/bytecode/StructureStubInfo.cpp \
Source/JavaScriptCore/bytecode/StructureStubInfo.h \
+ Source/JavaScriptCore/bytecode/StructureStubClearingWatchpoint.cpp \
+ Source/JavaScriptCore/bytecode/StructureStubClearingWatchpoint.h \
Source/JavaScriptCore/bytecode/ValueProfile.h \
Source/JavaScriptCore/bytecode/ValueRecovery.h \
Source/JavaScriptCore/bytecode/VirtualRegister.h \
@@ -383,6 +385,8 @@ javascriptcore_sources += \
Source/JavaScriptCore/jit/JITStubs.h \
Source/JavaScriptCore/jit/JITWriteBarrier.h \
Source/JavaScriptCore/jit/JSInterfaceJIT.h \
+ Source/JavaScriptCore/jit/JumpReplacementWatchpoint.cpp \
+ Source/JavaScriptCore/jit/JumpReplacementWatchpoint.h \
Source/JavaScriptCore/jit/SpecializedThunkJIT.h \
Source/JavaScriptCore/jit/ThunkGenerators.cpp \
Source/JavaScriptCore/jit/ThunkGenerators.h \
@@ -680,6 +684,7 @@ offlineasm_nosources += \
Source/JavaScriptCore/offlineasm/asm.rb \
Source/JavaScriptCore/offlineasm/ast.rb \
Source/JavaScriptCore/offlineasm/backends.rb \
+ Source/JavaScriptCore/offlineasm/config.rb \
Source/JavaScriptCore/offlineasm/generate_offset_extractor.rb \
Source/JavaScriptCore/offlineasm/instructions.rb \
Source/JavaScriptCore/offlineasm/offsets.rb \
diff --git a/Source/JavaScriptCore/JavaScriptCore.pri b/Source/JavaScriptCore/JavaScriptCore.pri
index f6580c51f..380bbaf1b 100644
--- a/Source/JavaScriptCore/JavaScriptCore.pri
+++ b/Source/JavaScriptCore/JavaScriptCore.pri
@@ -34,6 +34,12 @@ INCLUDEPATH += \
win32-* {
LIBS += -lwinmm
+
+ win32-g++* {
+ LIBS += -lpthreadGC2
+ } else:win32-msvc* {
+ LIBS += -lpthreadVC2
+ }
}
wince* {
diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def
index c50013ac1..dfa38aafb 100755
--- a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def
+++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def
@@ -72,6 +72,9 @@ EXPORTS
?append@StringBuilder@WTF@@QAEXPB_WI@Z
?ascii@UString@JSC@@QBE?AVCString@WTF@@XZ
?attach@Debugger@JSC@@QAEXPAVJSGlobalObject@2@@Z
+ ?base64Decode@WTF@@YA_NABVString@1@AAV?$Vector@D$0A@@1@W4Base64DecodePolicy@1@@Z
+ ?base64Encode@WTF@@YA?AVString@1@PBDIW4Base64EncodePolicy@1@@Z
+ ?base64Encode@WTF@@YAXPBDIAAV?$Vector@D$0A@@1@W4Base64EncodePolicy@1@@Z
?broadcast@ThreadCondition@WTF@@QAEXXZ
?bufferLengthForStringDecimal@DecimalNumber@WTF@@QBEIXZ
?bufferLengthForStringExponential@DecimalNumber@WTF@@QBEIXZ
diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj
index 92749eb75..2efa84059 100644
--- a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj
+++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj
@@ -1682,6 +1682,14 @@
>
</File>
<File
+ RelativePath="..\..\bytecode\StructureStubClearingWatchpoint.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\bytecode\StructureStubClearingWatchpoint.h"
+ >
+ </File>
+ <File
RelativePath="..\..\bytecode\StructureStubInfo.cpp"
>
</File>
@@ -1942,6 +1950,14 @@
>
</File>
<File
+ RelativePath="..\..\jit\JumpReplacementWatchpoint.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\jit\JumpReplacementWatchpoint.h"
+ >
+ </File>
+ <File
RelativePath="..\..\jit\JSInterfaceJIT.h"
>
</File>
diff --git a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj b/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
index 188c1ffe7..f9548f184 100644
--- a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
+++ b/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
@@ -146,6 +146,10 @@
0F766D2F15A8DCE0008F363E /* GCAwareJITStubRoutine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F766D2D15A8DCDD008F363E /* GCAwareJITStubRoutine.cpp */; };
0F766D3015A8DCE2008F363E /* GCAwareJITStubRoutine.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F766D2E15A8DCDD008F363E /* GCAwareJITStubRoutine.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F766D3115AA8112008F363E /* JITStubRoutine.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F766D1C15A5028D008F363E /* JITStubRoutine.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 0F766D3415AE2538008F363E /* JumpReplacementWatchpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F766D3215AE2535008F363E /* JumpReplacementWatchpoint.cpp */; };
+ 0F766D3515AE253B008F363E /* JumpReplacementWatchpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F766D3315AE2535008F363E /* JumpReplacementWatchpoint.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 0F766D3815AE4A1C008F363E /* StructureStubClearingWatchpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F766D3615AE4A1A008F363E /* StructureStubClearingWatchpoint.cpp */; };
+ 0F766D3915AE4A1F008F363E /* StructureStubClearingWatchpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F766D3715AE4A1A008F363E /* StructureStubClearingWatchpoint.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F7700921402FF3C0078EB39 /* SamplingCounter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F7700911402FF280078EB39 /* SamplingCounter.cpp */; };
0F7B294A14C3CD29007C3DB1 /* DFGCCallHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F7B294814C3CD23007C3DB1 /* DFGCCallHelpers.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F7B294B14C3CD2F007C3DB1 /* DFGCapabilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD82E1F14172C2F00179C94 /* DFGCapabilities.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -887,6 +891,10 @@
0F766D2A15A8CC34008F363E /* JITStubRoutineSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITStubRoutineSet.h; sourceTree = "<group>"; };
0F766D2D15A8DCDD008F363E /* GCAwareJITStubRoutine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GCAwareJITStubRoutine.cpp; sourceTree = "<group>"; };
0F766D2E15A8DCDD008F363E /* GCAwareJITStubRoutine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCAwareJITStubRoutine.h; sourceTree = "<group>"; };
+ 0F766D3215AE2535008F363E /* JumpReplacementWatchpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JumpReplacementWatchpoint.cpp; sourceTree = "<group>"; };
+ 0F766D3315AE2535008F363E /* JumpReplacementWatchpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JumpReplacementWatchpoint.h; sourceTree = "<group>"; };
+ 0F766D3615AE4A1A008F363E /* StructureStubClearingWatchpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StructureStubClearingWatchpoint.cpp; sourceTree = "<group>"; };
+ 0F766D3715AE4A1A008F363E /* StructureStubClearingWatchpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StructureStubClearingWatchpoint.h; sourceTree = "<group>"; };
0F77008E1402FDD60078EB39 /* SamplingCounter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SamplingCounter.h; sourceTree = "<group>"; };
0F7700911402FF280078EB39 /* SamplingCounter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SamplingCounter.cpp; sourceTree = "<group>"; };
0F7B294814C3CD23007C3DB1 /* DFGCCallHelpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGCCallHelpers.h; path = dfg/DFGCCallHelpers.h; sourceTree = "<group>"; };
@@ -1731,6 +1739,8 @@
14A6581A0F4E36F4000150FD /* JITStubs.h */,
A76F54A213B28AAB00EF2BCE /* JITWriteBarrier.h */,
A76C51741182748D00715B05 /* JSInterfaceJIT.h */,
+ 0F766D3215AE2535008F363E /* JumpReplacementWatchpoint.cpp */,
+ 0F766D3315AE2535008F363E /* JumpReplacementWatchpoint.h */,
A7386551118697B400540279 /* SpecializedThunkJIT.h */,
A7386552118697B400540279 /* ThunkGenerators.cpp */,
A7386553118697B400540279 /* ThunkGenerators.h */,
@@ -2433,6 +2443,8 @@
0FD82E4F141DAEA100179C94 /* SpeculatedType.h */,
1429D8830ED21C3D00B89619 /* SamplingTool.cpp */,
1429D8840ED21C3D00B89619 /* SamplingTool.h */,
+ 0F766D3615AE4A1A008F363E /* StructureStubClearingWatchpoint.cpp */,
+ 0F766D3715AE4A1A008F363E /* StructureStubClearingWatchpoint.h */,
BCCF0D0B0EF0B8A500413C8F /* StructureStubInfo.cpp */,
BCCF0D070EF0AAB900413C8F /* StructureStubInfo.h */,
0F963B3613FC6FDE0002D9B2 /* ValueProfile.h */,
@@ -2836,6 +2848,8 @@
0F766D2C15A8CC3A008F363E /* JITStubRoutineSet.h in Headers */,
0F766D3015A8DCE2008F363E /* GCAwareJITStubRoutine.h in Headers */,
0F766D3115AA8112008F363E /* JITStubRoutine.h in Headers */,
+ 0F766D3515AE253B008F363E /* JumpReplacementWatchpoint.h in Headers */,
+ 0F766D3915AE4A1F008F363E /* StructureStubClearingWatchpoint.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -3431,6 +3445,8 @@
0F766D2815A8CC1E008F363E /* JITStubRoutine.cpp in Sources */,
0F766D2B15A8CC38008F363E /* JITStubRoutineSet.cpp in Sources */,
0F766D2F15A8DCE0008F363E /* GCAwareJITStubRoutine.cpp in Sources */,
+ 0F766D3415AE2538008F363E /* JumpReplacementWatchpoint.cpp in Sources */,
+ 0F766D3815AE4A1C008F363E /* StructureStubClearingWatchpoint.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
diff --git a/Source/JavaScriptCore/Target.pri b/Source/JavaScriptCore/Target.pri
index b019e417e..035656f0c 100644
--- a/Source/JavaScriptCore/Target.pri
+++ b/Source/JavaScriptCore/Target.pri
@@ -67,6 +67,7 @@ SOURCES += \
bytecode/ResolveGlobalStatus.cpp \
bytecode/SamplingTool.cpp \
bytecode/SpeculatedType.cpp \
+ bytecode/StructureStubClearingWatchpoint.cpp \
bytecode/StructureStubInfo.cpp \
bytecode/Watchpoint.cpp \
bytecompiler/BytecodeGenerator.cpp \
@@ -151,6 +152,7 @@ SOURCES += \
jit/JITPropertyAccess32_64.cpp \
jit/JITStubRoutine.cpp \
jit/JITStubs.cpp \
+ jit/JumpReplacementWatchpoint.cpp \
jit/ThunkGenerators.cpp \
parser/Lexer.cpp \
parser/Nodes.cpp \
@@ -217,6 +219,7 @@ SOURCES += \
runtime/LiteralParser.cpp \
runtime/Lookup.cpp \
runtime/MathObject.cpp \
+ runtime/MemoryStatistics.cpp \
runtime/NameConstructor.cpp \
runtime/NameInstance.cpp \
runtime/NamePrototype.cpp \
diff --git a/Source/JavaScriptCore/assembler/ARMv7Assembler.h b/Source/JavaScriptCore/assembler/ARMv7Assembler.h
index eef0ba8a7..96c4f096c 100644
--- a/Source/JavaScriptCore/assembler/ARMv7Assembler.h
+++ b/Source/JavaScriptCore/assembler/ARMv7Assembler.h
@@ -462,28 +462,42 @@ public:
class LinkRecord {
public:
LinkRecord(intptr_t from, intptr_t to, JumpType type, Condition condition)
- : m_from(from)
- , m_to(to)
- , m_type(type)
- , m_linkType(LinkInvalid)
- , m_condition(condition)
{
+ data.realTypes.m_from = from;
+ data.realTypes.m_to = to;
+ data.realTypes.m_type = type;
+ data.realTypes.m_linkType = LinkInvalid;
+ data.realTypes.m_condition = condition;
}
- intptr_t from() const { return m_from; }
- void setFrom(intptr_t from) { m_from = from; }
- intptr_t to() const { return m_to; }
- JumpType type() const { return m_type; }
- JumpLinkType linkType() const { return m_linkType; }
- void setLinkType(JumpLinkType linkType) { ASSERT(m_linkType == LinkInvalid); m_linkType = linkType; }
- Condition condition() const { return m_condition; }
+ void operator=(const LinkRecord& other)
+ {
+ data.copyTypes.content[0] = other.data.copyTypes.content[0];
+ data.copyTypes.content[1] = other.data.copyTypes.content[1];
+ data.copyTypes.content[2] = other.data.copyTypes.content[2];
+ }
+ intptr_t from() const { return data.realTypes.m_from; }
+ void setFrom(intptr_t from) { data.realTypes.m_from = from; }
+ intptr_t to() const { return data.realTypes.m_to; }
+ JumpType type() const { return data.realTypes.m_type; }
+ JumpLinkType linkType() const { return data.realTypes.m_linkType; }
+ void setLinkType(JumpLinkType linkType) { ASSERT(data.realTypes.m_linkType == LinkInvalid); data.realTypes.m_linkType = linkType; }
+ Condition condition() const { return data.realTypes.m_condition; }
private:
- intptr_t m_from : 31;
- intptr_t m_to : 31;
- JumpType m_type : 8;
- JumpLinkType m_linkType : 8;
- Condition m_condition : 16;
+ union {
+ struct RealTypes {
+ intptr_t m_from : 31;
+ intptr_t m_to : 31;
+ JumpType m_type : 8;
+ JumpLinkType m_linkType : 8;
+ Condition m_condition : 16;
+ } realTypes;
+ struct CopyTypes {
+ uint32_t content[3];
+ } copyTypes;
+ COMPILE_ASSERT(sizeof(RealTypes) == sizeof(CopyTypes), LinkRecordCopyStructSizeEqualsRealStruct);
+ } data;
};
-
+
ARMv7Assembler()
: m_indexOfLastWatchpoint(INT_MIN)
, m_indexOfTailOfLastWatchpoint(INT_MIN)
diff --git a/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h b/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h
index a24f7573a..ef1808ffb 100644
--- a/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h
+++ b/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h
@@ -46,6 +46,7 @@
namespace JSC {
+class JumpReplacementWatchpoint;
class LinkBuffer;
class RepatchBuffer;
class Watchpoint;
@@ -277,6 +278,7 @@ public:
friend class AbstractMacroAssembler;
friend class DFG::CorrectableJumpPoint;
friend class Jump;
+ friend class JumpReplacementWatchpoint;
friend class MacroAssemblerCodeRef;
friend class LinkBuffer;
friend class Watchpoint;
diff --git a/Source/JavaScriptCore/assembler/MIPSAssembler.h b/Source/JavaScriptCore/assembler/MIPSAssembler.h
index 7212a182c..65307d950 100644
--- a/Source/JavaScriptCore/assembler/MIPSAssembler.h
+++ b/Source/JavaScriptCore/assembler/MIPSAssembler.h
@@ -616,6 +616,11 @@ public:
// General helpers
+ AssemblerLabel labelIgnoringWatchpoints()
+ {
+ return m_buffer.label();
+ }
+
AssemblerLabel label()
{
return m_buffer.label();
@@ -809,6 +814,28 @@ public:
#endif
}
+ static void replaceWithLoad(void* instructionStart)
+ {
+ MIPSWord* insn = reinterpret_cast<MIPSWord*>(instructionStart);
+ ASSERT((*insn & 0xffe00000) == 0x3c000000); // lui
+ insn++;
+ ASSERT((*insn & 0xfc0007ff) == 0x00000021); // addu
+ insn++;
+ *insn = 0x8c000000 | ((*insn) & 0x3ffffff); // lw
+ cacheFlush(insn, 4);
+ }
+
+ static void replaceWithAddressComputation(void* instructionStart)
+ {
+ MIPSWord* insn = reinterpret_cast<MIPSWord*>(instructionStart);
+ ASSERT((*insn & 0xffe00000) == 0x3c000000); // lui
+ insn++;
+ ASSERT((*insn & 0xfc0007ff) == 0x00000021); // addu
+ insn++;
+ *insn = 0x24000000 | ((*insn) & 0x3ffffff); // addiu
+ cacheFlush(insn, 4);
+ }
+
private:
/* Update each jump in the buffer of newBase. */
void relocateJumps(void* oldBase, void* newBase)
diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h b/Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h
index 5adcf9b4e..bc280acec 100644
--- a/Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h
+++ b/Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h
@@ -496,6 +496,20 @@ public:
ASSERT_NOT_REACHED();
}
+ ConvertibleLoadLabel convertibleLoadPtr(Address address, RegisterID dest)
+ {
+ ConvertibleLoadLabel result(this);
+ /*
+ lui addrTemp, (offset + 0x8000) >> 16
+ addu addrTemp, addrTemp, base
+ lw dest, (offset & 0xffff)(addrTemp)
+ */
+ m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
+ m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+ m_assembler.lw(dest, addrTempRegister, address.offset);
+ return result;
+ }
+
// Memory access operations:
//
// Loads are of the form load(address, destination) and stores of the form
diff --git a/Source/JavaScriptCore/bytecode/CallLinkInfo.cpp b/Source/JavaScriptCore/bytecode/CallLinkInfo.cpp
index 4c108ecf1..4933a494c 100644
--- a/Source/JavaScriptCore/bytecode/CallLinkInfo.cpp
+++ b/Source/JavaScriptCore/bytecode/CallLinkInfo.cpp
@@ -27,6 +27,7 @@
#include "CallLinkInfo.h"
#include "DFGOperations.h"
+#include "DFGThunks.h"
#include "RepatchBuffer.h"
#if ENABLE(JIT)
@@ -38,12 +39,12 @@ void CallLinkInfo::unlink(JSGlobalData& globalData, RepatchBuffer& repatchBuffer
if (isDFG) {
#if ENABLE(DFG_JIT)
- repatchBuffer.relink(CodeLocationCall(callReturnLocation), callType == Construct ? DFG::operationLinkConstruct : DFG::operationLinkCall);
+ repatchBuffer.relink(callReturnLocation, (callType == Construct ? globalData.getCTIStub(DFG::linkConstructThunkGenerator) : globalData.getCTIStub(DFG::linkCallThunkGenerator)).code());
#else
ASSERT_NOT_REACHED();
#endif
} else
- repatchBuffer.relink(CodeLocationNearCall(callReturnLocation), callType == Construct ? globalData.jitStubs->ctiVirtualConstructLink() : globalData.jitStubs->ctiVirtualCallLink());
+ repatchBuffer.relink(callReturnLocation, callType == Construct ? globalData.jitStubs->ctiVirtualConstructLink() : globalData.jitStubs->ctiVirtualCallLink());
hasSeenShouldRepatch = false;
callee.clear();
diff --git a/Source/JavaScriptCore/bytecode/CallLinkInfo.h b/Source/JavaScriptCore/bytecode/CallLinkInfo.h
index 44d50a971..4a78e5d02 100644
--- a/Source/JavaScriptCore/bytecode/CallLinkInfo.h
+++ b/Source/JavaScriptCore/bytecode/CallLinkInfo.h
@@ -65,7 +65,7 @@ struct CallLinkInfo : public BasicRawSentinelNode<CallLinkInfo> {
remove();
}
- CodeLocationLabel callReturnLocation; // it's a near call in the old JIT, or a normal call in DFG
+ CodeLocationNearCall callReturnLocation;
CodeLocationDataLabelPtr hotPathBegin;
CodeLocationNearCall hotPathOther;
JITWriteBarrier<JSFunction> callee;
diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.cpp b/Source/JavaScriptCore/bytecode/CodeBlock.cpp
index 48d0fe728..d417a5fbd 100644
--- a/Source/JavaScriptCore/bytecode/CodeBlock.cpp
+++ b/Source/JavaScriptCore/bytecode/CodeBlock.cpp
@@ -2026,16 +2026,16 @@ void CodeBlock::visitWeakReferences(SlotVisitor& visitor)
performTracingFixpointIteration(visitor);
}
-void CodeBlock::finalizeUnconditionally()
-{
#if ENABLE(JIT)
#if ENABLE(JIT_VERBOSE_OSR)
- static const bool verboseUnlinking = true;
+static const bool verboseUnlinking = true;
#else
- static const bool verboseUnlinking = false;
+static const bool verboseUnlinking = false;
#endif
#endif // ENABLE(JIT)
+void CodeBlock::finalizeUnconditionally()
+{
#if ENABLE(LLINT)
Interpreter* interpreter = m_globalData->interpreter;
// interpreter->classicEnabled() returns true if the old C++ interpreter is enabled. If that's enabled
@@ -2141,28 +2141,10 @@ void CodeBlock::finalizeUnconditionally()
for (size_t size = m_structureStubInfos.size(), i = 0; i < size; ++i) {
StructureStubInfo& stubInfo = m_structureStubInfos[i];
- AccessType accessType = static_cast<AccessType>(stubInfo.accessType);
-
if (stubInfo.visitWeakReferences())
continue;
- if (verboseUnlinking)
- dataLog("Clearing structure cache (kind %d) in %p.\n", stubInfo.accessType, this);
-
- if (isGetByIdAccess(accessType)) {
- if (getJITCode().jitType() == JITCode::DFGJIT)
- DFG::dfgResetGetByID(repatchBuffer, stubInfo);
- else
- JIT::resetPatchGetById(repatchBuffer, &stubInfo);
- } else {
- ASSERT(isPutByIdAccess(accessType));
- if (getJITCode().jitType() == JITCode::DFGJIT)
- DFG::dfgResetPutByID(repatchBuffer, stubInfo);
- else
- JIT::resetPatchPutById(repatchBuffer, &stubInfo);
- }
-
- stubInfo.reset();
+ resetStubInternal(repatchBuffer, stubInfo);
}
for (size_t size = m_methodCallLinkInfos.size(), i = 0; i < size; ++i) {
@@ -2198,6 +2180,40 @@ void CodeBlock::finalizeUnconditionally()
#endif
}
+#if ENABLE(JIT)
+void CodeBlock::resetStub(StructureStubInfo& stubInfo)
+{
+ if (stubInfo.accessType == access_unset)
+ return;
+
+ RepatchBuffer repatchBuffer(this);
+ resetStubInternal(repatchBuffer, stubInfo);
+}
+
+void CodeBlock::resetStubInternal(RepatchBuffer& repatchBuffer, StructureStubInfo& stubInfo)
+{
+ AccessType accessType = static_cast<AccessType>(stubInfo.accessType);
+
+ if (verboseUnlinking)
+ dataLog("Clearing structure cache (kind %d) in %p.\n", stubInfo.accessType, this);
+
+ if (isGetByIdAccess(accessType)) {
+ if (getJITCode().jitType() == JITCode::DFGJIT)
+ DFG::dfgResetGetByID(repatchBuffer, stubInfo);
+ else
+ JIT::resetPatchGetById(repatchBuffer, &stubInfo);
+ } else {
+ ASSERT(isPutByIdAccess(accessType));
+ if (getJITCode().jitType() == JITCode::DFGJIT)
+ DFG::dfgResetPutByID(repatchBuffer, stubInfo);
+ else
+ JIT::resetPatchPutById(repatchBuffer, &stubInfo);
+ }
+
+ stubInfo.reset();
+}
+#endif
+
void CodeBlock::stronglyVisitStrongReferences(SlotVisitor& visitor)
{
visitor.append(&m_globalObject);
diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.h b/Source/JavaScriptCore/bytecode/CodeBlock.h
index ed072f832..56ede595a 100644
--- a/Source/JavaScriptCore/bytecode/CodeBlock.h
+++ b/Source/JavaScriptCore/bytecode/CodeBlock.h
@@ -55,6 +55,7 @@
#include "JITCode.h"
#include "JITWriteBarrier.h"
#include "JSGlobalObject.h"
+#include "JumpReplacementWatchpoint.h"
#include "JumpTable.h"
#include "LLIntCallLinkInfo.h"
#include "LazyOperandValueProfile.h"
@@ -103,6 +104,7 @@ namespace JSC {
class DFGCodeBlocks;
class ExecState;
class LLIntOffsetsExtractor;
+ class RepatchBuffer;
inline int unmodifiedArgumentsRegister(int argumentsRegister) { return argumentsRegister - 1; }
@@ -204,6 +206,8 @@ namespace JSC {
{
return *(binarySearch<StructureStubInfo, unsigned, getStructureStubInfoBytecodeIndex>(m_structureStubInfos.begin(), m_structureStubInfos.size(), bytecodeIndex));
}
+
+ void resetStub(StructureStubInfo&);
CallLinkInfo& getCallLinkInfo(ReturnAddressPtr returnAddress)
{
@@ -328,7 +332,7 @@ namespace JSC {
return result;
}
- unsigned appendWatchpoint(const Watchpoint& watchpoint)
+ unsigned appendWatchpoint(const JumpReplacementWatchpoint& watchpoint)
{
createDFGDataIfNecessary();
unsigned result = m_dfgData->watchpoints.size();
@@ -367,7 +371,7 @@ namespace JSC {
return m_dfgData->speculationRecovery[index];
}
- Watchpoint& watchpoint(unsigned index)
+ JumpReplacementWatchpoint& watchpoint(unsigned index)
{
return m_dfgData->watchpoints[index];
}
@@ -1232,6 +1236,10 @@ namespace JSC {
if (!m_rareData)
m_rareData = adoptPtr(new RareData);
}
+
+#if ENABLE(JIT)
+ void resetStubInternal(RepatchBuffer&, StructureStubInfo&);
+#endif
int m_numParameters;
@@ -1299,7 +1307,7 @@ namespace JSC {
Vector<DFG::OSREntryData> osrEntry;
SegmentedVector<DFG::OSRExit, 8> osrExit;
Vector<DFG::SpeculationRecovery> speculationRecovery;
- SegmentedVector<Watchpoint, 1, 0> watchpoints;
+ SegmentedVector<JumpReplacementWatchpoint, 1, 0> watchpoints;
Vector<WeakReferenceTransition> transitions;
Vector<WriteBarrier<JSCell> > weakReferences;
DFG::VariableEventStream variableEventStream;
diff --git a/Source/JavaScriptCore/bytecode/CodeOrigin.h b/Source/JavaScriptCore/bytecode/CodeOrigin.h
index 034e48f3f..c9c0f7005 100644
--- a/Source/JavaScriptCore/bytecode/CodeOrigin.h
+++ b/Source/JavaScriptCore/bytecode/CodeOrigin.h
@@ -39,6 +39,8 @@ class ExecutableBase;
class JSFunction;
struct CodeOrigin {
+ static const unsigned maximumBytecodeIndex = (1u << 29) - 1;
+
// Bytecode offset that you'd use to re-execute this instruction.
unsigned bytecodeIndex : 29;
// Bytecode offset corresponding to the opcode that gives the result (needed to handle
@@ -48,7 +50,7 @@ struct CodeOrigin {
InlineCallFrame* inlineCallFrame;
CodeOrigin()
- : bytecodeIndex(std::numeric_limits<uint32_t>::max())
+ : bytecodeIndex(maximumBytecodeIndex)
, valueProfileOffset(0)
, inlineCallFrame(0)
{
@@ -59,11 +61,11 @@ struct CodeOrigin {
, valueProfileOffset(valueProfileOffset)
, inlineCallFrame(inlineCallFrame)
{
- ASSERT(bytecodeIndex < (1u << 29));
+ ASSERT(bytecodeIndex <= maximumBytecodeIndex);
ASSERT(valueProfileOffset < (1u << 3));
}
- bool isSet() const { return bytecodeIndex != std::numeric_limits<uint32_t>::max(); }
+ bool isSet() const { return bytecodeIndex != maximumBytecodeIndex; }
unsigned bytecodeIndexForValueProfile() const
{
diff --git a/Source/JavaScriptCore/bytecode/StructureStubClearingWatchpoint.cpp b/Source/JavaScriptCore/bytecode/StructureStubClearingWatchpoint.cpp
new file mode 100644
index 000000000..5cfb3d1e8
--- /dev/null
+++ b/Source/JavaScriptCore/bytecode/StructureStubClearingWatchpoint.cpp
@@ -0,0 +1,80 @@
+/*
+ * 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 "StructureStubClearingWatchpoint.h"
+
+#if ENABLE(JIT)
+
+#include "CodeBlock.h"
+#include "StructureStubInfo.h"
+
+namespace JSC {
+
+StructureStubClearingWatchpoint::~StructureStubClearingWatchpoint() { }
+
+StructureStubClearingWatchpoint* StructureStubClearingWatchpoint::push(
+ WatchpointsOnStructureStubInfo& holder,
+ OwnPtr<StructureStubClearingWatchpoint>& head)
+{
+ head = adoptPtr(new StructureStubClearingWatchpoint(holder, head.release()));
+ return head.get();
+}
+
+void StructureStubClearingWatchpoint::fireInternal()
+{
+ // This will implicitly cause my own demise: stub reset removes all watchpoints.
+ // That works, because deleting a watchpoint removes it from the set's list, and
+ // the set's list traversal for firing is robust against the set changing.
+ m_holder.codeBlock()->resetStub(*m_holder.stubInfo());
+}
+
+WatchpointsOnStructureStubInfo::~WatchpointsOnStructureStubInfo()
+{
+}
+
+StructureStubClearingWatchpoint* WatchpointsOnStructureStubInfo::addWatchpoint()
+{
+ return StructureStubClearingWatchpoint::push(*this, m_head);
+}
+
+StructureStubClearingWatchpoint* WatchpointsOnStructureStubInfo::ensureReferenceAndAddWatchpoint(
+ RefPtr<WatchpointsOnStructureStubInfo>& holderRef, CodeBlock* codeBlock,
+ StructureStubInfo* stubInfo)
+{
+ if (!holderRef)
+ holderRef = adoptRef(new WatchpointsOnStructureStubInfo(codeBlock, stubInfo));
+ else {
+ ASSERT(holderRef->m_codeBlock == codeBlock);
+ ASSERT(holderRef->m_stubInfo == stubInfo);
+ }
+
+ return holderRef->addWatchpoint();
+}
+
+} // namespace JSC
+
+#endif // ENABLE(JIT)
+
diff --git a/Source/JavaScriptCore/bytecode/StructureStubClearingWatchpoint.h b/Source/JavaScriptCore/bytecode/StructureStubClearingWatchpoint.h
new file mode 100644
index 000000000..827e816ee
--- /dev/null
+++ b/Source/JavaScriptCore/bytecode/StructureStubClearingWatchpoint.h
@@ -0,0 +1,109 @@
+/*
+ * 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 StructureStubClearingWatchpoint_h
+#define StructureStubClearingWatchpoint_h
+
+#include "Watchpoint.h"
+#include <wtf/Platform.h>
+
+#if ENABLE(JIT)
+
+#include <wtf/FastAllocBase.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+
+namespace JSC {
+
+class CodeBlock;
+class WatchpointsOnStructureStubInfo;
+struct StructureStubInfo;
+
+class StructureStubClearingWatchpoint : public Watchpoint {
+ WTF_MAKE_NONCOPYABLE(StructureStubClearingWatchpoint);
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ StructureStubClearingWatchpoint(
+ WatchpointsOnStructureStubInfo& holder)
+ : m_holder(holder)
+ {
+ }
+
+ StructureStubClearingWatchpoint(
+ WatchpointsOnStructureStubInfo& holder,
+ PassOwnPtr<StructureStubClearingWatchpoint> next)
+ : m_holder(holder)
+ , m_next(next)
+ {
+ }
+
+ virtual ~StructureStubClearingWatchpoint();
+
+ static StructureStubClearingWatchpoint* push(
+ WatchpointsOnStructureStubInfo& holder,
+ OwnPtr<StructureStubClearingWatchpoint>& head);
+
+protected:
+ void fireInternal();
+
+private:
+ WatchpointsOnStructureStubInfo& m_holder;
+ OwnPtr<StructureStubClearingWatchpoint> m_next;
+};
+
+class WatchpointsOnStructureStubInfo : public RefCounted<WatchpointsOnStructureStubInfo> {
+public:
+ WatchpointsOnStructureStubInfo(CodeBlock* codeBlock, StructureStubInfo* stubInfo)
+ : m_codeBlock(codeBlock)
+ , m_stubInfo(stubInfo)
+ {
+ }
+
+ ~WatchpointsOnStructureStubInfo();
+
+ StructureStubClearingWatchpoint* addWatchpoint();
+
+ static StructureStubClearingWatchpoint* ensureReferenceAndAddWatchpoint(
+ RefPtr<WatchpointsOnStructureStubInfo>& holderRef,
+ CodeBlock*, StructureStubInfo*);
+
+ CodeBlock* codeBlock() const { return m_codeBlock; }
+ StructureStubInfo* stubInfo() const { return m_stubInfo; }
+
+private:
+ CodeBlock* m_codeBlock;
+ StructureStubInfo* m_stubInfo;
+ OwnPtr<StructureStubClearingWatchpoint> m_head;
+};
+
+} // namespace JSC
+
+#endif // ENABLE(JIT)
+
+#endif // StructureStubClearingWatchpoint_h
+
diff --git a/Source/JavaScriptCore/bytecode/StructureStubInfo.h b/Source/JavaScriptCore/bytecode/StructureStubInfo.h
index 807966cf3..737ea88c2 100644
--- a/Source/JavaScriptCore/bytecode/StructureStubInfo.h
+++ b/Source/JavaScriptCore/bytecode/StructureStubInfo.h
@@ -36,6 +36,8 @@
#include "MacroAssembler.h"
#include "Opcode.h"
#include "Structure.h"
+#include "StructureStubClearingWatchpoint.h"
+#include <wtf/OwnPtr.h>
namespace JSC {
@@ -170,6 +172,7 @@ namespace JSC {
deref();
accessType = access_unset;
stubRoutine.clear();
+ watchpoints.clear();
}
void deref();
@@ -186,6 +189,12 @@ namespace JSC {
seen = true;
}
+ StructureStubClearingWatchpoint* addWatchpoint(CodeBlock* codeBlock)
+ {
+ return WatchpointsOnStructureStubInfo::ensureReferenceAndAddWatchpoint(
+ watchpoints, codeBlock, this);
+ }
+
unsigned bytecodeIndex;
int8_t accessType;
@@ -290,6 +299,7 @@ namespace JSC {
RefPtr<JITStubRoutine> stubRoutine;
CodeLocationCall callReturnLocation;
CodeLocationLabel hotPathBegin;
+ RefPtr<WatchpointsOnStructureStubInfo> watchpoints;
};
inline void* getStructureStubInfoReturnLocation(StructureStubInfo* structureStubInfo)
diff --git a/Source/JavaScriptCore/bytecode/Watchpoint.cpp b/Source/JavaScriptCore/bytecode/Watchpoint.cpp
index 1dd633f52..6f80dfa5e 100644
--- a/Source/JavaScriptCore/bytecode/Watchpoint.cpp
+++ b/Source/JavaScriptCore/bytecode/Watchpoint.cpp
@@ -4,26 +4,23 @@
* 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.
*
- * 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.
+ * 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"
@@ -39,30 +36,6 @@ Watchpoint::~Watchpoint()
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)
diff --git a/Source/JavaScriptCore/bytecode/Watchpoint.h b/Source/JavaScriptCore/bytecode/Watchpoint.h
index 0055bf607..8e0526c0f 100644
--- a/Source/JavaScriptCore/bytecode/Watchpoint.h
+++ b/Source/JavaScriptCore/bytecode/Watchpoint.h
@@ -4,33 +4,28 @@
* 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.
*
- * 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.
+ * 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 Watchpoint_h
#define Watchpoint_h
-#include "CodeLocation.h"
-#include "MacroAssembler.h"
#include <wtf/RefCounted.h>
#include <wtf/SentinelLinkedList.h>
@@ -39,33 +34,15 @@ 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();
+ virtual ~Watchpoint();
+
+ void fire() { fireInternal(); }
-private:
- uintptr_t m_source;
- uintptr_t m_destination;
+protected:
+ virtual void fireInternal() = 0;
};
enum InitialWatchpointSetMode { InitializedWatching, InitializedBlind };
diff --git a/Source/JavaScriptCore/dfg/DFGAbstractState.cpp b/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
index 4cd31f2a8..95f44c092 100644
--- a/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
+++ b/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
@@ -52,6 +52,10 @@ void AbstractState::beginBasicBlock(BasicBlock* basicBlock)
ASSERT(basicBlock->variablesAtTail.numberOfLocals() == basicBlock->valuesAtTail.numberOfLocals());
ASSERT(basicBlock->variablesAtHead.numberOfLocals() == basicBlock->variablesAtTail.numberOfLocals());
+ // This is usually a no-op, but it is possible that the graph has grown since the
+ // abstract state was last used.
+ m_nodes.resize(m_graph.size());
+
for (size_t i = 0; i < basicBlock->size(); i++)
m_nodes[basicBlock->at(i)].clear();
@@ -164,6 +168,7 @@ bool AbstractState::endBasicBlock(MergeMode mergeMode, BranchDirection* branchDi
BasicBlock* block = m_block; // Save the block for successor merging.
block->cfaFoundConstants = m_foundConstants;
+ block->cfaDidFinish = m_isValid;
if (!m_isValid) {
reset();
diff --git a/Source/JavaScriptCore/dfg/DFGAssemblyHelpers.h b/Source/JavaScriptCore/dfg/DFGAssemblyHelpers.h
index 4bea292f3..57f758c9c 100644
--- a/Source/JavaScriptCore/dfg/DFGAssemblyHelpers.h
+++ b/Source/JavaScriptCore/dfg/DFGAssemblyHelpers.h
@@ -46,12 +46,13 @@ public:
AssemblyHelpers(JSGlobalData* globalData, CodeBlock* codeBlock)
: m_globalData(globalData)
, m_codeBlock(codeBlock)
- , m_baselineCodeBlock(codeBlock->baselineVersion())
+ , m_baselineCodeBlock(codeBlock ? codeBlock->baselineVersion() : 0)
{
- ASSERT(m_codeBlock);
- ASSERT(m_baselineCodeBlock);
- ASSERT(!m_baselineCodeBlock->alternative());
- ASSERT(m_baselineCodeBlock->getJITType() == JITCode::BaselineJIT);
+ if (m_codeBlock) {
+ ASSERT(m_baselineCodeBlock);
+ ASSERT(!m_baselineCodeBlock->alternative());
+ ASSERT(m_baselineCodeBlock->getJITType() == JITCode::BaselineJIT);
+ }
}
CodeBlock* codeBlock() { return m_codeBlock; }
diff --git a/Source/JavaScriptCore/dfg/DFGBasicBlock.h b/Source/JavaScriptCore/dfg/DFGBasicBlock.h
index 9128f0882..441e2e75e 100644
--- a/Source/JavaScriptCore/dfg/DFGBasicBlock.h
+++ b/Source/JavaScriptCore/dfg/DFGBasicBlock.h
@@ -45,6 +45,7 @@ struct BasicBlock : Vector<NodeIndex, 8> {
, cfaHasVisited(false)
, cfaShouldRevisit(false)
, cfaFoundConstants(false)
+ , cfaDidFinish(true)
#if !ASSERT_DISABLED
, isLinked(false)
#endif
@@ -103,6 +104,7 @@ struct BasicBlock : Vector<NodeIndex, 8> {
bool cfaHasVisited;
bool cfaShouldRevisit;
bool cfaFoundConstants;
+ bool cfaDidFinish;
#if !ASSERT_DISABLED
bool isLinked;
#endif
diff --git a/Source/JavaScriptCore/dfg/DFGCCallHelpers.h b/Source/JavaScriptCore/dfg/DFGCCallHelpers.h
index 9c1718bdb..5985b251e 100644
--- a/Source/JavaScriptCore/dfg/DFGCCallHelpers.h
+++ b/Source/JavaScriptCore/dfg/DFGCCallHelpers.h
@@ -37,7 +37,7 @@ namespace JSC { namespace DFG {
class CCallHelpers : public AssemblyHelpers {
public:
- CCallHelpers(JSGlobalData* globalData, CodeBlock* codeBlock)
+ CCallHelpers(JSGlobalData* globalData, CodeBlock* codeBlock = 0)
: AssemblyHelpers(globalData, codeBlock)
{
}
diff --git a/Source/JavaScriptCore/dfg/DFGCFAPhase.cpp b/Source/JavaScriptCore/dfg/DFGCFAPhase.cpp
index c52349645..24ea0b36f 100644
--- a/Source/JavaScriptCore/dfg/DFGCFAPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGCFAPhase.cpp
@@ -95,8 +95,12 @@ private:
m_state.dump(WTF::dataFile());
dataLog("\n");
#endif
- if (!m_state.execute(i))
+ if (!m_state.execute(i)) {
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+ dataLog(" Expect OSR exit.\n");
+#endif
break;
+ }
}
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
dataLog(" tail regs: ");
diff --git a/Source/JavaScriptCore/dfg/DFGCFGSimplificationPhase.cpp b/Source/JavaScriptCore/dfg/DFGCFGSimplificationPhase.cpp
index c234e6e4e..dc1632dc4 100644
--- a/Source/JavaScriptCore/dfg/DFGCFGSimplificationPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGCFGSimplificationPhase.cpp
@@ -643,18 +643,6 @@ 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;
}
diff --git a/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp b/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp
index d3029b39a..a8eb9ee5c 100644
--- a/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp
@@ -40,6 +40,7 @@ class ConstantFoldingPhase : public Phase {
public:
ConstantFoldingPhase(Graph& graph)
: Phase(graph, "constant folding")
+ , m_state(graph)
{
}
@@ -47,114 +48,192 @@ public:
{
bool changed = false;
- AbstractState state(m_graph);
- InsertionSet<NodeIndex> insertionSet;
-
for (BlockIndex blockIndex = 0; blockIndex < m_graph.m_blocks.size(); ++blockIndex) {
BasicBlock* block = m_graph.m_blocks[blockIndex].get();
if (!block)
continue;
- if (!block->cfaFoundConstants)
- continue;
+ if (!block->cfaDidFinish)
+ changed |= paintUnreachableCode(blockIndex);
+ if (block->cfaFoundConstants)
+ changed |= foldConstants(blockIndex);
+ }
+
+ return changed;
+ }
+
+private:
+ bool foldConstants(BlockIndex blockIndex)
+ {
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
- dataLog("Constant folding considering Block #%u.\n", blockIndex);
+ dataLog("Constant folding considering Block #%u.\n", blockIndex);
#endif
- state.beginBasicBlock(block);
- for (unsigned indexInBlock = 0; indexInBlock < block->size(); ++indexInBlock) {
- if (!state.isValid())
- break;
- NodeIndex nodeIndex = block->at(indexInBlock);
- Node& node = m_graph[nodeIndex];
+ BasicBlock* block = m_graph.m_blocks[blockIndex].get();
+ bool changed = false;
+ m_state.beginBasicBlock(block);
+ for (unsigned indexInBlock = 0; indexInBlock < block->size(); ++indexInBlock) {
+ NodeIndex nodeIndex = block->at(indexInBlock);
+ Node& node = m_graph[nodeIndex];
- bool eliminated = false;
+ if (!m_state.isValid())
+ break;
+
+ 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;
+ switch (node.op()) {
+ case CheckArgumentsNotCreated: {
+ if (!isEmptySpeculation(
+ m_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;
- }
+ default:
+ break;
+ }
- if (eliminated) {
- changed = true;
- continue;
- }
+ if (eliminated) {
+ changed = true;
+ continue;
+ }
- state.execute(indexInBlock);
- if (!node.shouldGenerate()
- || state.didClobber()
- || node.hasConstant())
- continue;
- JSValue value = state.forNode(nodeIndex).value();
- if (!value)
- continue;
+ m_state.execute(indexInBlock);
+ if (!node.shouldGenerate()
+ || m_state.didClobber()
+ || node.hasConstant())
+ continue;
+ JSValue value = m_state.forNode(nodeIndex).value();
+ if (!value)
+ continue;
- Node phantom(Phantom, node.codeOrigin);
+ Node phantom(Phantom, node.codeOrigin);
- if (node.op() == GetLocal) {
- NodeIndex previousLocalAccess = NoNode;
- 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();
- block->variablesAtHead.operand(node.local()) = previousLocalAccess;
- } else {
- ASSERT(indexInBlock > 0);
- // Must search for the previous access to this local.
- for (BlockIndex subIndexInBlock = indexInBlock; subIndexInBlock--;) {
- NodeIndex subNodeIndex = block->at(subIndexInBlock);
- Node& subNode = m_graph[subNodeIndex];
- if (!subNode.shouldGenerate())
- continue;
- if (!subNode.hasVariableAccessData())
+ if (node.op() == GetLocal) {
+ NodeIndex previousLocalAccess = NoNode;
+ 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();
+ block->variablesAtHead.operand(node.local()) = previousLocalAccess;
+ } else {
+ ASSERT(indexInBlock > 0);
+ // Must search for the previous access to this local.
+ for (BlockIndex subIndexInBlock = indexInBlock; subIndexInBlock--;) {
+ NodeIndex subNodeIndex = block->at(subIndexInBlock);
+ Node& subNode = m_graph[subNodeIndex];
+ if (!subNode.shouldGenerate())
+ continue;
+ if (!subNode.hasVariableAccessData())
+ continue;
+ if (subNode.local() != node.local())
+ continue;
+ // The two must have been unified.
+ ASSERT(subNode.variableAccessData() == node.variableAccessData());
+ previousLocalAccess = subNodeIndex;
+ break;
+ }
+ if (previousLocalAccess == NoNode) {
+ // The previous access must have been a Phi.
+ for (BlockIndex phiIndexInBlock = block->phis.size(); phiIndexInBlock--;) {
+ NodeIndex phiNodeIndex = block->phis[phiIndexInBlock];
+ Node& phiNode = m_graph[phiNodeIndex];
+ if (!phiNode.shouldGenerate())
continue;
- if (subNode.local() != node.local())
+ if (phiNode.local() != node.local())
continue;
// The two must have been unified.
- ASSERT(subNode.variableAccessData() == node.variableAccessData());
- previousLocalAccess = subNodeIndex;
+ ASSERT(phiNode.variableAccessData() == node.variableAccessData());
+ previousLocalAccess = phiNodeIndex;
break;
}
ASSERT(previousLocalAccess != NoNode);
}
+ }
- NodeIndex tailNodeIndex = block->variablesAtTail.operand(node.local());
- if (tailNodeIndex == nodeIndex)
- block->variablesAtTail.operand(node.local()) = previousLocalAccess;
- else {
- ASSERT(m_graph[tailNodeIndex].op() == Flush
- || m_graph[tailNodeIndex].op() == SetLocal);
- }
+ ASSERT(previousLocalAccess != NoNode);
+
+ NodeIndex tailNodeIndex = block->variablesAtTail.operand(node.local());
+ if (tailNodeIndex == nodeIndex)
+ block->variablesAtTail.operand(node.local()) = previousLocalAccess;
+ else {
+ ASSERT(m_graph[tailNodeIndex].op() == Flush
+ || m_graph[tailNodeIndex].op() == SetLocal);
}
+ }
- phantom.children = node.children;
- phantom.ref();
+ phantom.children = node.children;
+ phantom.ref();
+
+ m_graph.convertToConstant(nodeIndex, value);
+ NodeIndex phantomNodeIndex = m_graph.size();
+ m_graph.append(phantom);
+ m_insertionSet.append(indexInBlock, phantomNodeIndex);
- m_graph.convertToConstant(nodeIndex, value);
- NodeIndex phantomNodeIndex = m_graph.size();
- m_graph.append(phantom);
- insertionSet.append(indexInBlock, phantomNodeIndex);
+ changed = true;
+ }
+ m_state.reset();
+ m_insertionSet.execute(*block);
+
+ return changed;
+ }
+
+ // This is necessary because the CFA may reach conclusions about constants based on its
+ // assumption that certain code must exit, but then those constants may lead future
+ // reexecutions of the CFA to believe that the same code will now no longer exit. Thus
+ // to ensure soundness, we must paint unreachable code as such, by inserting an
+ // unconditional ForceOSRExit wherever we find that a node would have always exited.
+ // This will only happen in cases where we are making static speculations, or we're
+ // making totally wrong speculations due to imprecision on the prediction propagator.
+ bool paintUnreachableCode(BlockIndex blockIndex)
+ {
+ bool changed = false;
+
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+ dataLog("Painting unreachable code in Block #%u.\n", blockIndex);
+#endif
+ BasicBlock* block = m_graph.m_blocks[blockIndex].get();
+ m_state.beginBasicBlock(block);
+
+ for (unsigned indexInBlock = 0; indexInBlock < block->size(); ++indexInBlock) {
+ m_state.execute(indexInBlock);
+ if (m_state.isValid())
+ continue;
+
+ NodeIndex nodeIndex = block->at(indexInBlock);
+ Node& node = m_graph[nodeIndex];
+ switch (node.op()) {
+ case Return:
+ case Throw:
+ case ThrowReferenceError:
+ case ForceOSRExit:
+ // Do nothing. These nodes will already do the right thing.
+ break;
+ default:
+ Node forceOSRExit(ForceOSRExit, node.codeOrigin);
+ forceOSRExit.ref();
+ NodeIndex forceOSRExitIndex = m_graph.size();
+ m_graph.append(forceOSRExit);
+ m_insertionSet.append(indexInBlock, forceOSRExitIndex);
changed = true;
+ break;
}
- insertionSet.execute(*block);
- state.reset();
+ break;
}
+ m_state.reset();
+ m_insertionSet.execute(*block);
return changed;
}
+
+ AbstractState m_state;
+ InsertionSet<NodeIndex> m_insertionSet;
};
bool performConstantFolding(Graph& graph)
diff --git a/Source/JavaScriptCore/dfg/DFGGPRInfo.h b/Source/JavaScriptCore/dfg/DFGGPRInfo.h
index 89faef94b..23f1697a6 100644
--- a/Source/JavaScriptCore/dfg/DFGGPRInfo.h
+++ b/Source/JavaScriptCore/dfg/DFGGPRInfo.h
@@ -273,6 +273,7 @@ public:
static const GPRReg argumentGPR1 = X86Registers::edx; // regT1
static const GPRReg nonArgGPR0 = X86Registers::eax; // regT0
static const GPRReg nonArgGPR1 = X86Registers::ebx; // regT3
+ static const GPRReg nonArgGPR2 = X86Registers::esi; // regT4
static const GPRReg returnValueGPR = X86Registers::eax; // regT0
static const GPRReg returnValueGPR2 = X86Registers::edx; // regT1
static const GPRReg nonPreservedNonReturnGPR = X86Registers::ecx;
@@ -344,6 +345,7 @@ public:
static const GPRReg argumentGPR5 = X86Registers::r9; // regT7
static const GPRReg nonArgGPR0 = X86Registers::eax; // regT0
static const GPRReg nonArgGPR1 = X86Registers::ebx; // regT3
+ static const GPRReg nonArgGPR2 = X86Registers::r10; // regT8
static const GPRReg returnValueGPR = X86Registers::eax; // regT0
static const GPRReg returnValueGPR2 = X86Registers::edx; // regT1
static const GPRReg nonPreservedNonReturnGPR = X86Registers::esi;
@@ -416,6 +418,7 @@ public:
static const GPRReg argumentGPR3 = ARMRegisters::r3; // FIXME!
static const GPRReg nonArgGPR0 = ARMRegisters::r4; // regT3
static const GPRReg nonArgGPR1 = ARMRegisters::r8; // regT4
+ static const GPRReg nonArgGPR2 = ARMRegisters::r9; // regT5
static const GPRReg returnValueGPR = ARMRegisters::r0; // regT0
static const GPRReg returnValueGPR2 = ARMRegisters::r1; // regT1
static const GPRReg nonPreservedNonReturnGPR = ARMRegisters::r2;
diff --git a/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp b/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp
index 497fc346f..2ebee13c1 100644
--- a/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp
+++ b/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp
@@ -153,7 +153,6 @@ void JITCompiler::link(LinkBuffer& linkBuffer)
unsigned returnAddressOffset = linkBuffer.returnAddressOffset(m_exceptionChecks[i].m_call);
codeOrigins[i].codeOrigin = record.m_codeOrigin;
codeOrigins[i].callReturnOffset = returnAddressOffset;
- record.m_token.assertCodeOriginIndex(i);
}
m_codeBlock->setNumberOfStructureStubInfos(m_propertyAccesses.size());
@@ -189,7 +188,8 @@ void JITCompiler::link(LinkBuffer& linkBuffer)
CallLinkInfo& info = m_codeBlock->callLinkInfo(i);
info.callType = m_jsCalls[i].m_callType;
info.isDFG = true;
- info.callReturnLocation = CodeLocationLabel(linkBuffer.locationOf(m_jsCalls[i].m_slowCall));
+ linkBuffer.link(m_jsCalls[i].m_slowCall, FunctionPtr((m_globalData->getCTIStub(info.callType == CallLinkInfo::Construct ? linkConstructThunkGenerator : linkCallThunkGenerator)).code().executableAddress()));
+ info.callReturnLocation = linkBuffer.locationOfNearCall(m_jsCalls[i].m_slowCall);
info.hotPathBegin = linkBuffer.locationOf(m_jsCalls[i].m_targetToCheck);
info.hotPathOther = linkBuffer.locationOfNearCall(m_jsCalls[i].m_fastCall);
}
@@ -280,7 +280,8 @@ bool JITCompiler::compileFunction(JITCode& entry, MacroAssemblerCodePtr& entryWi
move(stackPointerRegister, GPRInfo::argumentGPR0);
poke(GPRInfo::callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*));
- CallBeginToken token = beginCall();
+ CallBeginToken token;
+ beginCall(CodeOrigin(0), token);
Call callRegisterFileCheck = call();
notifyCall(callRegisterFileCheck, CodeOrigin(0), token);
jump(fromRegisterFileCheck);
@@ -297,7 +298,7 @@ bool JITCompiler::compileFunction(JITCode& entry, MacroAssemblerCodePtr& entryWi
branch32(AboveOrEqual, GPRInfo::regT1, TrustedImm32(m_codeBlock->numParameters())).linkTo(fromArityCheck, this);
move(stackPointerRegister, GPRInfo::argumentGPR0);
poke(GPRInfo::callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*));
- token = beginCall();
+ beginCall(CodeOrigin(0), token);
Call callArityCheck = call();
notifyCall(callArityCheck, CodeOrigin(0), token);
move(GPRInfo::regT0, GPRInfo::callFrameRegister);
diff --git a/Source/JavaScriptCore/dfg/DFGJITCompiler.h b/Source/JavaScriptCore/dfg/DFGJITCompiler.h
index 24dbbdcd0..d6374b790 100644
--- a/Source/JavaScriptCore/dfg/DFGJITCompiler.h
+++ b/Source/JavaScriptCore/dfg/DFGJITCompiler.h
@@ -76,28 +76,58 @@ class CallBeginToken {
public:
CallBeginToken()
#if !ASSERT_DISABLED
- : m_codeOriginIndex(UINT_MAX)
+ : m_registered(false)
+ , m_exceptionCheckIndex(std::numeric_limits<unsigned>::max())
#endif
{
}
- explicit CallBeginToken(unsigned codeOriginIndex)
+ ~CallBeginToken()
+ {
+ ASSERT(m_registered || !m_codeOrigin.isSet());
+ ASSERT(m_codeOrigin.isSet() == (m_exceptionCheckIndex != std::numeric_limits<unsigned>::max()));
+ }
+
+ void set(CodeOrigin codeOrigin, unsigned index)
+ {
#if !ASSERT_DISABLED
- : m_codeOriginIndex(codeOriginIndex)
+ ASSERT(m_registered || !m_codeOrigin.isSet());
+ ASSERT(m_codeOrigin.isSet() == (m_exceptionCheckIndex != std::numeric_limits<unsigned>::max()));
+ m_codeOrigin = codeOrigin;
+ m_registered = false;
+ m_exceptionCheckIndex = index;
+#else
+ UNUSED_PARAM(codeOrigin);
+ UNUSED_PARAM(index);
#endif
- {
- UNUSED_PARAM(codeOriginIndex);
}
- void assertCodeOriginIndex(unsigned codeOriginIndex) const
+ void registerWithExceptionCheck(CodeOrigin codeOrigin, unsigned index)
{
- ASSERT_UNUSED(codeOriginIndex, codeOriginIndex < UINT_MAX);
- ASSERT_UNUSED(codeOriginIndex, codeOriginIndex == m_codeOriginIndex);
+#if !ASSERT_DISABLED
+ ASSERT(m_codeOrigin == codeOrigin);
+ if (m_registered)
+ return;
+ ASSERT(m_exceptionCheckIndex == index);
+ m_registered = true;
+#else
+ UNUSED_PARAM(codeOrigin);
+ UNUSED_PARAM(index);
+#endif
}
+#if !ASSERT_DISABLED
+ const CodeOrigin& codeOrigin() const
+ {
+ return m_codeOrigin;
+ }
+#endif
+
private:
#if !ASSERT_DISABLED
- unsigned m_codeOriginIndex;
+ CodeOrigin m_codeOrigin;
+ bool m_registered;
+ unsigned m_exceptionCheckIndex;
#endif
};
@@ -107,25 +137,22 @@ private:
// Calls that might throw an exception also record the Jump taken on exception
// (unset if not present) and code origin used to recover handler/source info.
struct CallExceptionRecord {
- CallExceptionRecord(MacroAssembler::Call call, CodeOrigin codeOrigin, CallBeginToken token)
+ CallExceptionRecord(MacroAssembler::Call call, CodeOrigin codeOrigin)
: m_call(call)
, m_codeOrigin(codeOrigin)
- , m_token(token)
{
}
- CallExceptionRecord(MacroAssembler::Call call, MacroAssembler::Jump exceptionCheck, CodeOrigin codeOrigin, CallBeginToken token)
+ CallExceptionRecord(MacroAssembler::Call call, MacroAssembler::Jump exceptionCheck, CodeOrigin codeOrigin)
: m_call(call)
, m_exceptionCheck(exceptionCheck)
, m_codeOrigin(codeOrigin)
- , m_token(token)
{
}
MacroAssembler::Call m_call;
MacroAssembler::Jump m_exceptionCheck;
CodeOrigin m_codeOrigin;
- CallBeginToken m_token;
};
struct PropertyAccessRecord {
@@ -257,19 +284,27 @@ public:
m_disassembler->setEndOfCode(labelIgnoringWatchpoints());
}
+ unsigned currentCodeOriginIndex() const
+ {
+ return m_currentCodeOriginIndex;
+ }
+
// Get a token for beginning a call, and set the current code origin index in
- // the call frame.
- CallBeginToken beginCall()
+ // the call frame. For each beginCall() there must be at least one exception
+ // check, and all of the exception checks must have the same CodeOrigin as the
+ // beginCall().
+ void beginCall(CodeOrigin codeOrigin, CallBeginToken& token)
{
- unsigned codeOriginIndex = m_currentCodeOriginIndex++;
- store32(TrustedImm32(codeOriginIndex), tagFor(static_cast<VirtualRegister>(RegisterFile::ArgumentCount)));
- return CallBeginToken(codeOriginIndex);
+ unsigned index = m_exceptionChecks.size();
+ store32(TrustedImm32(index), tagFor(static_cast<VirtualRegister>(RegisterFile::ArgumentCount)));
+ token.set(codeOrigin, index);
}
// Notify the JIT of a call that does not require linking.
- void notifyCall(Call functionCall, CodeOrigin codeOrigin, CallBeginToken token)
+ void notifyCall(Call functionCall, CodeOrigin codeOrigin, CallBeginToken& token)
{
- m_exceptionChecks.append(CallExceptionRecord(functionCall, codeOrigin, token));
+ token.registerWithExceptionCheck(codeOrigin, m_exceptionChecks.size());
+ m_exceptionChecks.append(CallExceptionRecord(functionCall, codeOrigin));
}
// Add a call out from JIT code, without an exception check.
@@ -279,20 +314,27 @@ public:
m_calls.append(CallLinkRecord(functionCall, function));
return functionCall;
}
+
+ void prepareForExceptionCheck()
+ {
+ move(TrustedImm32(m_exceptionChecks.size()), GPRInfo::nonPreservedNonReturnGPR);
+ }
// Add a call out from JIT code, with an exception check.
- void addExceptionCheck(Call functionCall, CodeOrigin codeOrigin, CallBeginToken token)
+ void addExceptionCheck(Call functionCall, CodeOrigin codeOrigin, CallBeginToken& token)
{
- move(TrustedImm32(m_exceptionChecks.size()), GPRInfo::nonPreservedNonReturnGPR);
- m_exceptionChecks.append(CallExceptionRecord(functionCall, emitExceptionCheck(), codeOrigin, token));
+ prepareForExceptionCheck();
+ token.registerWithExceptionCheck(codeOrigin, m_exceptionChecks.size());
+ m_exceptionChecks.append(CallExceptionRecord(functionCall, emitExceptionCheck(), codeOrigin));
}
// Add a call out from JIT code, with a fast exception check that tests if the return value is zero.
- void addFastExceptionCheck(Call functionCall, CodeOrigin codeOrigin, CallBeginToken token)
+ void addFastExceptionCheck(Call functionCall, CodeOrigin codeOrigin, CallBeginToken& token)
{
- move(TrustedImm32(m_exceptionChecks.size()), GPRInfo::nonPreservedNonReturnGPR);
+ prepareForExceptionCheck();
Jump exceptionCheck = branchTestPtr(Zero, GPRInfo::returnValueGPR);
- m_exceptionChecks.append(CallExceptionRecord(functionCall, exceptionCheck, codeOrigin, token));
+ token.registerWithExceptionCheck(codeOrigin, m_exceptionChecks.size());
+ m_exceptionChecks.append(CallExceptionRecord(functionCall, exceptionCheck, codeOrigin));
}
// Helper methods to get predictions
diff --git a/Source/JavaScriptCore/dfg/DFGOperations.cpp b/Source/JavaScriptCore/dfg/DFGOperations.cpp
index 5d6575a6f..bbe55d351 100644
--- a/Source/JavaScriptCore/dfg/DFGOperations.cpp
+++ b/Source/JavaScriptCore/dfg/DFGOperations.cpp
@@ -30,6 +30,7 @@
#include "CodeBlock.h"
#include "DFGOSRExit.h"
#include "DFGRepatch.h"
+#include "DFGThunks.h"
#include "HostCallReturnValue.h"
#include "GetterSetter.h"
#include "Interpreter.h"
@@ -849,7 +850,6 @@ static void* handleHostCall(ExecState* execCallee, JSValue callee, CodeSpecializ
execCallee->setScopeChain(exec->scopeChain());
execCallee->setCodeBlock(0);
- execCallee->clearReturnPC();
if (kind == CodeForCall) {
CallData callData;
@@ -862,14 +862,14 @@ static void* handleHostCall(ExecState* execCallee, JSValue callee, CodeSpecializ
execCallee->setCallee(asObject(callee));
globalData->hostCallReturnValue = JSValue::decode(callData.native.function(execCallee));
if (globalData->exception)
- return 0;
+ return globalData->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress();
return reinterpret_cast<void*>(getHostCallReturnValue);
}
ASSERT(callType == CallTypeNone);
exec->globalData().exception = createNotAFunctionError(exec, callee);
- return 0;
+ return globalData->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress();
}
ASSERT(kind == CodeForConstruct);
@@ -884,17 +884,17 @@ static void* handleHostCall(ExecState* execCallee, JSValue callee, CodeSpecializ
execCallee->setCallee(asObject(callee));
globalData->hostCallReturnValue = JSValue::decode(constructData.native.function(execCallee));
if (globalData->exception)
- return 0;
+ return globalData->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress();
return reinterpret_cast<void*>(getHostCallReturnValue);
}
ASSERT(constructType == ConstructTypeNone);
exec->globalData().exception = createNotAConstructorError(exec, callee);
- return 0;
+ return globalData->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress();
}
-inline void* linkFor(ExecState* execCallee, ReturnAddressPtr returnAddress, CodeSpecializationKind kind)
+inline void* linkFor(ExecState* execCallee, CodeSpecializationKind kind)
{
ExecState* exec = execCallee->callerFrame();
JSGlobalData* globalData = &exec->globalData();
@@ -918,7 +918,7 @@ inline void* linkFor(ExecState* execCallee, ReturnAddressPtr returnAddress, Code
JSObject* error = functionExecutable->compileFor(execCallee, callee->scope(), kind);
if (error) {
globalData->exception = createStackOverflowError(exec);
- return 0;
+ return globalData->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress();
}
codeBlock = &functionExecutable->generatedBytecodeFor(kind);
if (execCallee->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->numParameters()))
@@ -926,7 +926,7 @@ inline void* linkFor(ExecState* execCallee, ReturnAddressPtr returnAddress, Code
else
codePtr = functionExecutable->generatedJITCodeFor(kind).addressForCall();
}
- CallLinkInfo& callLinkInfo = exec->codeBlock()->getCallLinkInfo(returnAddress);
+ CallLinkInfo& callLinkInfo = exec->codeBlock()->getCallLinkInfo(execCallee->returnPC());
if (!callLinkInfo.seenOnce())
callLinkInfo.setSeen();
else
@@ -934,16 +934,14 @@ inline void* linkFor(ExecState* execCallee, ReturnAddressPtr returnAddress, Code
return codePtr.executableAddress();
}
-P_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_E(operationLinkCall);
-void* DFG_OPERATION operationLinkCallWithReturnAddress(ExecState* execCallee, ReturnAddressPtr returnAddress)
+void* DFG_OPERATION operationLinkCall(ExecState* execCallee)
{
- return linkFor(execCallee, returnAddress, CodeForCall);
+ return linkFor(execCallee, CodeForCall);
}
-P_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_E(operationLinkConstruct);
-void* DFG_OPERATION operationLinkConstructWithReturnAddress(ExecState* execCallee, ReturnAddressPtr returnAddress)
+void* DFG_OPERATION operationLinkConstruct(ExecState* execCallee)
{
- return linkFor(execCallee, returnAddress, CodeForConstruct);
+ return linkFor(execCallee, CodeForConstruct);
}
inline void* virtualFor(ExecState* execCallee, CodeSpecializationKind kind)
@@ -965,7 +963,7 @@ inline void* virtualFor(ExecState* execCallee, CodeSpecializationKind kind)
JSObject* error = functionExecutable->compileFor(execCallee, function->scope(), kind);
if (error) {
exec->globalData().exception = error;
- return 0;
+ return globalData->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress();
}
}
return executable->generatedJITCodeWithArityCheckFor(kind).executableAddress();
diff --git a/Source/JavaScriptCore/dfg/DFGRepatch.cpp b/Source/JavaScriptCore/dfg/DFGRepatch.cpp
index 752316f9c..e25c6aa27 100644
--- a/Source/JavaScriptCore/dfg/DFGRepatch.cpp
+++ b/Source/JavaScriptCore/dfg/DFGRepatch.cpp
@@ -30,6 +30,7 @@
#include "DFGCCallHelpers.h"
#include "DFGSpeculativeJIT.h"
+#include "DFGThunks.h"
#include "GCAwareJITStubRoutine.h"
#include "LinkBuffer.h"
#include "Operations.h"
@@ -70,6 +71,48 @@ static void dfgRepatchByIdSelfAccess(CodeBlock* codeBlock, StructureStubInfo& st
#endif
}
+static void addStructureTransitionCheck(
+ JSCell* object, Structure* structure, CodeBlock* codeBlock, StructureStubInfo& stubInfo,
+ MacroAssembler& jit, MacroAssembler::JumpList& failureCases, GPRReg scratchGPR)
+{
+ if (object->structure() == structure && structure->transitionWatchpointSetIsStillValid()) {
+ structure->addTransitionWatchpoint(stubInfo.addWatchpoint(codeBlock));
+#if DFG_ENABLE(JIT_ASSERT)
+ // If we execute this code, the object must have the structure we expect. Assert
+ // this in debug modes.
+ jit.move(MacroAssembler::TrustedImmPtr(object), scratchGPR);
+ MacroAssembler::Jump ok = jit.branchPtr(
+ MacroAssembler::Equal,
+ MacroAssembler::Address(scratchGPR, JSCell::structureOffset()),
+ MacroAssembler::TrustedImmPtr(structure));
+ jit.breakpoint();
+ ok.link(&jit);
+#endif
+ return;
+ }
+
+ jit.move(MacroAssembler::TrustedImmPtr(object), scratchGPR);
+ failureCases.append(
+ jit.branchPtr(
+ MacroAssembler::NotEqual,
+ MacroAssembler::Address(scratchGPR, JSCell::structureOffset()),
+ MacroAssembler::TrustedImmPtr(structure)));
+}
+
+static void addStructureTransitionCheck(
+ JSValue prototype, CodeBlock* codeBlock, StructureStubInfo& stubInfo,
+ MacroAssembler& jit, MacroAssembler::JumpList& failureCases, GPRReg scratchGPR)
+{
+ if (prototype.isNull())
+ return;
+
+ ASSERT(prototype.isCell());
+
+ addStructureTransitionCheck(
+ prototype.asCell(), prototype.asCell()->structure(), codeBlock, stubInfo, jit,
+ failureCases, scratchGPR);
+}
+
static void emitRestoreScratch(MacroAssembler& stubJit, bool needToRestoreScratch, GPRReg scratchGPR, MacroAssembler::Jump& success, MacroAssembler::Jump& fail, MacroAssembler::JumpList failureCases)
{
if (needToRestoreScratch) {
@@ -136,8 +179,9 @@ static void generateProtoChainAccessStub(ExecState* exec, StructureStubInfo& stu
JSObject* protoObject = 0;
for (unsigned i = 0; i < count; ++i, ++it) {
protoObject = asObject(currStructure->prototypeForLookup(exec));
- stubJit.move(MacroAssembler::TrustedImmPtr(protoObject), scratchGPR);
- failureCases.append(stubJit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(scratchGPR, JSCell::structureOffset()), MacroAssembler::TrustedImmPtr(protoObject->structure())));
+ addStructureTransitionCheck(
+ protoObject, protoObject->structure(), exec->codeBlock(), stubInfo, stubJit,
+ failureCases, scratchGPR);
currStructure = it->get();
}
@@ -568,17 +612,6 @@ static V_DFGOperation_EJCI appropriateListBuildingPutByIdFunction(const PutPrope
return operationPutByIdNonStrictBuildList;
}
-static void testPrototype(MacroAssembler &stubJit, GPRReg scratchGPR, JSValue prototype, MacroAssembler::JumpList& failureCases)
-{
- if (prototype.isNull())
- return;
-
- ASSERT(prototype.isCell());
-
- stubJit.move(MacroAssembler::TrustedImmPtr(prototype.asCell()), scratchGPR);
- failureCases.append(stubJit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(scratchGPR, JSCell::structureOffset()), MacroAssembler::TrustedImmPtr(prototype.asCell()->structure())));
-}
-
static void emitPutReplaceStub(
ExecState* exec,
JSValue,
@@ -707,12 +740,17 @@ static void emitPutTransitionStub(
ASSERT(oldStructure->transitionWatchpointSetHasBeenInvalidated());
failureCases.append(stubJit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::structureOffset()), MacroAssembler::TrustedImmPtr(oldStructure)));
-
- testPrototype(stubJit, scratchGPR, oldStructure->storedPrototype(), failureCases);
+
+ addStructureTransitionCheck(
+ oldStructure->storedPrototype(), exec->codeBlock(), stubInfo, stubJit, failureCases,
+ scratchGPR);
if (putKind == NotDirect) {
- for (WriteBarrier<Structure>* it = prototypeChain->head(); *it; ++it)
- testPrototype(stubJit, scratchGPR, (*it)->storedPrototype(), failureCases);
+ for (WriteBarrier<Structure>* it = prototypeChain->head(); *it; ++it) {
+ addStructureTransitionCheck(
+ (*it)->storedPrototype(), exec->codeBlock(), stubInfo, stubJit, failureCases,
+ scratchGPR);
+ }
}
#if ENABLE(GGC) || ENABLE(WRITE_BARRIER_PROFILING)
@@ -916,6 +954,7 @@ void dfgBuildPutByIdList(ExecState* exec, JSValue baseValue, const Identifier& p
void dfgLinkFor(ExecState* exec, CallLinkInfo& callLinkInfo, CodeBlock* calleeCodeBlock, JSFunction* callee, MacroAssemblerCodePtr codePtr, CodeSpecializationKind kind)
{
CodeBlock* callerCodeBlock = exec->callerFrame()->codeBlock();
+ JSGlobalData* globalData = callerCodeBlock->globalData();
RepatchBuffer repatchBuffer(callerCodeBlock);
@@ -928,17 +967,17 @@ void dfgLinkFor(ExecState* exec, CallLinkInfo& callLinkInfo, CodeBlock* calleeCo
calleeCodeBlock->linkIncomingCall(&callLinkInfo);
if (kind == CodeForCall) {
- repatchBuffer.relink(CodeLocationCall(callLinkInfo.callReturnLocation), operationVirtualCall);
+ repatchBuffer.relink(callLinkInfo.callReturnLocation, globalData->getCTIStub(virtualCallThunkGenerator).code());
return;
}
ASSERT(kind == CodeForConstruct);
- repatchBuffer.relink(CodeLocationCall(callLinkInfo.callReturnLocation), operationVirtualConstruct);
+ repatchBuffer.relink(callLinkInfo.callReturnLocation, globalData->getCTIStub(virtualConstructThunkGenerator).code());
}
void dfgResetGetByID(RepatchBuffer& repatchBuffer, StructureStubInfo& stubInfo)
{
repatchBuffer.relink(stubInfo.callReturnLocation, operationGetByIdOptimize);
- repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabelPtrAtOffset(-(uintptr_t)stubInfo.patch.dfg.deltaCheckImmToCall), reinterpret_cast<void*>(-1));
+ repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabelPtrAtOffset(-(intptr_t)stubInfo.patch.dfg.deltaCheckImmToCall), reinterpret_cast<void*>(-1));
#if USE(JSVALUE64)
repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabelCompactAtOffset(stubInfo.patch.dfg.deltaCallToLoadOrStore), 0);
#else
@@ -963,7 +1002,7 @@ void dfgResetPutByID(RepatchBuffer& repatchBuffer, StructureStubInfo& stubInfo)
optimizedFunction = operationPutByIdDirectNonStrictOptimize;
}
repatchBuffer.relink(stubInfo.callReturnLocation, optimizedFunction);
- repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabelPtrAtOffset(-(uintptr_t)stubInfo.patch.dfg.deltaCheckImmToCall), reinterpret_cast<void*>(-1));
+ repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabelPtrAtOffset(-(intptr_t)stubInfo.patch.dfg.deltaCheckImmToCall), reinterpret_cast<void*>(-1));
#if USE(JSVALUE64)
repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabel32AtOffset(stubInfo.patch.dfg.deltaCallToLoadOrStore), 0);
#else
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
index 57bc84a12..28d8033cb 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
@@ -1738,7 +1738,8 @@ public:
{
prepareForExternalCall();
CodeOrigin codeOrigin = at(m_compileIndex).codeOrigin;
- CallBeginToken token = m_jit.beginCall();
+ CallBeginToken token;
+ m_jit.beginCall(codeOrigin, token);
JITCompiler::Call call = m_jit.appendCall(function);
m_jit.addExceptionCheck(call, codeOrigin, token);
return call;
@@ -2165,7 +2166,7 @@ public:
// 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)
+ JumpReplacementWatchpoint* speculationWatchpoint(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex)
{
if (!m_compileOkay)
return 0;
@@ -2176,13 +2177,13 @@ public:
m_jit.graph().methodOfGettingAValueProfileFor(nodeIndex),
JITCompiler::Jump(), this, m_stream->size())));
exit.m_watchpointIndex = m_jit.codeBlock()->appendWatchpoint(
- Watchpoint(m_jit.watchpointLabel()));
+ JumpReplacementWatchpoint(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()
+ JumpReplacementWatchpoint* speculationWatchpoint()
{
return speculationWatchpoint(UncountableWatchpoint, JSValueSource(), NoNode);
}
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
index bbbf3c40c..ec2377389 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
@@ -956,14 +956,9 @@ void SpeculativeJIT::nonSpeculativeNonPeepholeStrictEq(Node& node, bool invert)
void SpeculativeJIT::emitCall(Node& node)
{
- P_DFGOperation_E slowCallFunction;
- if (node.op() == Call)
- slowCallFunction = operationLinkCall;
- else {
+ if (node.op() != Call)
ASSERT(node.op() == Construct);
- slowCallFunction = operationLinkConstruct;
- }
// For constructors, the this argument is not passed but we have to make space
// for it.
@@ -1007,16 +1002,18 @@ void SpeculativeJIT::emitCall(Node& node)
JITCompiler::DataLabelPtr targetToCheck;
JITCompiler::JumpList slowPath;
+ CallBeginToken token;
+ m_jit.beginCall(node.codeOrigin, token);
+
+ m_jit.addPtr(TrustedImm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister);
+
slowPath.append(m_jit.branchPtrWithPatch(MacroAssembler::NotEqual, calleePayloadGPR, targetToCheck));
slowPath.append(m_jit.branch32(MacroAssembler::NotEqual, calleeTagGPR, TrustedImm32(JSValue::CellTag)));
m_jit.loadPtr(MacroAssembler::Address(calleePayloadGPR, OBJECT_OFFSETOF(JSFunction, m_scopeChain)), resultPayloadGPR);
- m_jit.storePtr(resultPayloadGPR, callFramePayloadSlot(RegisterFile::ScopeChain));
- m_jit.store32(MacroAssembler::TrustedImm32(JSValue::CellTag), callFrameTagSlot(RegisterFile::ScopeChain));
-
- m_jit.addPtr(TrustedImm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister);
+ m_jit.storePtr(resultPayloadGPR, MacroAssembler::Address(GPRInfo::callFrameRegister, static_cast<ptrdiff_t>(sizeof(Register)) * RegisterFile::ScopeChain + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)));
+ m_jit.store32(MacroAssembler::TrustedImm32(JSValue::CellTag), MacroAssembler::Address(GPRInfo::callFrameRegister, static_cast<ptrdiff_t>(sizeof(Register)) * RegisterFile::ScopeChain + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)));
CodeOrigin codeOrigin = at(m_compileIndex).codeOrigin;
- CallBeginToken token = m_jit.beginCall();
JITCompiler::Call fastCall = m_jit.nearCall();
m_jit.notifyCall(fastCall, codeOrigin, token);
@@ -1024,15 +1021,20 @@ void SpeculativeJIT::emitCall(Node& node)
slowPath.link(&m_jit);
- m_jit.addPtr(TrustedImm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
- m_jit.poke(GPRInfo::argumentGPR0);
- token = m_jit.beginCall();
- JITCompiler::Call slowCall = m_jit.appendCall(slowCallFunction);
- m_jit.addFastExceptionCheck(slowCall, codeOrigin, token);
- m_jit.addPtr(TrustedImm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister);
- token = m_jit.beginCall();
- JITCompiler::Call theCall = m_jit.call(GPRInfo::returnValueGPR);
- m_jit.notifyCall(theCall, codeOrigin, token);
+ if (calleeTagGPR == GPRInfo::nonArgGPR0) {
+ if (calleePayloadGPR == GPRInfo::nonArgGPR1)
+ m_jit.swap(GPRInfo::nonArgGPR1, GPRInfo::nonArgGPR0);
+ else {
+ m_jit.move(calleeTagGPR, GPRInfo::nonArgGPR1);
+ m_jit.move(calleePayloadGPR, GPRInfo::nonArgGPR0);
+ }
+ } else {
+ m_jit.move(calleePayloadGPR, GPRInfo::nonArgGPR0);
+ m_jit.move(calleeTagGPR, GPRInfo::nonArgGPR1);
+ }
+ m_jit.prepareForExceptionCheck();
+ JITCompiler::Call slowCall = m_jit.nearCall();
+ m_jit.notifyCall(slowCall, codeOrigin, token);
done.link(&m_jit);
@@ -2863,7 +2865,7 @@ void SpeculativeJIT::compile(Node& node)
}
case Branch:
- if (isStrictInt32(node.child1().index()) || at(node.child1()).shouldSpeculateInteger()) {
+ if (at(node.child1()).shouldSpeculateInteger()) {
SpeculateIntegerOperand op(this, node.child1());
BlockIndex taken = node.takenBlockIndex();
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
index 27eb28fa7..b5058e35a 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
@@ -953,14 +953,8 @@ void SpeculativeJIT::nonSpeculativeNonPeepholeStrictEq(Node& node, bool invert)
void SpeculativeJIT::emitCall(Node& node)
{
- P_DFGOperation_E slowCallFunction;
-
- if (node.op() == Call)
- slowCallFunction = operationLinkCall;
- else {
+ if (node.op() != Call)
ASSERT(node.op() == Construct);
- slowCallFunction = operationLinkConstruct;
- }
// For constructors, the this argument is not passed but we have to make space
// for it.
@@ -998,14 +992,16 @@ void SpeculativeJIT::emitCall(Node& node)
JITCompiler::DataLabelPtr targetToCheck;
JITCompiler::Jump slowPath;
+ CallBeginToken token;
+ m_jit.beginCall(node.codeOrigin, token);
+
+ m_jit.addPtr(TrustedImm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister);
+
slowPath = m_jit.branchPtrWithPatch(MacroAssembler::NotEqual, calleeGPR, targetToCheck, MacroAssembler::TrustedImmPtr(JSValue::encode(JSValue())));
m_jit.loadPtr(MacroAssembler::Address(calleeGPR, OBJECT_OFFSETOF(JSFunction, m_scopeChain)), resultGPR);
- m_jit.storePtr(resultGPR, callFrameSlot(RegisterFile::ScopeChain));
+ m_jit.storePtr(resultGPR, MacroAssembler::Address(GPRInfo::callFrameRegister, static_cast<ptrdiff_t>(sizeof(Register)) * RegisterFile::ScopeChain));
- m_jit.addPtr(TrustedImm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister);
-
CodeOrigin codeOrigin = at(m_compileIndex).codeOrigin;
- CallBeginToken token = m_jit.beginCall();
JITCompiler::Call fastCall = m_jit.nearCall();
m_jit.notifyCall(fastCall, codeOrigin, token);
@@ -1013,14 +1009,10 @@ void SpeculativeJIT::emitCall(Node& node)
slowPath.link(&m_jit);
- m_jit.addPtr(TrustedImm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
- token = m_jit.beginCall();
- JITCompiler::Call slowCall = m_jit.appendCall(slowCallFunction);
- m_jit.addFastExceptionCheck(slowCall, codeOrigin, token);
- m_jit.addPtr(TrustedImm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister);
- token = m_jit.beginCall();
- JITCompiler::Call theCall = m_jit.call(GPRInfo::returnValueGPR);
- m_jit.notifyCall(theCall, codeOrigin, token);
+ m_jit.move(calleeGPR, GPRInfo::nonArgGPR0);
+ m_jit.prepareForExceptionCheck();
+ JITCompiler::Call slowCall = m_jit.nearCall();
+ m_jit.notifyCall(slowCall, codeOrigin, token);
done.link(&m_jit);
@@ -2947,7 +2939,7 @@ void SpeculativeJIT::compile(Node& node)
}
case Branch:
- if (isStrictInt32(node.child1().index()) || at(node.child1()).shouldSpeculateInteger()) {
+ if (at(node.child1()).shouldSpeculateInteger()) {
SpeculateIntegerOperand op(this, node.child1());
BlockIndex taken = node.takenBlockIndex();
diff --git a/Source/JavaScriptCore/dfg/DFGThunks.cpp b/Source/JavaScriptCore/dfg/DFGThunks.cpp
index 08ca6eaa1..b056de79c 100644
--- a/Source/JavaScriptCore/dfg/DFGThunks.cpp
+++ b/Source/JavaScriptCore/dfg/DFGThunks.cpp
@@ -28,6 +28,7 @@
#if ENABLE(DFG_JIT)
+#include "DFGCCallHelpers.h"
#include "DFGFPRInfo.h"
#include "DFGGPRInfo.h"
#include "DFGOSRExitCompiler.h"
@@ -82,6 +83,217 @@ MacroAssemblerCodeRef osrExitGenerationThunkGenerator(JSGlobalData* globalData)
return FINALIZE_CODE(patchBuffer, ("DFG OSR exit generation thunk"));
}
+inline void emitPointerValidation(CCallHelpers& jit, GPRReg pointerGPR)
+{
+#if !ASSERT_DISABLED
+ CCallHelpers::Jump isNonZero = jit.branchTestPtr(CCallHelpers::NonZero, pointerGPR);
+ jit.breakpoint();
+ isNonZero.link(&jit);
+ jit.push(pointerGPR);
+ jit.load8(pointerGPR, pointerGPR);
+ jit.pop(pointerGPR);
+#else
+ UNUSED_PARAM(jit);
+ UNUSED_PARAM(pointerGPR);
+#endif
+}
+
+MacroAssemblerCodeRef throwExceptionFromCallSlowPathGenerator(JSGlobalData* globalData)
+{
+ CCallHelpers jit(globalData);
+
+ // We will jump to here if the JIT code thinks it's making a call, but the
+ // linking helper (C++ code) decided to throw an exception instead. We will
+ // have saved the callReturnIndex in the first arguments of JITStackFrame.
+ // Note that the return address will be on the stack at this point, so we
+ // need to remove it and drop it on the floor, since we don't care about it.
+ // Finally note that the call frame register points at the callee frame, so
+ // we need to pop it.
+ jit.preserveReturnAddressAfterCall(GPRInfo::nonPreservedNonReturnGPR);
+ jit.loadPtr(
+ CCallHelpers::Address(
+ GPRInfo::callFrameRegister,
+ static_cast<ptrdiff_t>(sizeof(Register)) * RegisterFile::CallerFrame),
+ GPRInfo::callFrameRegister);
+ jit.peek(GPRInfo::nonPreservedNonReturnGPR, JITSTACKFRAME_ARGS_INDEX);
+ jit.setupArgumentsWithExecState(GPRInfo::nonPreservedNonReturnGPR);
+ jit.move(CCallHelpers::TrustedImmPtr(bitwise_cast<void*>(lookupExceptionHandler)), GPRInfo::nonArgGPR0);
+ emitPointerValidation(jit, GPRInfo::nonArgGPR0);
+ jit.call(GPRInfo::nonArgGPR0);
+ emitPointerValidation(jit, GPRInfo::returnValueGPR2);
+ jit.jump(GPRInfo::returnValueGPR2);
+
+ LinkBuffer patchBuffer(*globalData, &jit, GLOBAL_THUNK_ID);
+ return FINALIZE_CODE(patchBuffer, ("DFG throw exception from call slow path thunk"));
+}
+
+static void slowPathFor(
+ CCallHelpers& jit, JSGlobalData* globalData, P_DFGOperation_E slowPathFunction)
+{
+ jit.preserveReturnAddressAfterCall(GPRInfo::nonArgGPR2);
+ emitPointerValidation(jit, GPRInfo::nonArgGPR2);
+ jit.storePtr(
+ GPRInfo::nonArgGPR2,
+ CCallHelpers::Address(
+ GPRInfo::callFrameRegister,
+ static_cast<ptrdiff_t>(sizeof(Register)) * RegisterFile::ReturnPC));
+ jit.storePtr(GPRInfo::callFrameRegister, &globalData->topCallFrame);
+ jit.poke(GPRInfo::nonPreservedNonReturnGPR, JITSTACKFRAME_ARGS_INDEX);
+ jit.setupArgumentsExecState();
+ jit.move(CCallHelpers::TrustedImmPtr(bitwise_cast<void*>(slowPathFunction)), GPRInfo::nonArgGPR0);
+ emitPointerValidation(jit, GPRInfo::nonArgGPR0);
+ jit.call(GPRInfo::nonArgGPR0);
+
+ // This slow call will return the address of one of the following:
+ // 1) Exception throwing thunk.
+ // 2) Host call return value returner thingy.
+ // 3) The function to call.
+ jit.loadPtr(
+ CCallHelpers::Address(
+ GPRInfo::callFrameRegister,
+ static_cast<ptrdiff_t>(sizeof(Register)) * RegisterFile::ReturnPC),
+ GPRInfo::nonPreservedNonReturnGPR);
+ jit.storePtr(
+ CCallHelpers::TrustedImmPtr(0),
+ CCallHelpers::Address(
+ GPRInfo::callFrameRegister,
+ static_cast<ptrdiff_t>(sizeof(Register)) * RegisterFile::ReturnPC));
+ emitPointerValidation(jit, GPRInfo::nonPreservedNonReturnGPR);
+ jit.restoreReturnAddressBeforeReturn(GPRInfo::nonPreservedNonReturnGPR);
+ emitPointerValidation(jit, GPRInfo::returnValueGPR);
+ jit.jump(GPRInfo::returnValueGPR);
+}
+
+static MacroAssemblerCodeRef linkForThunkGenerator(
+ JSGlobalData* globalData, CodeSpecializationKind kind)
+{
+ // The return address is on the stack or in the link register. We will hence
+ // save the return address to the call frame while we make a C++ function call
+ // to perform linking and lazy compilation if necessary. We expect the callee
+ // to be in nonArgGPR0/nonArgGPR1 (payload/tag), the call frame to have already
+ // been adjusted, nonPreservedNonReturnGPR holds the exception handler index,
+ // and all other registers to be available for use. We use JITStackFrame::args
+ // to save important information across calls.
+
+ CCallHelpers jit(globalData);
+
+ slowPathFor(jit, globalData, kind == CodeForCall ? operationLinkCall : operationLinkConstruct);
+
+ LinkBuffer patchBuffer(*globalData, &jit, GLOBAL_THUNK_ID);
+ return FINALIZE_CODE(
+ patchBuffer,
+ ("DFG link %s slow path thunk", kind == CodeForCall ? "call" : "construct"));
+}
+
+MacroAssemblerCodeRef linkCallThunkGenerator(JSGlobalData* globalData)
+{
+ return linkForThunkGenerator(globalData, CodeForCall);
+}
+
+MacroAssemblerCodeRef linkConstructThunkGenerator(JSGlobalData* globalData)
+{
+ return linkForThunkGenerator(globalData, CodeForConstruct);
+}
+
+static MacroAssemblerCodeRef virtualForThunkGenerator(
+ JSGlobalData* globalData, CodeSpecializationKind kind)
+{
+ // The return address is on the stack, or in the link register. We will hence
+ // jump to the callee, or save the return address to the call frame while we
+ // make a C++ function call to the appropriate DFG operation.
+
+ CCallHelpers jit(globalData);
+
+ CCallHelpers::JumpList slowCase;
+
+ // FIXME: we should have a story for eliminating these checks. In many cases,
+ // the DFG knows that the value is definitely a cell, or definitely a function.
+
+#if USE(JSVALUE64)
+ slowCase.append(
+ jit.branchTestPtr(
+ CCallHelpers::NonZero, GPRInfo::nonArgGPR0, GPRInfo::tagMaskRegister));
+#else
+ slowCase.append(
+ jit.branch32(
+ CCallHelpers::NotEqual, GPRInfo::nonArgGPR1,
+ CCallHelpers::TrustedImm32(JSValue::CellTag)));
+#endif
+ slowCase.append(
+ jit.branchPtr(
+ CCallHelpers::NotEqual,
+ CCallHelpers::Address(GPRInfo::nonArgGPR0, JSCell::classInfoOffset()),
+ CCallHelpers::TrustedImmPtr(&JSFunction::s_info)));
+
+ // Now we know we have a JSFunction.
+
+ jit.loadPtr(
+ CCallHelpers::Address(GPRInfo::nonArgGPR0, JSFunction::offsetOfExecutable()),
+ GPRInfo::nonArgGPR2);
+ slowCase.append(
+ jit.branch32(
+ CCallHelpers::LessThan,
+ CCallHelpers::Address(
+ GPRInfo::nonArgGPR2, ExecutableBase::offsetOfNumParametersFor(kind)),
+ CCallHelpers::TrustedImm32(0)));
+
+ // Now we know that we have a CodeBlock, and we're committed to making a fast
+ // call.
+
+ jit.loadPtr(
+ CCallHelpers::Address(GPRInfo::nonArgGPR0, JSFunction::offsetOfScopeChain()),
+ GPRInfo::nonArgGPR1);
+#if USE(JSVALUE64)
+ jit.storePtr(
+ GPRInfo::nonArgGPR1,
+ CCallHelpers::Address(
+ GPRInfo::callFrameRegister,
+ static_cast<ptrdiff_t>(sizeof(Register)) * RegisterFile::ScopeChain));
+#else
+ jit.storePtr(
+ GPRInfo::nonArgGPR1,
+ CCallHelpers::Address(
+ GPRInfo::callFrameRegister,
+ static_cast<ptrdiff_t>(sizeof(Register)) * RegisterFile::ScopeChain +
+ OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)));
+ jit.store32(
+ CCallHelpers::TrustedImm32(JSValue::CellTag),
+ CCallHelpers::Address(
+ GPRInfo::callFrameRegister,
+ static_cast<ptrdiff_t>(sizeof(Register)) * RegisterFile::ScopeChain +
+ OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)));
+#endif
+
+ jit.loadPtr(
+ CCallHelpers::Address(GPRInfo::nonArgGPR2, ExecutableBase::offsetOfJITCodeWithArityCheckFor(kind)),
+ GPRInfo::regT0);
+
+ // Make a tail call. This will return back to DFG code.
+ emitPointerValidation(jit, GPRInfo::regT0);
+ jit.jump(GPRInfo::regT0);
+
+ slowCase.link(&jit);
+
+ // Here we don't know anything, so revert to the full slow path.
+
+ slowPathFor(jit, globalData, kind == CodeForCall ? operationVirtualCall : operationVirtualConstruct);
+
+ LinkBuffer patchBuffer(*globalData, &jit, GLOBAL_THUNK_ID);
+ return FINALIZE_CODE(
+ patchBuffer,
+ ("DFG virtual %s slow path thunk", kind == CodeForCall ? "call" : "construct"));
+}
+
+MacroAssemblerCodeRef virtualCallThunkGenerator(JSGlobalData* globalData)
+{
+ return virtualForThunkGenerator(globalData, CodeForCall);
+}
+
+MacroAssemblerCodeRef virtualConstructThunkGenerator(JSGlobalData* globalData)
+{
+ return virtualForThunkGenerator(globalData, CodeForConstruct);
+}
+
} } // namespace JSC::DFG
#endif // ENABLE(DFG_JIT)
diff --git a/Source/JavaScriptCore/dfg/DFGThunks.h b/Source/JavaScriptCore/dfg/DFGThunks.h
index 3db62442a..11a06d107 100644
--- a/Source/JavaScriptCore/dfg/DFGThunks.h
+++ b/Source/JavaScriptCore/dfg/DFGThunks.h
@@ -40,6 +40,14 @@ namespace DFG {
MacroAssemblerCodeRef osrExitGenerationThunkGenerator(JSGlobalData*);
+MacroAssemblerCodeRef throwExceptionFromCallSlowPathGenerator(JSGlobalData*);
+
+MacroAssemblerCodeRef linkCallThunkGenerator(JSGlobalData*);
+MacroAssemblerCodeRef linkConstructThunkGenerator(JSGlobalData*);
+
+MacroAssemblerCodeRef virtualCallThunkGenerator(JSGlobalData*);
+MacroAssemblerCodeRef virtualConstructThunkGenerator(JSGlobalData*);
+
} } // namespace JSC::DFG
#endif // ENABLE(DFG_JIT)
diff --git a/Source/JavaScriptCore/dfg/DFGVariableEventStream.cpp b/Source/JavaScriptCore/dfg/DFGVariableEventStream.cpp
index 5d548a755..a1152bc2b 100644
--- a/Source/JavaScriptCore/dfg/DFGVariableEventStream.cpp
+++ b/Source/JavaScriptCore/dfg/DFGVariableEventStream.cpp
@@ -102,6 +102,10 @@ void VariableEventStream::reconstruct(
while (at(startIndex).kind() != Reset)
startIndex--;
+#if DFG_ENABLE(DEBUG_VERBOSE)
+ dataLog("Computing OSR exit recoveries starting at seq#%u.\n", startIndex);
+#endif
+
// Step 2: Create a mock-up of the DFG's state and execute the events.
Operands<ValueSource> operandSources(codeBlock->numParameters(), numVariables);
Vector<MinifiedGenerationInfo, 32> generationInfos(graph.originalGraphSize());
diff --git a/Source/JavaScriptCore/heap/HeapTimer.cpp b/Source/JavaScriptCore/heap/HeapTimer.cpp
index ae66f9e26..fa979781e 100644
--- a/Source/JavaScriptCore/heap/HeapTimer.cpp
+++ b/Source/JavaScriptCore/heap/HeapTimer.cpp
@@ -98,8 +98,38 @@ void HeapTimer::timerDidFire(CFRunLoopTimerRef, void* info)
agent->m_shutdownMutex.unlock();
}
+#elif PLATFORM(BLACKBERRY)
+
+HeapTimer::HeapTimer(JSGlobalData* globalData)
+ : m_globalData(globalData)
+ , m_timer(this, &HeapTimer::timerDidFire)
+{
+}
+
+HeapTimer::~HeapTimer()
+{
+}
+
+void HeapTimer::timerDidFire()
+{
+ doWork();
+}
+
+void HeapTimer::synchronize()
+{
+}
+
+void HeapTimer::invalidate()
+{
+}
+
+void HeapTimer::didStartVMShutdown()
+{
+ delete this;
+}
+
#else
-
+
HeapTimer::HeapTimer(JSGlobalData* globalData)
: m_globalData(globalData)
{
diff --git a/Source/JavaScriptCore/heap/HeapTimer.h b/Source/JavaScriptCore/heap/HeapTimer.h
index 9255e0648..88715098a 100644
--- a/Source/JavaScriptCore/heap/HeapTimer.h
+++ b/Source/JavaScriptCore/heap/HeapTimer.h
@@ -31,6 +31,8 @@
#if USE(CF)
#include <CoreFoundation/CoreFoundation.h>
+#elif PLATFORM(BLACKBERRY)
+#include <BlackBerryPlatformTimer.h>
#endif
namespace JSC {
@@ -63,6 +65,10 @@ protected:
CFRunLoopTimerContext m_context;
Mutex m_shutdownMutex;
+#elif PLATFORM(BLACKBERRY)
+ void timerDidFire();
+
+ BlackBerry::Platform::Timer<HeapTimer> m_timer;
#endif
private:
diff --git a/Source/JavaScriptCore/heap/MachineStackMarker.cpp b/Source/JavaScriptCore/heap/MachineStackMarker.cpp
index 8e0c57b6a..7eb57479b 100644
--- a/Source/JavaScriptCore/heap/MachineStackMarker.cpp
+++ b/Source/JavaScriptCore/heap/MachineStackMarker.cpp
@@ -141,8 +141,10 @@ MachineThreads::MachineThreads(Heap* heap)
MachineThreads::~MachineThreads()
{
- if (m_threadSpecific)
- ThreadSpecificKeyDelete(m_threadSpecific);
+ if (m_threadSpecific) {
+ int error = pthread_key_delete(m_threadSpecific);
+ ASSERT_UNUSED(error, !error);
+ }
MutexLocker registeredThreadsLock(m_registeredThreadsMutex);
for (Thread* t = m_registeredThreads; t;) {
@@ -179,17 +181,19 @@ void MachineThreads::makeUsableFromMultipleThreads()
if (m_threadSpecific)
return;
- ThreadSpecificKeyCreate(&m_threadSpecific, removeThread);
+ int error = pthread_key_create(&m_threadSpecific, removeThread);
+ if (error)
+ CRASH();
}
void MachineThreads::addCurrentThread()
{
ASSERT(!m_heap->globalData()->exclusiveThread || m_heap->globalData()->exclusiveThread == currentThread());
- if (!m_threadSpecific || ThreadSpecificGet(m_threadSpecific))
+ if (!m_threadSpecific || pthread_getspecific(m_threadSpecific))
return;
- ThreadSpecificSet(m_threadSpecific, this);
+ pthread_setspecific(m_threadSpecific, this);
Thread* thread = new Thread(getCurrentPlatformThread(), wtfThreadData().stack().origin());
MutexLocker lock(m_registeredThreadsMutex);
diff --git a/Source/JavaScriptCore/heap/MachineStackMarker.h b/Source/JavaScriptCore/heap/MachineStackMarker.h
index 3d4aa22d4..5c7705fcf 100644
--- a/Source/JavaScriptCore/heap/MachineStackMarker.h
+++ b/Source/JavaScriptCore/heap/MachineStackMarker.h
@@ -22,8 +22,8 @@
#ifndef MachineThreads_h
#define MachineThreads_h
+#include <pthread.h>
#include <wtf/Noncopyable.h>
-#include <wtf/ThreadSpecific.h>
#include <wtf/ThreadingPrimitives.h>
namespace JSC {
@@ -55,7 +55,7 @@ namespace JSC {
Heap* m_heap;
Mutex m_registeredThreadsMutex;
Thread* m_registeredThreads;
- WTF::ThreadSpecificKey m_threadSpecific;
+ pthread_key_t m_threadSpecific;
};
} // namespace JSC
diff --git a/Source/JavaScriptCore/jit/JIT.cpp b/Source/JavaScriptCore/jit/JIT.cpp
index 285355f1b..52a7158e6 100644
--- a/Source/JavaScriptCore/jit/JIT.cpp
+++ b/Source/JavaScriptCore/jit/JIT.cpp
@@ -739,7 +739,7 @@ JITCode JIT::privateCompile(CodePtr* functionEntryArityCheck, JITCompilationEffo
CallLinkInfo& info = m_codeBlock->callLinkInfo(i);
info.callType = m_callStructureStubCompilationInfo[i].callType;
info.bytecodeIndex = m_callStructureStubCompilationInfo[i].bytecodeIndex;
- info.callReturnLocation = CodeLocationLabel(patchBuffer.locationOfNearCall(m_callStructureStubCompilationInfo[i].callReturnLocation));
+ info.callReturnLocation = patchBuffer.locationOfNearCall(m_callStructureStubCompilationInfo[i].callReturnLocation);
info.hotPathBegin = patchBuffer.locationOf(m_callStructureStubCompilationInfo[i].hotPathBegin);
info.hotPathOther = patchBuffer.locationOfNearCall(m_callStructureStubCompilationInfo[i].hotPathOther);
}
@@ -802,12 +802,12 @@ void JIT::linkFor(JSFunction* callee, CodeBlock* callerCodeBlock, CodeBlock* cal
// Patch the slow patch so we do not continue to try to link.
if (kind == CodeForCall) {
- repatchBuffer.relink(CodeLocationNearCall(callLinkInfo->callReturnLocation), globalData->jitStubs->ctiVirtualCall());
+ repatchBuffer.relink(callLinkInfo->callReturnLocation, globalData->jitStubs->ctiVirtualCall());
return;
}
ASSERT(kind == CodeForConstruct);
- repatchBuffer.relink(CodeLocationNearCall(callLinkInfo->callReturnLocation), globalData->jitStubs->ctiVirtualConstruct());
+ repatchBuffer.relink(callLinkInfo->callReturnLocation, globalData->jitStubs->ctiVirtualConstruct());
}
} // namespace JSC
diff --git a/Source/JavaScriptCore/jit/JITStubs.cpp b/Source/JavaScriptCore/jit/JITStubs.cpp
index 2273f0f38..bfc4709bc 100644
--- a/Source/JavaScriptCore/jit/JITStubs.cpp
+++ b/Source/JavaScriptCore/jit/JITStubs.cpp
@@ -740,17 +740,20 @@ __asm EncodedJSValue ctiTrampoline(void*, RegisterFile*, CallFrame*, void* /*unu
{
ARM
stmdb sp!, {r1-r3}
- stmdb sp!, {r4-r8, lr}
+ stmdb sp!, {r4-r6, r8-r11, lr}
sub sp, sp, # PRESERVEDR4_OFFSET
- mov r4, r2
- mov r5, #512
+ mov r5, r2
+ mov r6, #512
mov lr, pc
bx r0
add sp, sp, # PRESERVEDR4_OFFSET
- ldmia sp!, {r4-r8, lr}
+ ldmia sp!, {r4-r6, r8-r11, lr}
add sp, sp, #12
bx lr
}
+__asm void ctiTrampolineEnd()
+{
+}
__asm void ctiVMThrowTrampoline()
{
@@ -759,7 +762,7 @@ __asm void ctiVMThrowTrampoline()
mov r0, sp
bl cti_vm_throw
add sp, sp, # PRESERVEDR4_OFFSET
- ldmia sp!, {r4-r8, lr}
+ ldmia sp!, {r4-r6, r8-r11, lr}
add sp, sp, #12
bx lr
}
@@ -1212,31 +1215,32 @@ RVCT()
MSVC_BEGIN( AREA Trampoline, CODE)
MSVC_BEGIN()
MSVC_BEGIN( EXPORT ctiTrampoline)
+MSVC_BEGIN( EXPORT ctiTrampolineEnd)
MSVC_BEGIN( EXPORT ctiVMThrowTrampoline)
MSVC_BEGIN( EXPORT ctiOpThrowNotCaught)
MSVC_BEGIN()
MSVC_BEGIN(ctiTrampoline PROC)
MSVC_BEGIN( stmdb sp!, {r1-r3})
-MSVC_BEGIN( stmdb sp!, {r4-r8, lr})
+MSVC_BEGIN( stmdb sp!, {r4-r6, r8-r11, lr})
MSVC_BEGIN( sub sp, sp, #68 ; sync with PRESERVEDR4_OFFSET)
-MSVC_BEGIN( mov r4, r2)
-MSVC_BEGIN( mov r5, #512)
+MSVC_BEGIN( mov r5, r2)
+MSVC_BEGIN( mov r6, #512)
MSVC_BEGIN( ; r0 contains the code)
MSVC_BEGIN( mov lr, pc)
MSVC_BEGIN( bx r0)
MSVC_BEGIN( add sp, sp, #68 ; sync with PRESERVEDR4_OFFSET)
-MSVC_BEGIN( ldmia sp!, {r4-r8, lr})
+MSVC_BEGIN( ldmia sp!, {r4-r6, r8-r11, lr})
MSVC_BEGIN( add sp, sp, #12)
MSVC_BEGIN( bx lr)
+MSVC_BEGIN(ctiTrampolineEnd)
MSVC_BEGIN(ctiTrampoline ENDP)
MSVC_BEGIN()
MSVC_BEGIN(ctiVMThrowTrampoline PROC)
MSVC_BEGIN( mov r0, sp)
-MSVC_BEGIN( mov lr, pc)
MSVC_BEGIN( bl cti_vm_throw)
MSVC_BEGIN(ctiOpThrowNotCaught)
MSVC_BEGIN( add sp, sp, #68 ; sync with PRESERVEDR4_OFFSET)
-MSVC_BEGIN( ldmia sp!, {r4-r8, lr})
+MSVC_BEGIN( ldmia sp!, {r4-r6, r8-r11, lr})
MSVC_BEGIN( add sp, sp, #12)
MSVC_BEGIN( bx lr)
MSVC_BEGIN(ctiVMThrowTrampoline ENDP)
diff --git a/Source/JavaScriptCore/jit/JumpReplacementWatchpoint.cpp b/Source/JavaScriptCore/jit/JumpReplacementWatchpoint.cpp
new file mode 100644
index 000000000..725108dd5
--- /dev/null
+++ b/Source/JavaScriptCore/jit/JumpReplacementWatchpoint.cpp
@@ -0,0 +1,56 @@
+/*
+ * 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 "JumpReplacementWatchpoint.h"
+
+#if ENABLE(JIT)
+
+#include "LinkBuffer.h"
+
+namespace JSC {
+
+void JumpReplacementWatchpoint::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());
+}
+
+void JumpReplacementWatchpoint::fireInternal()
+{
+ MacroAssembler::replaceWithJump(
+ CodeLocationLabel(bitwise_cast<void*>(m_source)),
+ CodeLocationLabel(bitwise_cast<void*>(m_destination)));
+ if (isOnList())
+ remove();
+}
+
+} // namespace JSC
+
+#endif // ENABLE(JIT)
+
diff --git a/Source/JavaScriptCore/jit/JumpReplacementWatchpoint.h b/Source/JavaScriptCore/jit/JumpReplacementWatchpoint.h
new file mode 100644
index 000000000..b4f35c724
--- /dev/null
+++ b/Source/JavaScriptCore/jit/JumpReplacementWatchpoint.h
@@ -0,0 +1,73 @@
+/*
+ * 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 JumpReplacementWatchpoint_h
+#define JumpReplacementWatchpoint_h
+
+#include "Watchpoint.h"
+#include <wtf/Platform.h>
+
+#if ENABLE(JIT)
+
+#include "CodeLocation.h"
+#include "MacroAssembler.h"
+
+namespace JSC {
+
+class JumpReplacementWatchpoint : public Watchpoint {
+public:
+ JumpReplacementWatchpoint()
+ : m_source(std::numeric_limits<uintptr_t>::max())
+ , m_destination(std::numeric_limits<uintptr_t>::max())
+ {
+ }
+
+ JumpReplacementWatchpoint(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&);
+
+protected:
+ void fireInternal();
+
+private:
+ uintptr_t m_source;
+ uintptr_t m_destination;
+};
+
+} // namespace JSC
+
+#endif // ENABLE(JIT)
+
+#endif // JumpReplacementWatchpoint_h
+
diff --git a/Source/JavaScriptCore/jsc.cpp b/Source/JavaScriptCore/jsc.cpp
index 43337e4ee..5f3dbdb99 100644
--- a/Source/JavaScriptCore/jsc.cpp
+++ b/Source/JavaScriptCore/jsc.cpp
@@ -113,19 +113,23 @@ struct Script {
}
};
-struct CommandLine {
- CommandLine()
- : interactive(false)
- , dump(false)
- , exitCode(false)
+class CommandLine {
+public:
+ CommandLine(int argc, char** argv)
+ : m_interactive(false)
+ , m_dump(false)
+ , m_exitCode(false)
{
+ parseArguments(argc, argv);
}
- bool interactive;
- bool dump;
- bool exitCode;
- Vector<Script> scripts;
- Vector<UString> arguments;
+ bool m_interactive;
+ bool m_dump;
+ bool m_exitCode;
+ Vector<Script> m_scripts;
+ Vector<UString> m_arguments;
+
+ void parseArguments(int, char**);
};
static const char interactivePrompt[] = "> ";
@@ -623,7 +627,7 @@ static NO_RETURN void printUsageStatement(bool help = false)
exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
-static void parseArguments(int argc, char** argv, CommandLine& options)
+void CommandLine::parseArguments(int argc, char** argv)
{
int i = 1;
bool needToDumpOptions = false;
@@ -634,21 +638,21 @@ static void parseArguments(int argc, char** argv, CommandLine& options)
if (!strcmp(arg, "-f")) {
if (++i == argc)
printUsageStatement();
- options.scripts.append(Script(true, argv[i]));
+ m_scripts.append(Script(true, argv[i]));
continue;
}
if (!strcmp(arg, "-e")) {
if (++i == argc)
printUsageStatement();
- options.scripts.append(Script(false, argv[i]));
+ m_scripts.append(Script(false, argv[i]));
continue;
}
if (!strcmp(arg, "-i")) {
- options.interactive = true;
+ m_interactive = true;
continue;
}
if (!strcmp(arg, "-d")) {
- options.dump = true;
+ m_dump = true;
continue;
}
if (!strcmp(arg, "-s")) {
@@ -661,7 +665,7 @@ static void parseArguments(int argc, char** argv, CommandLine& options)
continue;
}
if (!strcmp(arg, "-x")) {
- options.exitCode = true;
+ m_exitCode = true;
continue;
}
if (!strcmp(arg, "--")) {
@@ -690,14 +694,14 @@ static void parseArguments(int argc, char** argv, CommandLine& options)
// This arg is not recognized by the VM nor by jsc. Pass it on to the
// script.
- options.scripts.append(Script(true, argv[i]));
+ m_scripts.append(Script(true, argv[i]));
}
- if (options.scripts.isEmpty())
- options.interactive = true;
+ if (m_scripts.isEmpty())
+ m_interactive = true;
for (; i < argc; ++i)
- options.arguments.append(argv[i]);
+ m_arguments.append(argv[i]);
if (needToDumpOptions)
JSC::Options::dumpAllOptions(stderr);
@@ -707,21 +711,21 @@ static void parseArguments(int argc, char** argv, CommandLine& options)
int jscmain(int argc, char** argv)
{
+ // Note that the options parsing can affect JSGlobalData creation, and thus
+ // comes first.
+ CommandLine options(argc, argv);
RefPtr<JSGlobalData> globalData = JSGlobalData::create(ThreadStackTypeLarge, LargeHeap);
JSLockHolder lock(globalData.get());
int result;
- CommandLine options;
- parseArguments(argc, argv, options);
-
- GlobalObject* globalObject = GlobalObject::create(*globalData, GlobalObject::createStructure(*globalData, jsNull()), options.arguments);
- bool success = runWithScripts(globalObject, options.scripts, options.dump);
- if (options.interactive && success)
+ GlobalObject* globalObject = GlobalObject::create(*globalData, GlobalObject::createStructure(*globalData, jsNull()), options.m_arguments);
+ bool success = runWithScripts(globalObject, options.m_scripts, options.m_dump);
+ if (options.m_interactive && success)
runInteractive(globalObject);
result = success ? 0 : 3;
- if (options.exitCode)
+ if (options.m_exitCode)
printf("jsc exiting %d\n", result);
return result;
diff --git a/Source/JavaScriptCore/llint/LLIntOfflineAsmConfig.h b/Source/JavaScriptCore/llint/LLIntOfflineAsmConfig.h
index 7720f5ec2..9a1539576 100644
--- a/Source/JavaScriptCore/llint/LLIntOfflineAsmConfig.h
+++ b/Source/JavaScriptCore/llint/LLIntOfflineAsmConfig.h
@@ -91,6 +91,10 @@
#define OFFLINE_ASM_VALUE_PROFILER 0
#endif
+// These are for building an interpreter from generated assembly code:
+#define OFFLINE_ASM_BEGIN asm (
+#define OFFLINE_ASM_END );
+
#if CPU(ARM_THUMB2)
#define OFFLINE_ASM_GLOBAL_LABEL(label) \
".globl " SYMBOL_STRING(label) "\n" \
@@ -105,4 +109,6 @@
SYMBOL_STRING(label) ":\n"
#endif
+#define OFFLINE_ASM_LOCAL_LABEL(label) LOCAL_LABEL_STRING(label) ":\n"
+
#endif // LLIntOfflineAsmConfig_h
diff --git a/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm b/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm
index 9d6304de7..513b742ee 100644
--- a/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm
+++ b/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm
@@ -301,8 +301,8 @@ end
_llint_op_enter:
traceExecution()
- loadp CodeBlock[cfr], t2
- loadi CodeBlock::m_numVars[t2], t2
+ loadp CodeBlock[cfr], t2 // t2<CodeBlock> = cfr.CodeBlock
+ loadi CodeBlock::m_numVars[t2], t2 // t2<size_t> = t2<CodeBlock>.m_numVars
btiz t2, .opEnterDone
move UndefinedTag, t0
move 0, t1
diff --git a/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm b/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm
index a7a2ce88f..b976421f0 100644
--- a/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm
+++ b/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm
@@ -182,8 +182,8 @@ end
_llint_op_enter:
traceExecution()
- loadp CodeBlock[cfr], t2
- loadi CodeBlock::m_numVars[t2], t2
+ loadp CodeBlock[cfr], t2 // t2<CodeBlock> = cfr.CodeBlock
+ loadi CodeBlock::m_numVars[t2], t2 // t2<size_t> = t2<CodeBlock>.m_numVars
btiz t2, .opEnterDone
move ValueUndefined, t0
.opEnterLoop:
diff --git a/Source/JavaScriptCore/offlineasm/armv7.rb b/Source/JavaScriptCore/offlineasm/armv7.rb
index 69df51a45..18538120b 100644
--- a/Source/JavaScriptCore/offlineasm/armv7.rb
+++ b/Source/JavaScriptCore/offlineasm/armv7.rb
@@ -21,6 +21,7 @@
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
# THE POSSIBILITY OF SUCH DAMAGE.
+require "config"
require "ast"
require "opt"
@@ -147,6 +148,7 @@ def armV7LowerBranchOps(list)
list.each {
| node |
if node.is_a? Instruction
+ annotation = node.annotation
case node.opcode
when /^b(addi|subi|ori|addp)/
op = $1
@@ -161,17 +163,17 @@ def armV7LowerBranchOps(list)
op = "oris"
end
- newList << Instruction.new(node.codeOrigin, op, node.operands[0..-2])
+ newList << Instruction.new(node.codeOrigin, op, node.operands[0..-2], annotation)
newList << Instruction.new(node.codeOrigin, branch, [node.operands[-1]])
when "bmulio"
tmp1 = Tmp.new(node.codeOrigin, :gpr)
tmp2 = Tmp.new(node.codeOrigin, :gpr)
- newList << Instruction.new(node.codeOrigin, "smulli", [node.operands[0], node.operands[1], node.operands[1], tmp1])
+ newList << Instruction.new(node.codeOrigin, "smulli", [node.operands[0], node.operands[1], node.operands[1], tmp1], annotation)
newList << Instruction.new(node.codeOrigin, "rshifti", [node.operands[-2], Immediate.new(node.codeOrigin, 31), tmp2])
newList << Instruction.new(node.codeOrigin, "bineq", [tmp1, tmp2, node.operands[-1]])
when /^bmuli/
condition = $~.post_match
- newList << Instruction.new(node.codeOrigin, "muli", node.operands[0..-2])
+ newList << Instruction.new(node.codeOrigin, "muli", node.operands[0..-2], annotation)
newList << Instruction.new(node.codeOrigin, "bti" + condition, [node.operands[-2], node.operands[-1]])
else
newList << node
@@ -210,9 +212,9 @@ def armV7LowerShiftOps(list)
case node.opcode
when "lshifti", "rshifti", "urshifti", "lshiftp", "rshiftp", "urshiftp"
if node.operands.size == 2
- newList << Instruction.new(node.codeOrigin, node.opcode, [armV7SanitizeShift(node.operands[0], newList), node.operands[1]])
+ newList << Instruction.new(node.codeOrigin, node.opcode, [armV7SanitizeShift(node.operands[0], newList), node.operands[1]], node.annotation)
else
- newList << Instruction.new(node.codeOrigin, node.opcode, [node.operands[0], armV7SanitizeShift(node.operands[1], newList), node.operands[2]])
+ newList << Instruction.new(node.codeOrigin, node.opcode, [node.operands[0], armV7SanitizeShift(node.operands[1], newList), node.operands[2]], node.annotation)
raise "Wrong number of operands for shift at #{node.codeOriginString}" unless node.operands.size == 3
end
else
@@ -321,9 +323,9 @@ def armV7LowerMalformedAddressesDouble(list)
if node.is_a? Instruction
case node.opcode
when "loadd"
- newList << Instruction.new(node.codeOrigin, "loadd", [node.operands[0].armV7DoubleAddress(newList), node.operands[1]])
+ newList << Instruction.new(node.codeOrigin, "loadd", [node.operands[0].armV7DoubleAddress(newList), node.operands[1]], node.annotation)
when "stored"
- newList << Instruction.new(node.codeOrigin, "stored", [node.operands[0], node.operands[1].armV7DoubleAddress(newList)])
+ newList << Instruction.new(node.codeOrigin, "stored", [node.operands[0], node.operands[1].armV7DoubleAddress(newList)], node.annotation)
else
newList << node
end
@@ -364,7 +366,7 @@ def armV7LowerMisplacedImmediates(list)
newOperands << operand
end
}
- newList << Instruction.new(node.codeOrigin, node.opcode, newOperands)
+ newList << Instruction.new(node.codeOrigin, node.opcode, newOperands, node.annotation)
else
newList << node
end
@@ -431,6 +433,7 @@ def armV7LowerMalformedImmediates(list)
list.each {
| node |
if node.is_a? Instruction
+ annotation = node.annotation
case node.opcode
when "move"
newList << node
@@ -445,14 +448,15 @@ def armV7LowerMalformedImmediates(list)
newOpcode = "add" + node.opcode[-1..-1]
end
newList << Instruction.new(node.codeOrigin, newOpcode,
- [Immediate.new(-node.operands[0].value)] + node.operands[1..-1])
+ [Immediate.new(-node.operands[0].value)] + node.operands[1..-1],
+ annotation)
else
newList << node.armV7LowerMalformedImmediatesRecurse(newList)
end
when "muli", "mulp"
if node.operands[0].is_a? Immediate
tmp = Tmp.new(codeOrigin, :gpr)
- newList << Instruction.new(node.codeOrigin, "move", [node.operands[0], tmp])
+ newList << Instruction.new(node.codeOrigin, "move", [node.operands[0], tmp], annotation)
newList << Instruction.new(node.codeOrigin, "muli", [tmp] + node.operands[1..-1])
else
newList << node.armV7LowerMalformedImmediatesRecurse(newList)
@@ -514,30 +518,36 @@ def armV7LowerMisplacedAddresses(list)
| node |
if node.is_a? Instruction
postInstructions = []
+ annotation = node.annotation
case node.opcode
when "addi", "addp", "addis", "andi", "andp", "lshifti", "lshiftp", "muli", "mulp", "negi",
"negp", "noti", "ori", "oris", "orp", "rshifti", "urshifti", "rshiftp", "urshiftp", "subi",
"subp", "subis", "xori", "xorp", /^bi/, /^bp/, /^bti/, /^btp/, /^ci/, /^cp/, /^ti/
newList << Instruction.new(node.codeOrigin,
node.opcode,
- armV7AsRegisters(newList, postInstructions, node.operands, "i"))
+ armV7AsRegisters(newList, postInstructions, node.operands, "i"),
+ annotation)
when "bbeq", "bbneq", "bba", "bbaeq", "bbb", "bbbeq", "btbo", "btbz", "btbnz", "tbz", "tbnz",
"tbo", "cbeq", "cbneq", "cba", "cbaeq", "cbb", "cbbeq"
newList << Instruction.new(node.codeOrigin,
node.opcode,
- armV7AsRegisters(newList, postInstructions, node.operands, "b"))
+ armV7AsRegisters(newList, postInstructions, node.operands, "b"),
+ annotation)
when "bbgt", "bbgteq", "bblt", "bblteq", "btbs", "tbs", "cbgt", "cbgteq", "cblt", "cblteq"
newList << Instruction.new(node.codeOrigin,
node.opcode,
- armV7AsRegisters(newList, postInstructions, node.operands, "bs"))
+ armV7AsRegisters(newList, postInstructions, node.operands, "bs"),
+ annotation)
when "addd", "divd", "subd", "muld", "sqrtd", /^bd/
newList << Instruction.new(node.codeOrigin,
node.opcode,
- armV7AsRegisters(newList, postInstructions, node.operands, "d"))
+ armV7AsRegisters(newList, postInstructions, node.operands, "d"),
+ annotation)
when "jmp", "call"
newList << Instruction.new(node.codeOrigin,
node.opcode,
- [armV7AsRegister(newList, postInstructions, node.operands[0], "p", false)])
+ [armV7AsRegister(newList, postInstructions, node.operands[0], "p", false)],
+ annotation)
else
newList << node
end
@@ -565,6 +575,7 @@ def armV7LowerRegisterReuse(list)
list.each {
| node |
if node.is_a? Instruction
+ annotation = node.annotation
case node.opcode
when "cieq", "cineq", "cia", "ciaeq", "cib", "cibeq", "cigt", "cigteq", "cilt", "cilteq",
"cpeq", "cpneq", "cpa", "cpaeq", "cpb", "cpbeq", "cpgt", "cpgteq", "cplt", "cplteq",
@@ -573,7 +584,7 @@ def armV7LowerRegisterReuse(list)
if node.operands.size == 2
if node.operands[0] == node.operands[1]
tmp = Tmp.new(node.codeOrigin, :gpr)
- newList << Instruction.new(node.codeOrigin, "move", [node.operands[0], tmp])
+ newList << Instruction.new(node.codeOrigin, "move", [node.operands[0], tmp], annotation)
newList << Instruction.new(node.codeOrigin, node.opcode, [tmp, node.operands[1]])
else
newList << node
@@ -582,11 +593,11 @@ def armV7LowerRegisterReuse(list)
raise "Wrong number of arguments at #{node.codeOriginString}" unless node.operands.size == 3
if node.operands[0] == node.operands[2]
tmp = Tmp.new(node.codeOrigin, :gpr)
- newList << Instruction.new(node.codeOrigin, "move", [node.operands[0], tmp])
+ newList << Instruction.new(node.codeOrigin, "move", [node.operands[0], tmp], annotation)
newList << Instruction.new(node.codeOrigin, node.opcode, [tmp, node.operands[1], node.operands[2]])
elsif node.operands[1] == node.operands[2]
tmp = Tmp.new(node.codeOrigin, :gpr)
- newList << Instruction.new(node.codeOrigin, "move", [node.operands[1], tmp])
+ newList << Instruction.new(node.codeOrigin, "move", [node.operands[1], tmp], annotation)
newList << Instruction.new(node.codeOrigin, node.opcode, [node.operands[0], tmp, node.operands[2]])
else
newList << node
@@ -732,7 +743,9 @@ end
class Instruction
def lowerARMv7
- $asm.comment codeOriginString
+ $asm.codeOrigin codeOriginString
+ $asm.annotation annotation
+
case opcode
when "addi", "addp", "addis"
if opcode == "addis"
diff --git a/Source/JavaScriptCore/offlineasm/asm.rb b/Source/JavaScriptCore/offlineasm/asm.rb
index 50f9bc886..0cf6320af 100644
--- a/Source/JavaScriptCore/offlineasm/asm.rb
+++ b/Source/JavaScriptCore/offlineasm/asm.rb
@@ -25,6 +25,7 @@
$: << File.dirname(__FILE__)
+require "config"
require "backends"
require "digest/sha1"
require "offsets"
@@ -39,16 +40,21 @@ class Assembler
@state = :cpp
@commentState = :none
@comment = nil
+ @internalComment = nil
+ @annotation = nil
+ @codeOrigin = nil
+ @numLocalLabels = 0
+ @numGlobalLabels = 0
end
def enterAsm
- @outp.puts "asm ("
+ @outp.puts "OFFLINE_ASM_BEGIN"
@state = :asm
end
def leaveAsm
putsLastComment
- @outp.puts ");"
+ @outp.puts "OFFLINE_ASM_END"
@state = :cpp
end
@@ -58,17 +64,35 @@ class Assembler
leaveAsm
end
+ # Concatenates all the various components of the comment to dump.
def lastComment
- if @comment
- result = "// #{@comment}"
- else
- result = ""
+ result = ""
+ result = " #{@comment} ." if @comment
+ result += " #{@annotation} ." if @annotation and $enableTrailingInstrAnnotations
+ result += " #{@internalComment} ." if @internalComment
+ result += " #{@codeOrigin} ." if @codeOrigin and $enableCodeOriginComments
+ if result != ""
+ result = " //" + result
end
+
+ # Reset all the components that we've just sent to be dumped.
@commentState = :none
@comment = nil
+ @internalComment = nil
+ @annotation = nil
+ @codeOrigin = nil
result
end
+ # Dumps the current instruction annotation in interlaced mode if appropriate.
+ def putInterlacedAnnotation()
+ raise unless @state == :asm
+ if $enableInterlacedInstrAnnotations
+ @outp.puts(" // #{@annotation}") if @annotation
+ @annotation = nil
+ end
+ end
+
def putsLastComment
comment = lastComment
unless comment.empty?
@@ -78,7 +102,8 @@ class Assembler
def puts(*line)
raise unless @state == :asm
- @outp.puts("\"\\t" + line.join('') + "\\n\" #{lastComment}")
+ putInterlacedAnnotation
+ @outp.puts(" \"\\t" + line.join('') + "\\n\"#{lastComment}")
end
def print(line)
@@ -88,12 +113,18 @@ class Assembler
def putsLabel(labelName)
raise unless @state == :asm
- @outp.puts("OFFLINE_ASM_GLOBAL_LABEL(#{labelName}) #{lastComment}")
+ @numGlobalLabels += 1
+ @outp.puts("\n")
+ @internalComment = $enableLabelCountComments ? "Global Label #{@numGlobalLabels}" : nil
+ @outp.puts("OFFLINE_ASM_GLOBAL_LABEL(#{labelName})#{lastComment}")
end
def putsLocalLabel(labelName)
raise unless @state == :asm
- @outp.puts("LOCAL_LABEL_STRING(#{labelName}) \":\\n\" #{lastComment}")
+ @numLocalLabels += 1
+ @outp.puts("\n")
+ @internalComment = $enableLabelCountComments ? "Local Label #{@numLocalLabels}" : nil
+ @outp.puts("OFFLINE_ASM_LOCAL_LABEL(#{labelName})#{lastComment}")
end
def self.labelReference(labelName)
@@ -104,22 +135,31 @@ class Assembler
"\" LOCAL_LABEL_STRING(#{labelName}) \""
end
- def comment(text)
+ def codeOrigin(text)
case @commentState
when :none
- @comment = text
+ @codeOrigin = text
@commentState = :one
when :one
- @outp.puts "// #{@comment}"
- @outp.puts "// #{text}"
- @comment = nil
+ if $enableCodeOriginComments
+ @outp.puts " // #{@codeOrigin}"
+ @outp.puts " // #{text}"
+ end
+ @codeOrigin = nil
@commentState = :many
when :many
- @outp.puts "// #{text}"
+ @outp.puts "// #{text}" if $enableCodeOriginComments
else
raise
end
end
+
+ def comment(text)
+ @comment = text
+ end
+ def annotation(text)
+ @annotation = text
+ end
end
asmFile = ARGV.shift
diff --git a/Source/JavaScriptCore/offlineasm/ast.rb b/Source/JavaScriptCore/offlineasm/ast.rb
index e555b5d98..86ad6bcb2 100644
--- a/Source/JavaScriptCore/offlineasm/ast.rb
+++ b/Source/JavaScriptCore/offlineasm/ast.rb
@@ -21,6 +21,8 @@
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
# THE POSSIBILITY OF SUCH DAMAGE.
+require "config"
+
#
# Base utility types for the AST.
#
@@ -784,12 +786,13 @@ class AbsoluteAddress < NoChildren
end
class Instruction < Node
- attr_reader :opcode, :operands
+ attr_reader :opcode, :operands, :annotation
- def initialize(codeOrigin, opcode, operands)
+ def initialize(codeOrigin, opcode, operands, annotation=nil)
super(codeOrigin)
@opcode = opcode
@operands = operands
+ @annotation = annotation
end
def children
@@ -797,7 +800,7 @@ class Instruction < Node
end
def mapChildren(&proc)
- Instruction.new(codeOrigin, @opcode, @operands.map(&proc))
+ Instruction.new(codeOrigin, @opcode, @operands.map(&proc), @annotation)
end
def dump
diff --git a/Source/JavaScriptCore/offlineasm/backends.rb b/Source/JavaScriptCore/offlineasm/backends.rb
index db7a1e218..e33a2a083 100644
--- a/Source/JavaScriptCore/offlineasm/backends.rb
+++ b/Source/JavaScriptCore/offlineasm/backends.rb
@@ -21,6 +21,7 @@
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
# THE POSSIBILITY OF SUCH DAMAGE.
+require "config"
require "armv7"
require "ast"
require "x86"
diff --git a/Source/JavaScriptCore/offlineasm/config.rb b/Source/JavaScriptCore/offlineasm/config.rb
new file mode 100644
index 000000000..ce1898170
--- /dev/null
+++ b/Source/JavaScriptCore/offlineasm/config.rb
@@ -0,0 +1,76 @@
+# 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. AND ITS CONTRIBUTORS ``AS IS''
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+# THE POSSIBILITY OF SUCH DAMAGE.
+
+
+# Turns on dumping of the count of labels.
+# For example, the output will look like this:
+#
+# ...
+# OFFLINE_ASM_LOCAL_LABEL(_offlineasm_4_functionArityCheck__continue) // Local Label 24 .
+# ...
+# OFFLINE_ASM_GLOBAL_LABEL(llint_op_enter) // Global Label 8 .
+# ...
+#
+$enableLabelCountComments = false
+
+# Turns on dumping of source file and line numbers in the output file.
+# For example, the output will look like this:
+#
+# ...
+# "\tmovq -8(%r13), %rcx\n" // JavaScriptCore/llint/LowLevelInterpreter64.asm:185
+# "\tmovl 52(%rcx), %ecx\n" // JavaScriptCore/llint/LowLevelInterpreter64.asm:186
+# ...
+#
+$enableCodeOriginComments = true
+
+# Turns on recording and dumping of annotations in the generated output file.
+# An annotations can be specified for each instruction in the source asm files.
+#
+# $enableInterlacedInstrAnnotations will interlace the annotation between
+# instructions. For example, the output will look like this:
+#
+# ...
+# // @ t2<CodeBlock> = cfr.CodeBlock
+# "\tmovq -8(%r13), %rcx\n"
+# // @ t2<size_t> = t2<CodeBlock>.m_numVars
+# "\tmovl 52(%rcx), %ecx\n"
+# ...
+#
+# $enableTrailingInstrAnnotations will insert the annotation in the trailing
+# comment after your instructions. For example, the output will look like this:
+#
+# ...
+# "\tmovq -8(%r13), %rcx\n" // @ t2<CodeBlock> = cfr.CodeBlock
+# "\tmovl 52(%rcx), %ecx\n" // @ t2<size_t> = t2<CodeBlock>.m_numVars
+# ...
+#
+# If both $enableInterlacedInstrAnnotations and $enableTrailingInstrAnnotations
+# are enabled, interlaced annotations will take precedence, and any available
+# annotations will only be dumped in the interlaced format.
+#
+$enableInterlacedInstrAnnotations = false
+$enableTrailingInstrAnnotations = false
+
+
+# Sanity check for annotation configs.
+$enableInstrAnnotations = ($enableInterlacedInstrAnnotations or $enableTrailingInstrAnnotations)
diff --git a/Source/JavaScriptCore/offlineasm/generate_offset_extractor.rb b/Source/JavaScriptCore/offlineasm/generate_offset_extractor.rb
index b2a8c2c83..fefbb1290 100644
--- a/Source/JavaScriptCore/offlineasm/generate_offset_extractor.rb
+++ b/Source/JavaScriptCore/offlineasm/generate_offset_extractor.rb
@@ -25,6 +25,7 @@
$: << File.dirname(__FILE__)
+require "config"
require "backends"
require "digest/sha1"
require "offsets"
diff --git a/Source/JavaScriptCore/offlineasm/instructions.rb b/Source/JavaScriptCore/offlineasm/instructions.rb
index 67cec6d96..aa1a32393 100644
--- a/Source/JavaScriptCore/offlineasm/instructions.rb
+++ b/Source/JavaScriptCore/offlineasm/instructions.rb
@@ -21,6 +21,8 @@
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
# THE POSSIBILITY OF SUCH DAMAGE.
+require "config"
+
# Interesting invariant, which we take advantage of: branching instructions
# always begin with "b", and no non-branching instructions begin with "b".
# Terminal instructions are "jmp" and "ret".
diff --git a/Source/JavaScriptCore/offlineasm/offsets.rb b/Source/JavaScriptCore/offlineasm/offsets.rb
index 4f2734f86..8a064a216 100644
--- a/Source/JavaScriptCore/offlineasm/offsets.rb
+++ b/Source/JavaScriptCore/offlineasm/offsets.rb
@@ -21,6 +21,7 @@
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
# THE POSSIBILITY OF SUCH DAMAGE.
+require "config"
require "ast"
def to32Bit(value)
diff --git a/Source/JavaScriptCore/offlineasm/opt.rb b/Source/JavaScriptCore/offlineasm/opt.rb
index 3170d3ae1..c721758f7 100644
--- a/Source/JavaScriptCore/offlineasm/opt.rb
+++ b/Source/JavaScriptCore/offlineasm/opt.rb
@@ -21,6 +21,7 @@
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
# THE POSSIBILITY OF SUCH DAMAGE.
+require "config"
require "ast"
#
diff --git a/Source/JavaScriptCore/offlineasm/parser.rb b/Source/JavaScriptCore/offlineasm/parser.rb
index 11863c724..8696a61a9 100644
--- a/Source/JavaScriptCore/offlineasm/parser.rb
+++ b/Source/JavaScriptCore/offlineasm/parser.rb
@@ -21,6 +21,7 @@
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
# THE POSSIBILITY OF SUCH DAMAGE.
+require "config"
require "ast"
require "instructions"
require "pathname"
@@ -81,11 +82,20 @@ def lex(str, fileName)
fileName = Pathname.new(fileName)
result = []
lineNumber = 1
+ annotation = nil
while not str.empty?
case str
when /\A\#([^\n]*)/
# comment, ignore
+ when /\A\/\/([^\n]*)/
+ # annotation
+ annotation = $1
when /\A\n/
+ # We've found a '\n'. Emit the last comment recorded if appropriate:
+ if $enableInstrAnnotations and annotation
+ result << Token.new(CodeOrigin.new(fileName, lineNumber), "@" + annotation)
+ annotation = nil
+ end
result << Token.new(CodeOrigin.new(fileName, lineNumber), $&)
lineNumber += 1
when /\A[a-zA-Z]([a-zA-Z0-9_]*)/
@@ -136,6 +146,10 @@ def isIdentifier(token)
token =~ /\A[a-zA-Z]([a-zA-Z0-9_]*)\Z/ and not isKeyword(token)
end
+def isAnnotation(token)
+ token =~ /\A\@([^\n]*)/
+end
+
def isLabel(token)
token =~ /\A_([a-zA-Z0-9_]*)\Z/
end
@@ -535,6 +549,10 @@ class Parser
# Zero operand instruction, and it's the last one.
list << Instruction.new(codeOrigin, name, [])
break
+ elsif isAnnotation @tokens[@idx]
+ annotation = @tokens[@idx].string
+ list << Instruction.new(codeOrigin, name, [], annotation)
+ @idx += 2 # Consume the newline as well.
elsif @tokens[@idx] == "\n"
# Zero operand instruction.
list << Instruction.new(codeOrigin, name, [])
@@ -543,6 +561,7 @@ class Parser
# It's definitely an instruction, and it has at least one operand.
operands = []
endOfSequence = false
+ annotation = nil
loop {
operands << parseOperand("while inside of instruction #{name}")
if (not final and @idx == @tokens.size) or (final and @tokens[@idx] =~ final)
@@ -552,6 +571,10 @@ class Parser
elsif @tokens[@idx] == ","
# Has another operand.
@idx += 1
+ elsif isAnnotation @tokens[@idx]
+ annotation = @tokens[@idx].string
+ @idx += 2 # Consume the newline as well.
+ break
elsif @tokens[@idx] == "\n"
# The end of the instruction.
@idx += 1
@@ -560,7 +583,7 @@ class Parser
parseError("Expected a comma, newline, or #{final} after #{operands.last.dump}")
end
}
- list << Instruction.new(codeOrigin, name, operands)
+ list << Instruction.new(codeOrigin, name, operands, annotation)
if endOfSequence
break
end
diff --git a/Source/JavaScriptCore/offlineasm/registers.rb b/Source/JavaScriptCore/offlineasm/registers.rb
index 2c5a4ebf6..f062ae6a5 100644
--- a/Source/JavaScriptCore/offlineasm/registers.rb
+++ b/Source/JavaScriptCore/offlineasm/registers.rb
@@ -21,6 +21,8 @@
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
# THE POSSIBILITY OF SUCH DAMAGE.
+require "config"
+
GPRS =
[
"t0",
diff --git a/Source/JavaScriptCore/offlineasm/self_hash.rb b/Source/JavaScriptCore/offlineasm/self_hash.rb
index 2c300fccc..b91057391 100644
--- a/Source/JavaScriptCore/offlineasm/self_hash.rb
+++ b/Source/JavaScriptCore/offlineasm/self_hash.rb
@@ -21,6 +21,7 @@
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
# THE POSSIBILITY OF SUCH DAMAGE.
+require "config"
require "digest/sha1"
require "pathname"
diff --git a/Source/JavaScriptCore/offlineasm/settings.rb b/Source/JavaScriptCore/offlineasm/settings.rb
index b7daa7492..601934f99 100644
--- a/Source/JavaScriptCore/offlineasm/settings.rb
+++ b/Source/JavaScriptCore/offlineasm/settings.rb
@@ -21,6 +21,7 @@
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
# THE POSSIBILITY OF SUCH DAMAGE.
+require "config"
require "ast"
require "backends"
require "parser"
diff --git a/Source/JavaScriptCore/offlineasm/transform.rb b/Source/JavaScriptCore/offlineasm/transform.rb
index 86c72be67..a47ea0ad6 100644
--- a/Source/JavaScriptCore/offlineasm/transform.rb
+++ b/Source/JavaScriptCore/offlineasm/transform.rb
@@ -21,6 +21,7 @@
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
# THE POSSIBILITY OF SUCH DAMAGE.
+require "config"
require "ast"
#
diff --git a/Source/JavaScriptCore/offlineasm/x86.rb b/Source/JavaScriptCore/offlineasm/x86.rb
index 383526b25..470318a09 100644
--- a/Source/JavaScriptCore/offlineasm/x86.rb
+++ b/Source/JavaScriptCore/offlineasm/x86.rb
@@ -21,6 +21,8 @@
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
# THE POSSIBILITY OF SUCH DAMAGE.
+require "config"
+
def isX64
case $activeBackend
when "X86"
@@ -353,7 +355,7 @@ class Sequence
operand
end
}
- newNode = Instruction.new(node.codeOrigin, node.opcode, newOperands)
+ newNode = Instruction.new(node.codeOrigin, node.opcode, newOperands, node.annotation)
end
else
unless node.is_a? Label or
@@ -622,7 +624,9 @@ class Instruction
end
def lowerX86Common
- $asm.comment codeOriginString
+ $asm.codeOrigin codeOriginString
+ $asm.annotation annotation
+
case opcode
when "addi"
handleX86Add(:int)
diff --git a/Source/JavaScriptCore/runtime/Executable.h b/Source/JavaScriptCore/runtime/Executable.h
index e5f6de438..2f6c6a253 100644
--- a/Source/JavaScriptCore/runtime/Executable.h
+++ b/Source/JavaScriptCore/runtime/Executable.h
@@ -176,6 +176,30 @@ namespace JSC {
return intrinsic();
return NoIntrinsic;
}
+
+ static ptrdiff_t offsetOfJITCodeFor(CodeSpecializationKind kind)
+ {
+ if (kind == CodeForCall)
+ return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForCall);
+ ASSERT(kind == CodeForConstruct);
+ return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForConstruct);
+ }
+
+ static ptrdiff_t offsetOfJITCodeWithArityCheckFor(CodeSpecializationKind kind)
+ {
+ if (kind == CodeForCall)
+ return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForCallWithArityCheck);
+ ASSERT(kind == CodeForConstruct);
+ return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForConstructWithArityCheck);
+ }
+
+ static ptrdiff_t offsetOfNumParametersFor(CodeSpecializationKind kind)
+ {
+ if (kind == CodeForCall)
+ return OBJECT_OFFSETOF(ExecutableBase, m_numParametersForCall);
+ ASSERT(kind == CodeForConstruct);
+ return OBJECT_OFFSETOF(ExecutableBase, m_numParametersForConstruct);
+ }
#endif
protected:
diff --git a/Source/JavaScriptCore/runtime/GCActivityCallbackBlackBerry.cpp b/Source/JavaScriptCore/runtime/GCActivityCallbackBlackBerry.cpp
index 3b0b5a751..d9f96fa1e 100644
--- a/Source/JavaScriptCore/runtime/GCActivityCallbackBlackBerry.cpp
+++ b/Source/JavaScriptCore/runtime/GCActivityCallbackBlackBerry.cpp
@@ -20,39 +20,40 @@
#include "GCActivityCallback.h"
#include "Heap.h"
+#include "JSGlobalData.h"
#include <BlackBerryPlatformMemory.h>
namespace JSC {
+static const size_t bytesWorthGC = 4 * 1024 * 1024;
+
DefaultGCActivityCallback::DefaultGCActivityCallback(Heap* heap)
: GCActivityCallback(heap->globalData())
{
}
-DefaultGCActivityCallback::doWork()
+void DefaultGCActivityCallback::doWork()
{
+ m_globalData->heap.collect(Heap::DoNotSweep);
}
void DefaultGCActivityCallback::didAllocate(size_t bytesAllocated)
{
- if (!BlackBerry::Platform::isMemoryLow())
- return;
-
- if (bytesAllocated < 1 * 1024 * 1024)
+ if (bytesAllocated < bytesWorthGC || m_timer.started())
return;
- if (m_globalData->heap.isBusy() || !m_globalData->heap.isSafeToCollect())
- return;
-
- m_globalData->heap.collect(Heap::DoNotSweep);
+ // Try using ~5% CPU time.
+ m_timer.start(m_globalData->heap.lastGCLength() * 20);
}
void DefaultGCActivityCallback::willCollect()
{
+ cancel();
}
void DefaultGCActivityCallback::cancel()
{
+ m_timer.stop();
}
}
diff --git a/Source/JavaScriptCore/runtime/JSValue.h b/Source/JavaScriptCore/runtime/JSValue.h
index f74bfad90..6f98bd6f7 100644
--- a/Source/JavaScriptCore/runtime/JSValue.h
+++ b/Source/JavaScriptCore/runtime/JSValue.h
@@ -124,6 +124,18 @@ namespace JSC {
friend class LLInt::Data;
public:
+#if USE(JSVALUE32_64)
+ enum { Int32Tag = 0xffffffff };
+ enum { BooleanTag = 0xfffffffe };
+ enum { NullTag = 0xfffffffd };
+ enum { UndefinedTag = 0xfffffffc };
+ enum { CellTag = 0xfffffffb };
+ enum { EmptyValueTag = 0xfffffffa };
+ enum { DeletedValueTag = 0xfffffff9 };
+
+ enum { LowestTag = DeletedValueTag };
+#endif
+
static EncodedJSValue encode(JSValue);
static JSValue decode(EncodedJSValue);
@@ -278,16 +290,6 @@ namespace JSC {
* cell, integer and bool values the lower 32 bits (the 'payload') contain the pointer
* integer or boolean value; in the case of all other tags the payload is 0.
*/
- enum { Int32Tag = 0xffffffff };
- enum { BooleanTag = 0xfffffffe };
- enum { NullTag = 0xfffffffd };
- enum { UndefinedTag = 0xfffffffc };
- enum { CellTag = 0xfffffffb };
- enum { EmptyValueTag = 0xfffffffa };
- enum { DeletedValueTag = 0xfffffff9 };
-
- enum { LowestTag = DeletedValueTag };
-
uint32_t tag() const;
int32_t payload() const;
#elif USE(JSVALUE64)
diff --git a/Source/JavaScriptCore/wscript b/Source/JavaScriptCore/wscript
index 4afb4d26a..2270455c8 100644
--- a/Source/JavaScriptCore/wscript
+++ b/Source/JavaScriptCore/wscript
@@ -33,7 +33,7 @@ def build(bld):
import Options
- jscore_excludes = ['jsc.cpp', 'ExecutableAllocatorPosix.cpp', 'LLIntOffsetsExtractor.cpp']
+ jscore_excludes = ['jsc.cpp', 'ExecutableAllocatorPosix.cpp', 'LLIntOffsetsExtractor.cpp', 'udis86_itab.c']
jscore_exclude_patterns = get_port_excludes(Options.options.port)
jscore_exclude_patterns.append('*None.cpp')
@@ -46,9 +46,6 @@ def build(bld):
else:
jscore_excludes.append('JSStringRefBSTR.cpp')
- if sys.platform.startswith('darwin'):
- jscore_excludes.append('GCActivityCallback.cpp') # this is an empty impl.
-
bld.env.LIBDIR = output_dir
full_dirs = get_dirs_for_features(jscore_dir, features=[Options.options.port.lower()], dirs=jscore_dirs)
abs_dirs = []