summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@nokia.com>2012-08-21 10:57:44 +0200
committerSimon Hausmann <simon.hausmann@nokia.com>2012-08-21 10:57:44 +0200
commit5ef7c8a6a70875d4430752d146bdcb069605d71d (patch)
treef6256640b6c46d7da221435803cae65326817ba2 /Source/JavaScriptCore
parentdecad929f578d8db641febc8740649ca6c574638 (diff)
downloadqtwebkit-5ef7c8a6a70875d4430752d146bdcb069605d71d.tar.gz
Imported WebKit commit 356d83016b090995d08ad568f2d2c243aa55e831 (http://svn.webkit.org/repository/webkit/trunk@126147)
New snapshot including various build fixes for newer Qt 5
Diffstat (limited to 'Source/JavaScriptCore')
-rw-r--r--Source/JavaScriptCore/CMakeLists.txt1
-rw-r--r--Source/JavaScriptCore/ChangeLog840
-rw-r--r--Source/JavaScriptCore/Configurations/FeatureDefines.xcconfig3
-rw-r--r--Source/JavaScriptCore/GNUmakefile.list.am3
-rw-r--r--Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj8
-rwxr-xr-xSource/JavaScriptCore/JavaScriptCore.vcproj/testRegExp/testRegExp.vcproj7
-rw-r--r--Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj12
-rw-r--r--Source/JavaScriptCore/Target.pri2
-rw-r--r--Source/JavaScriptCore/assembler/ARMAssembler.cpp80
-rw-r--r--Source/JavaScriptCore/assembler/ARMAssembler.h154
-rw-r--r--Source/JavaScriptCore/assembler/MacroAssemblerARM.cpp22
-rw-r--r--Source/JavaScriptCore/assembler/MacroAssemblerARM.h246
-rw-r--r--Source/JavaScriptCore/bytecode/ArrayProfile.cpp55
-rw-r--r--Source/JavaScriptCore/bytecode/ArrayProfile.h104
-rw-r--r--Source/JavaScriptCore/bytecode/CodeBlock.cpp116
-rw-r--r--Source/JavaScriptCore/bytecode/CodeBlock.h25
-rw-r--r--Source/JavaScriptCore/bytecode/Instruction.h3
-rw-r--r--Source/JavaScriptCore/bytecode/Opcode.h6
-rw-r--r--Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp17
-rw-r--r--Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h1
-rw-r--r--Source/JavaScriptCore/config.h5
-rw-r--r--Source/JavaScriptCore/dfg/DFGAbstractState.cpp87
-rw-r--r--Source/JavaScriptCore/dfg/DFGAbstractValue.h536
-rw-r--r--Source/JavaScriptCore/dfg/DFGArgumentsSimplificationPhase.cpp24
-rw-r--r--Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp39
-rw-r--r--Source/JavaScriptCore/dfg/DFGCFGSimplificationPhase.cpp4
-rw-r--r--Source/JavaScriptCore/dfg/DFGCSEPhase.cpp13
-rw-r--r--Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp15
-rw-r--r--Source/JavaScriptCore/dfg/DFGDriver.cpp45
-rw-r--r--Source/JavaScriptCore/dfg/DFGDriver.h8
-rw-r--r--Source/JavaScriptCore/dfg/DFGFixupPhase.cpp31
-rw-r--r--Source/JavaScriptCore/dfg/DFGGraph.h83
-rw-r--r--Source/JavaScriptCore/dfg/DFGNode.h22
-rw-r--r--Source/JavaScriptCore/dfg/DFGNodeType.h1
-rw-r--r--Source/JavaScriptCore/dfg/DFGOSREntry.cpp4
-rw-r--r--Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp1
-rw-r--r--Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp84
-rw-r--r--Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h10
-rw-r--r--Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp76
-rw-r--r--Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp60
-rw-r--r--Source/JavaScriptCore/dfg/DFGStructureAbstractValue.h327
-rw-r--r--Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.cpp22
-rw-r--r--Source/JavaScriptCore/interpreter/Interpreter.cpp2
-rw-r--r--Source/JavaScriptCore/jit/JITDriver.h8
-rw-r--r--Source/JavaScriptCore/jit/JITPropertyAccess.cpp18
-rw-r--r--Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp18
-rw-r--r--Source/JavaScriptCore/jit/JITStubs.cpp3
-rw-r--r--Source/JavaScriptCore/llint/LLIntExceptions.cpp11
-rw-r--r--Source/JavaScriptCore/llint/LLIntOffsetsExtractor.cpp1
-rw-r--r--Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm38
-rw-r--r--Source/JavaScriptCore/llint/LowLevelInterpreter64.asm36
-rw-r--r--Source/JavaScriptCore/runtime/Executable.cpp44
-rw-r--r--Source/JavaScriptCore/runtime/Executable.h22
-rw-r--r--Source/JavaScriptCore/runtime/ExecutionHarness.h8
-rw-r--r--Source/JavaScriptCore/runtime/Structure.h5
-rw-r--r--Source/JavaScriptCore/shell/PlatformEfl.cmake2
56 files changed, 2505 insertions, 913 deletions
diff --git a/Source/JavaScriptCore/CMakeLists.txt b/Source/JavaScriptCore/CMakeLists.txt
index 146a11910..317814aa9 100644
--- a/Source/JavaScriptCore/CMakeLists.txt
+++ b/Source/JavaScriptCore/CMakeLists.txt
@@ -39,6 +39,7 @@ SET(JavaScriptCore_SOURCES
assembler/LinkBuffer.cpp
+ bytecode/ArrayProfile.cpp
bytecode/CallLinkInfo.cpp
bytecode/CallLinkStatus.cpp
bytecode/CodeBlock.cpp
diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog
index 063b2f519..4297df1e5 100644
--- a/Source/JavaScriptCore/ChangeLog
+++ b/Source/JavaScriptCore/ChangeLog
@@ -1,3 +1,843 @@
+2012-08-20 Mark Lam <mark.lam@apple.com>
+
+ Fix broken non-JIT build.
+ https://bugs.webkit.org/show_bug.cgi?id=94564.
+
+ Reviewed by Filip Pizlo.
+
+ Added some UNUSED_PARAM() macros to make the compiler happy.
+
+ * runtime/Executable.cpp:
+ (JSC::EvalExecutable::compileInternal):
+ (JSC::ProgramExecutable::compileInternal):
+ (JSC::FunctionExecutable::compileForCallInternal):
+ (JSC::FunctionExecutable::compileForConstructInternal):
+
+2012-08-20 Mark Lam <mark.lam@apple.com>
+
+ Fixed erroneous line number for LLint frame when throwing exceptions.
+ https://bugs.webkit.org/show_bug.cgi?id=94051.
+
+ Reviewed by Filip Pizlo.
+
+ For LLInt frames, before throwing an exception, adjust the PC from the
+ return PC back to the call PC if we are indeed at a call site.
+
+ * bytecode/CodeBlock.cpp:
+ (JSC::CodeBlock::adjustPCIfAtCallSite):
+ (JSC):
+ (JSC::CodeBlock::bytecodeOffset):
+ * bytecode/CodeBlock.h:
+ (CodeBlock):
+ * llint/LLIntExceptions.cpp:
+ (JSC::LLInt::fixupPCforExceptionIfNeeded):
+ (LLInt):
+ (JSC::LLInt::interpreterThrowInCaller):
+ (JSC::LLInt::returnToThrow):
+ (JSC::LLInt::callToThrow):
+
+2012-08-20 Filip Pizlo <fpizlo@apple.com>
+
+ fast/js/dfg-peephole-compare-final-object-to-final-object-or-other-when-both-proven-final-object.html on 32-bit
+ https://bugs.webkit.org/show_bug.cgi?id=94538
+
+ Reviewed by Mark Hahnenberg.
+
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality):
+
+2012-08-20 Filip Pizlo <fpizlo@apple.com>
+
+ fast/js/dfg-compare-final-object-to-final-object-or-other-when-both-proven-final-object.html crashes on 32-bit
+ https://bugs.webkit.org/show_bug.cgi?id=94026
+
+ Reviewed by Mark Hahnenberg.
+
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::compileObjectToObjectOrOtherEquality):
+
+2012-08-19 Filip Pizlo <fpizlo@apple.com>
+
+ The relationship between abstract values and structure transition watchpoints should be rationalized
+ https://bugs.webkit.org/show_bug.cgi?id=94205
+
+ Reviewed by Geoffrey Garen.
+
+ This patch does a number of things related to the handling of the abstract values
+ arrising from values with structures known to be watchpointable:
+
+ - This rationalizes the relationship between the structure that we know an object
+ to have *right now* based on having executed a check against that structure, and
+ the structure that we know the object could have *in the future* based on a type
+ check executed in the past over a structure that was watchpointable.
+
+ - We use the above to assert that structure transition watchpoints are being used
+ soundly.
+
+ - We use the above to strength reduce CheckStructure into StructureTransitionWatchpoint
+ whenever possible.
+
+ - This rationalizes the handling of CFA over constants that appeared in the bytecode.
+ If at compile-time the constant has a watchpointable structure, then we can prove
+ what structures it may have in the future. The analysis uses this to both assert
+ that structure transition watchpoints are being used correctly, and to find
+ opportunities for using them more aggressively.
+
+ The net effect of all of these changes is that OSR entry should work more smoothly.
+ It may also be a slight win due to strength reductions, though most of those strength
+ reductions would have already been done by the parser and the structure check hoister.
+
+ * GNUmakefile.list.am:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * dfg/DFGAbstractState.cpp:
+ (JSC::DFG::AbstractState::beginBasicBlock):
+ (JSC::DFG::AbstractState::execute):
+ * dfg/DFGAbstractValue.h:
+ (DFG):
+ (JSC::DFG::AbstractValue::clear):
+ (JSC::DFG::AbstractValue::isClear):
+ (JSC::DFG::AbstractValue::makeTop):
+ (JSC::DFG::AbstractValue::clobberStructures):
+ (JSC::DFG::AbstractValue::isTop):
+ (JSC::DFG::AbstractValue::setFuturePossibleStructure):
+ (AbstractValue):
+ (JSC::DFG::AbstractValue::filterFuturePossibleStructure):
+ (JSC::DFG::AbstractValue::setMostSpecific):
+ (JSC::DFG::AbstractValue::set):
+ (JSC::DFG::AbstractValue::operator==):
+ (JSC::DFG::AbstractValue::merge):
+ (JSC::DFG::AbstractValue::filter):
+ (JSC::DFG::AbstractValue::filterValueByType):
+ (JSC::DFG::AbstractValue::validateType):
+ (JSC::DFG::AbstractValue::validate):
+ (JSC::DFG::AbstractValue::checkConsistency):
+ (JSC::DFG::AbstractValue::dump):
+ * dfg/DFGArgumentsSimplificationPhase.cpp:
+ (JSC::DFG::ArgumentsSimplificationPhase::run):
+ * dfg/DFGCSEPhase.cpp:
+ (JSC::DFG::CSEPhase::checkStructureLoadElimination):
+ (JSC::DFG::CSEPhase::structureTransitionWatchpointElimination):
+ (JSC::DFG::CSEPhase::performNodeCSE):
+ * dfg/DFGConstantFoldingPhase.cpp:
+ (JSC::DFG::ConstantFoldingPhase::foldConstants):
+ * dfg/DFGNode.h:
+ (JSC::DFG::Node::convertToStructureTransitionWatchpoint):
+ (Node):
+ (JSC::DFG::Node::hasStructure):
+ * dfg/DFGNodeType.h:
+ (DFG):
+ * dfg/DFGOSREntry.cpp:
+ (JSC::DFG::prepareOSREntry):
+ * dfg/DFGPredictionPropagationPhase.cpp:
+ (JSC::DFG::PredictionPropagationPhase::propagate):
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::convertLastOSRExitToForward):
+ (JSC::DFG::SpeculativeJIT::forwardSpeculationWatchpoint):
+ (DFG):
+ (JSC::DFG::SpeculativeJIT::speculationWatchpointWithConditionalDirection):
+ (JSC::DFG::SpeculativeJIT::forwardSpeculationCheck):
+ (JSC::DFG::SpeculativeJIT::speculateArray):
+ * dfg/DFGSpeculativeJIT.h:
+ (SpeculativeJIT):
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGStructureAbstractValue.h: Added.
+ (DFG):
+ (StructureAbstractValue):
+ (JSC::DFG::StructureAbstractValue::StructureAbstractValue):
+ (JSC::DFG::StructureAbstractValue::clear):
+ (JSC::DFG::StructureAbstractValue::makeTop):
+ (JSC::DFG::StructureAbstractValue::top):
+ (JSC::DFG::StructureAbstractValue::add):
+ (JSC::DFG::StructureAbstractValue::addAll):
+ (JSC::DFG::StructureAbstractValue::contains):
+ (JSC::DFG::StructureAbstractValue::isSubsetOf):
+ (JSC::DFG::StructureAbstractValue::doesNotContainAnyOtherThan):
+ (JSC::DFG::StructureAbstractValue::isSupersetOf):
+ (JSC::DFG::StructureAbstractValue::filter):
+ (JSC::DFG::StructureAbstractValue::isClear):
+ (JSC::DFG::StructureAbstractValue::isTop):
+ (JSC::DFG::StructureAbstractValue::isClearOrTop):
+ (JSC::DFG::StructureAbstractValue::isNeitherClearNorTop):
+ (JSC::DFG::StructureAbstractValue::size):
+ (JSC::DFG::StructureAbstractValue::at):
+ (JSC::DFG::StructureAbstractValue::operator[]):
+ (JSC::DFG::StructureAbstractValue::last):
+ (JSC::DFG::StructureAbstractValue::speculationFromStructures):
+ (JSC::DFG::StructureAbstractValue::hasSingleton):
+ (JSC::DFG::StructureAbstractValue::singleton):
+ (JSC::DFG::StructureAbstractValue::operator==):
+ (JSC::DFG::StructureAbstractValue::dump):
+ (JSC::DFG::StructureAbstractValue::topValue):
+ * dfg/DFGStructureCheckHoistingPhase.cpp:
+ (JSC::DFG::StructureCheckHoistingPhase::run):
+
+2012-08-17 Filip Pizlo <fpizlo@apple.com>
+
+ The current state of the call frame should be taken into account in the DFG for both predictions and proofs
+ https://bugs.webkit.org/show_bug.cgi?id=94412
+
+ Reviewed by Geoffrey Garen.
+
+ This ensures that no matter how smart the DFG gets, it'll always know through
+ which entrypoint OSR will try to enter, and with which values it will attempt
+ to do so. For prologue OSR, this has no effect other than adding the current
+ arguments to the argument predictions. For loop OSR, this makes our treatment
+ of the loop slightly more conservative - just conservative enough to ensure
+ that OSR succeeds.
+
+ * bytecode/CodeBlock.cpp:
+ (JSC::ProgramCodeBlock::compileOptimized):
+ (JSC::EvalCodeBlock::compileOptimized):
+ (JSC::FunctionCodeBlock::compileOptimized):
+ * bytecode/CodeBlock.h:
+ (CodeBlock):
+ (ProgramCodeBlock):
+ (EvalCodeBlock):
+ (FunctionCodeBlock):
+ * dfg/DFGAbstractState.cpp:
+ (JSC::DFG::AbstractState::initialize):
+ * dfg/DFGAbstractValue.h:
+ (JSC::DFG::AbstractValue::setMostSpecific):
+ (AbstractValue):
+ * dfg/DFGByteCodeParser.cpp:
+ (JSC::DFG::ByteCodeParser::fixVariableAccessPredictions):
+ (JSC::DFG::ByteCodeParser::parse):
+ * dfg/DFGDriver.cpp:
+ (JSC::DFG::compile):
+ (JSC::DFG::tryCompile):
+ (JSC::DFG::tryCompileFunction):
+ * dfg/DFGDriver.h:
+ (DFG):
+ (JSC::DFG::tryCompile):
+ (JSC::DFG::tryCompileFunction):
+ * dfg/DFGGraph.h:
+ (JSC::DFG::Graph::Graph):
+ (Graph):
+ * jit/JITDriver.h:
+ (JSC::jitCompileIfAppropriate):
+ (JSC::jitCompileFunctionIfAppropriate):
+ * jit/JITStubs.cpp:
+ (JSC::DEFINE_STUB_FUNCTION):
+ * runtime/Executable.cpp:
+ (JSC::EvalExecutable::compileOptimized):
+ (JSC::EvalExecutable::compileInternal):
+ (JSC::ProgramExecutable::compileOptimized):
+ (JSC::ProgramExecutable::compileInternal):
+ (JSC::FunctionExecutable::compileOptimizedForCall):
+ (JSC::FunctionExecutable::compileOptimizedForConstruct):
+ (JSC::FunctionExecutable::compileForCallInternal):
+ (JSC::FunctionExecutable::compileForConstructInternal):
+ * runtime/Executable.h:
+ (EvalExecutable):
+ (ProgramExecutable):
+ (FunctionExecutable):
+ (JSC::FunctionExecutable::compileOptimizedFor):
+ * runtime/ExecutionHarness.h:
+ (JSC::prepareForExecution):
+ (JSC::prepareFunctionForExecution):
+
+2012-08-17 Filip Pizlo <fpizlo@apple.com>
+
+ DFG CSE should be more honest about when it changed the IR
+ https://bugs.webkit.org/show_bug.cgi?id=94408
+
+ Reviewed by Geoffrey Garen.
+
+ The CSE phase now always returns true if it changed the IR.
+
+ * dfg/DFGCSEPhase.cpp:
+ (JSC::DFG::CSEPhase::setReplacement):
+ (JSC::DFG::CSEPhase::eliminate):
+ (JSC::DFG::CSEPhase::performNodeCSE):
+
+2012-08-17 Filip Pizlo <fpizlo@apple.com>
+
+ DFG is still too pessimistic about what constitutes a side-effect on array accesses
+ https://bugs.webkit.org/show_bug.cgi?id=94309
+
+ Reviewed by Geoffrey Garen.
+
+ This change means that even if structure transition watchpoints are not used for
+ hoisting of clobbered structure checks, we still retain good performance on the
+ benchmarks we care about. That's important, since butterflies will likely make
+ most array structures not watchpointable.
+
+ * dfg/DFGAbstractState.cpp:
+ (JSC::DFG::AbstractState::execute):
+ * dfg/DFGStructureCheckHoistingPhase.cpp:
+ (JSC::DFG::StructureCheckHoistingPhase::run):
+
+2012-08-17 Milian Wolff <milian.wolff@kdab.com>
+
+ [Qt] QNX build fails due to ctype usage in system headers
+ https://bugs.webkit.org/show_bug.cgi?id=93849
+
+ Reviewed by Simon Hausmann.
+
+ Move the check for whether DisallowCType should be active or not
+ to the DisallowCType.h header. This way, we can update the list
+ of platforms or OSes which do not work with this header in a
+ central place. All users can now safely include the header
+ and do not need to place custom guards around it.
+
+ * config.h:
+
+2012-08-16 Simon Hausmann <simon.hausmann@nokia.com>
+
+ [Qt] Replace use of internal Weak smart pointer with JSWeakObjectMap
+ https://bugs.webkit.org/show_bug.cgi?id=93872
+
+ Reviewed by Kenneth Rohde Christiansen.
+
+ * Target.pri: Add missing JSWeakObjectMap file to build.
+
+2012-08-16 Filip Pizlo <fpizlo@apple.com>
+
+ Structure check hoisting should be less expensive
+ https://bugs.webkit.org/show_bug.cgi?id=94201
+
+ Reviewed by Mark Hahnenberg.
+
+ This appears like a broad win on short-running programs.
+
+ * dfg/DFGArgumentsSimplificationPhase.cpp:
+ (JSC::DFG::ArgumentsSimplificationPhase::run):
+ * dfg/DFGCSEPhase.cpp:
+ (JSC::DFG::CSEPhase::performNodeCSE):
+ * dfg/DFGDriver.cpp:
+ (JSC::DFG::compile):
+ * dfg/DFGGraph.h:
+ (JSC::DFG::Graph::compareAndSwap):
+ (Graph):
+ (JSC::DFG::Graph::substitute):
+ (JSC::DFG::Graph::substituteGetLocal):
+ * dfg/DFGStructureCheckHoistingPhase.cpp:
+ (JSC::DFG::StructureCheckHoistingPhase::run):
+
+2012-08-16 Filip Pizlo <fpizlo@apple.com>
+
+ All op_resolve_global instructions should end up in the list of global resolve instructions
+ https://bugs.webkit.org/show_bug.cgi?id=94247
+ <rdar://problem/12103500>
+
+ Reviewed by Mark Hahnenberg.
+
+ * bytecompiler/BytecodeGenerator.cpp:
+ (JSC::BytecodeGenerator::emitResolveWithBase):
+
+2012-08-15 Bruno de Oliveira Abinader <bruno.abinader@basyskom.com>
+
+ [css3-text] Add CSS3 Text decoration compile flag
+ https://bugs.webkit.org/show_bug.cgi?id=93863
+
+ Reviewed by Julien Chaffraix.
+
+ This patch handles the compile flag implementation, which will come disabled by
+ default, thus not exposing the CSS3 text decoration features to the web, unless
+ when explicitly enabling it with "--css3-text-decoration" build parameter.
+
+ * Configurations/FeatureDefines.xcconfig:
+
+2012-08-15 Sheriff Bot <webkit.review.bot@gmail.com>
+
+ Unreviewed, rolling out r125687.
+ http://trac.webkit.org/changeset/125687
+ https://bugs.webkit.org/show_bug.cgi?id=94147
+
+ It broke the whole world (Requested by Ossy_night on #webkit).
+
+ * API/JSValueRef.cpp:
+ (JSValueToBoolean):
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def:
+ * bytecode/Watchpoint.h:
+ (WatchpointSet):
+ * debugger/DebuggerCallFrame.h:
+ * dfg/DFGAbstractState.cpp:
+ (JSC::DFG::AbstractState::execute):
+ * dfg/DFGCFGSimplificationPhase.cpp:
+ (JSC::DFG::CFGSimplificationPhase::run):
+ * dfg/DFGOperations.cpp:
+ * dfg/DFGOperations.h:
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::nonSpeculativeNonPeepholeCompareNull):
+ (JSC::DFG::SpeculativeJIT::nonSpeculativePeepholeBranchNull):
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::nonSpeculativeNonPeepholeCompareNull):
+ (JSC::DFG::SpeculativeJIT::nonSpeculativePeepholeBranchNull):
+ (JSC::DFG::SpeculativeJIT::compile):
+ * interpreter/Interpreter.cpp:
+ (JSC::Interpreter::privateExecute):
+ * jit/JITOpcodes.cpp:
+ (JSC::JIT::emit_op_is_undefined):
+ (JSC::JIT::emit_op_jeq_null):
+ (JSC::JIT::emit_op_jneq_null):
+ (JSC::JIT::emit_op_eq_null):
+ (JSC::JIT::emit_op_neq_null):
+ * jit/JITOpcodes32_64.cpp:
+ (JSC::JIT::emit_op_is_undefined):
+ (JSC::JIT::emit_op_jeq_null):
+ (JSC::JIT::emit_op_jneq_null):
+ (JSC::JIT::emit_op_eq_null):
+ (JSC::JIT::emit_op_neq_null):
+ * jit/JITStubs.cpp:
+ (JSC::DEFINE_STUB_FUNCTION):
+ * llint/LLIntSlowPaths.cpp:
+ (JSC::LLInt::LLINT_SLOW_PATH_DECL):
+ * llint/LowLevelInterpreter32_64.asm:
+ * llint/LowLevelInterpreter64.asm:
+ * runtime/ArrayPrototype.cpp:
+ (JSC::arrayProtoFuncFilter):
+ (JSC::arrayProtoFuncEvery):
+ (JSC::arrayProtoFuncSome):
+ * runtime/BooleanConstructor.cpp:
+ (JSC::constructBoolean):
+ (JSC::callBooleanConstructor):
+ * runtime/JSCell.h:
+ (JSCell):
+ * runtime/JSGlobalObject.cpp:
+ (JSC::JSGlobalObject::JSGlobalObject):
+ * runtime/JSGlobalObject.h:
+ (JSGlobalObject):
+ * runtime/JSString.h:
+ (JSC::JSCell::toBoolean):
+ (JSC::JSValue::toBoolean):
+ * runtime/JSValue.h:
+ * runtime/ObjectConstructor.cpp:
+ (JSC::toPropertyDescriptor):
+ * runtime/Operations.cpp:
+ (JSC::jsTypeStringForValue):
+ (JSC::jsIsObjectType):
+ * runtime/Operations.h:
+ (JSC):
+ (JSC::JSValue::equalSlowCaseInline):
+ * runtime/RegExpConstructor.cpp:
+ (JSC::setRegExpConstructorMultiline):
+ * runtime/RegExpPrototype.cpp:
+ (JSC::regExpProtoFuncToString):
+ * runtime/Structure.h:
+
+2012-08-15 Gabor Ballabas <gaborb@inf.u-szeged.hu>
+
+ Buildfix after r125541
+ https://bugs.webkit.org/show_bug.cgi?id=94097
+
+ Reviewed by Filip Pizlo.
+
+ r125541 has broken the traditional ARM port build of JSC.
+
+ * assembler/MacroAssemblerARM.h:
+ (JSC::MacroAssemblerARM::neg32):
+ (JSC::MacroAssemblerARM::xor32):
+
+2012-08-14 Mark Hahnenberg <mhahnenberg@apple.com>
+
+ Change behavior of MasqueradesAsUndefined to better accommodate DFG changes
+ https://bugs.webkit.org/show_bug.cgi?id=93884
+
+ Reviewed by Geoffrey Garen.
+
+ With some upcoming changes to the DFG to remove uses of ClassInfo, we will be changing the behavior of
+ MasqueradesAsUndefined. In order to make this change consistent across all of our execution engines,
+ we will make this change to MasqueradesAsUndefined as a separate patch. After this patch, MasqueradesAsUndefined
+ objects will only masquerade as undefined in their original context (i.e. their original JSGlobalObject).
+ For example, if an object that masquerades as undefined in frame A is passed to frame B, it will not
+ masquerade as undefined within frame B, but it will continue to masquerade in frame A.
+
+ There are two primary changes that are taking place here. One is to thread the ExecState* through
+ JSValue::toBoolean and JSCell::toBoolean so that JSCell::toBoolean can check the object's
+ JSGlobalObject to compare it to the lexical JSGlobalObject of the currently running code. If the two
+ are distinct, then the object cannot MasqueradeAsUndefined.
+
+ The other change is to perform this comparison of JSGlobalObjects everywhere where the MasqueradesAsUndefined
+ flag in the Structure is checked. For C++ code, this check has been factored into its own function in
+ Structure::masqueradesAsUndefined. We only perform this check in the DFG if the current JSGlobalObject has
+ had a MasqueradesAsUndefined object allocated within its context. This conditional compilation is managed
+ through the use of a WatchpointSet in each JSGlobalObject and alternate create() functions for JS DOM wrappers
+ that are MasqueradesAsUndefined.
+
+ * API/JSValueRef.cpp:
+ (JSValueToBoolean):
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def:
+ * bytecode/Watchpoint.h:
+ (WatchpointSet):
+ * debugger/DebuggerCallFrame.h:
+ (JSC::DebuggerCallFrame::callFrame):
+ * dfg/DFGAbstractState.cpp:
+ (JSC::DFG::AbstractState::execute):
+ * dfg/DFGCFGSimplificationPhase.cpp:
+ (JSC::DFG::CFGSimplificationPhase::run):
+ * dfg/DFGOperations.cpp:
+ * dfg/DFGOperations.h:
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::nonSpeculativeNonPeepholeCompareNull):
+ (JSC::DFG::SpeculativeJIT::nonSpeculativePeepholeBranchNull):
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::nonSpeculativeNonPeepholeCompareNull):
+ (JSC::DFG::SpeculativeJIT::nonSpeculativePeepholeBranchNull):
+ (JSC::DFG::SpeculativeJIT::compile):
+ * interpreter/Interpreter.cpp:
+ (JSC::Interpreter::privateExecute):
+ * jit/JITOpcodes.cpp:
+ (JSC::JIT::emit_op_is_undefined):
+ (JSC::JIT::emit_op_jeq_null):
+ (JSC::JIT::emit_op_jneq_null):
+ (JSC::JIT::emit_op_eq_null):
+ (JSC::JIT::emit_op_neq_null):
+ * jit/JITOpcodes32_64.cpp:
+ (JSC::JIT::emit_op_is_undefined):
+ (JSC::JIT::emit_op_jeq_null):
+ (JSC::JIT::emit_op_jneq_null):
+ (JSC::JIT::emit_op_eq_null):
+ (JSC::JIT::emit_op_neq_null):
+ * jit/JITStubs.cpp:
+ (JSC::DEFINE_STUB_FUNCTION):
+ * llint/LLIntSlowPaths.cpp:
+ (JSC::LLInt::LLINT_SLOW_PATH_DECL):
+ * llint/LowLevelInterpreter32_64.asm:
+ * llint/LowLevelInterpreter64.asm:
+ * runtime/ArrayPrototype.cpp:
+ (JSC::arrayProtoFuncFilter):
+ (JSC::arrayProtoFuncEvery):
+ (JSC::arrayProtoFuncSome):
+ * runtime/BooleanConstructor.cpp:
+ (JSC::constructBoolean):
+ (JSC::callBooleanConstructor):
+ * runtime/JSCell.h:
+ (JSCell):
+ * runtime/JSGlobalObject.cpp:
+ (JSC::JSGlobalObject::JSGlobalObject):
+ * runtime/JSGlobalObject.h:
+ (JSGlobalObject):
+ (JSC::JSGlobalObject::masqueradesAsUndefinedWatchpoint):
+ * runtime/JSString.h:
+ (JSC::JSCell::toBoolean):
+ (JSC::JSValue::toBoolean):
+ * runtime/JSValue.h:
+ * runtime/ObjectConstructor.cpp:
+ (JSC::toPropertyDescriptor):
+ * runtime/Operations.cpp:
+ (JSC::jsTypeStringForValue):
+ (JSC::jsIsObjectType):
+ * runtime/Operations.h:
+ (JSC):
+ (JSC::JSValue::equalSlowCaseInline):
+ * runtime/RegExpConstructor.cpp:
+ (JSC::setRegExpConstructorMultiline):
+ * runtime/RegExpPrototype.cpp:
+ (JSC::regExpProtoFuncToString):
+ * runtime/Structure.h:
+ (Structure):
+ (JSC::Structure::globalObjectOffset):
+ (JSC::Structure::masqueradesAsUndefined):
+ (JSC):
+
+2012-08-14 Filip Pizlo <fpizlo@apple.com>
+
+ Unreviewed, build fix for !ENABLE(DFG_JIT)
+
+ * jit/JITPropertyAccess.cpp:
+ (JSC::JIT::emit_op_get_by_val):
+ (JSC::JIT::emit_op_put_by_val):
+ (JSC::JIT::privateCompilePatchGetArrayLength):
+ * jit/JITPropertyAccess32_64.cpp:
+ (JSC::JIT::emit_op_get_by_val):
+ (JSC::JIT::emit_op_put_by_val):
+ (JSC::JIT::privateCompilePatchGetArrayLength):
+ * llint/LowLevelInterpreter32_64.asm:
+ * llint/LowLevelInterpreter64.asm:
+
+2012-08-13 Filip Pizlo <fpizlo@apple.com>
+
+ Array checks should use the structure, not the class info
+ https://bugs.webkit.org/show_bug.cgi?id=93150
+
+ Reviewed by Mark Hahnenberg.
+
+ This changes all array checks used in array accesses (get, put, get length,
+ push, pop) to use the structure, not the class info. Additionally, these
+ checks in the LLInt and baseline JIT record the structure in an ArrayProfile,
+ so that the DFG can know exactly what structure to check for.
+
+ * CMakeLists.txt:
+ * GNUmakefile.list.am:
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * Target.pri:
+ * bytecode/ArrayProfile.cpp: Added.
+ (JSC):
+ (JSC::ArrayProfile::computeUpdatedPrediction):
+ * bytecode/ArrayProfile.h: Added.
+ (JSC):
+ (JSC::arrayModeFromStructure):
+ (ArrayProfile):
+ (JSC::ArrayProfile::ArrayProfile):
+ (JSC::ArrayProfile::bytecodeOffset):
+ (JSC::ArrayProfile::addressOfLastSeenStructure):
+ (JSC::ArrayProfile::observeStructure):
+ (JSC::ArrayProfile::expectedStructure):
+ (JSC::ArrayProfile::structureIsPolymorphic):
+ (JSC::ArrayProfile::hasDefiniteStructure):
+ (JSC::ArrayProfile::observedArrayModes):
+ * bytecode/CodeBlock.cpp:
+ (JSC::CodeBlock::dump):
+ (JSC::CodeBlock::getArrayProfile):
+ (JSC):
+ (JSC::CodeBlock::getOrAddArrayProfile):
+ (JSC::CodeBlock::updateAllPredictionsAndCountLiveness):
+ * bytecode/CodeBlock.h:
+ (JSC::CodeBlock::executionEntryCount):
+ (JSC::CodeBlock::numberOfArrayProfiles):
+ (JSC::CodeBlock::arrayProfiles):
+ (JSC::CodeBlock::addArrayProfile):
+ (CodeBlock):
+ * bytecode/Instruction.h:
+ (JSC):
+ (JSC::Instruction::Instruction):
+ * bytecode/Opcode.h:
+ (JSC):
+ (JSC::padOpcodeName):
+ * bytecompiler/BytecodeGenerator.cpp:
+ (JSC::BytecodeGenerator::emitGetArgumentByVal):
+ (JSC::BytecodeGenerator::emitGetByVal):
+ (JSC::BytecodeGenerator::emitPutByVal):
+ * dfg/DFGAbstractState.cpp:
+ (JSC::DFG::AbstractState::initialize):
+ (JSC::DFG::AbstractState::execute):
+ * dfg/DFGAbstractValue.h:
+ (JSC::DFG::StructureAbstractValue::hasSingleton):
+ (StructureAbstractValue):
+ (JSC::DFG::StructureAbstractValue::singleton):
+ * dfg/DFGArgumentsSimplificationPhase.cpp:
+ (JSC::DFG::ArgumentsSimplificationPhase::run):
+ * dfg/DFGByteCodeParser.cpp:
+ (JSC::DFG::ByteCodeParser::parseBlock):
+ * dfg/DFGFixupPhase.cpp:
+ (JSC::DFG::FixupPhase::fixupNode):
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::speculateArray):
+ (DFG):
+ (JSC::DFG::SpeculativeJIT::compile):
+ (JSC::DFG::SpeculativeJIT::checkArgumentTypes):
+ (JSC::DFG::SpeculativeJIT::compileGetIndexedPropertyStorage):
+ * dfg/DFGSpeculativeJIT.h:
+ (SpeculativeJIT):
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGStructureCheckHoistingPhase.cpp:
+ (JSC::DFG::StructureCheckHoistingPhase::run):
+ * jit/JITPropertyAccess.cpp:
+ (JSC::JIT::emit_op_get_by_val):
+ (JSC::JIT::emit_op_put_by_val):
+ (JSC::JIT::privateCompilePatchGetArrayLength):
+ * jit/JITPropertyAccess32_64.cpp:
+ (JSC::JIT::emit_op_get_by_val):
+ (JSC::JIT::emit_op_put_by_val):
+ (JSC::JIT::privateCompilePatchGetArrayLength):
+ * llint/LLIntOffsetsExtractor.cpp:
+ * llint/LowLevelInterpreter32_64.asm:
+ * llint/LowLevelInterpreter64.asm:
+ * runtime/Structure.h:
+ (Structure):
+ (JSC::Structure::classInfoOffset):
+
+2012-08-14 Gabor Ballabas <gaborb@inf.u-szeged.hu>
+
+ Rename functions in the ARM port of DFG-JIT for better code readability.
+ https://bugs.webkit.org/show_bug.cgi?id=93609
+
+ Reviewed by Zoltan Herczeg.
+
+ Rename functions in the ARM port of DFG-JIT for better code
+ readability, and for following the WebKit coding style
+ wherever it is possible.
+
+ * assembler/ARMAssembler.cpp:
+ (JSC::ARMAssembler::genInt):
+ (JSC::ARMAssembler::getImm):
+ (JSC::ARMAssembler::moveImm):
+ (JSC::ARMAssembler::encodeComplexImm):
+ (JSC::ARMAssembler::dataTransfer32):
+ (JSC::ARMAssembler::baseIndexTransfer32):
+ (JSC::ARMAssembler::dataTransfer16):
+ (JSC::ARMAssembler::baseIndexTransfer16):
+ (JSC::ARMAssembler::dataTransferFloat):
+ (JSC::ARMAssembler::baseIndexTransferFloat):
+ * assembler/ARMAssembler.h:
+ (JSC::ARMAssembler::bitAnd):
+ (JSC::ARMAssembler::bitAnds):
+ (JSC::ARMAssembler::eor):
+ (JSC::ARMAssembler::eors):
+ (JSC::ARMAssembler::sub):
+ (JSC::ARMAssembler::subs):
+ (JSC::ARMAssembler::rsb):
+ (JSC::ARMAssembler::rsbs):
+ (JSC::ARMAssembler::add):
+ (JSC::ARMAssembler::adds):
+ (JSC::ARMAssembler::adc):
+ (JSC::ARMAssembler::adcs):
+ (JSC::ARMAssembler::sbc):
+ (JSC::ARMAssembler::sbcs):
+ (JSC::ARMAssembler::rsc):
+ (JSC::ARMAssembler::rscs):
+ (JSC::ARMAssembler::tst):
+ (JSC::ARMAssembler::teq):
+ (JSC::ARMAssembler::cmp):
+ (JSC::ARMAssembler::cmn):
+ (JSC::ARMAssembler::orr):
+ (JSC::ARMAssembler::orrs):
+ (JSC::ARMAssembler::mov):
+ (JSC::ARMAssembler::movw):
+ (JSC::ARMAssembler::movt):
+ (JSC::ARMAssembler::movs):
+ (JSC::ARMAssembler::bic):
+ (JSC::ARMAssembler::bics):
+ (JSC::ARMAssembler::mvn):
+ (JSC::ARMAssembler::mvns):
+ (JSC::ARMAssembler::mul):
+ (JSC::ARMAssembler::muls):
+ (JSC::ARMAssembler::mull):
+ (JSC::ARMAssembler::vmov_f64):
+ (JSC::ARMAssembler::vadd_f64):
+ (JSC::ARMAssembler::vdiv_f64):
+ (JSC::ARMAssembler::vsub_f64):
+ (JSC::ARMAssembler::vmul_f64):
+ (JSC::ARMAssembler::vcmp_f64):
+ (JSC::ARMAssembler::vsqrt_f64):
+ (JSC::ARMAssembler::vabs_f64):
+ (JSC::ARMAssembler::vneg_f64):
+ (JSC::ARMAssembler::ldrImmediate):
+ (JSC::ARMAssembler::ldrUniqueImmediate):
+ (JSC::ARMAssembler::dtrUp):
+ (JSC::ARMAssembler::dtrUpRegister):
+ (JSC::ARMAssembler::dtrDown):
+ (JSC::ARMAssembler::dtrDownRegister):
+ (JSC::ARMAssembler::halfDtrUp):
+ (JSC::ARMAssembler::halfDtrUpRegister):
+ (JSC::ARMAssembler::halfDtrDown):
+ (JSC::ARMAssembler::halfDtrDownRegister):
+ (JSC::ARMAssembler::doubleDtrUp):
+ (JSC::ARMAssembler::doubleDtrDown):
+ (JSC::ARMAssembler::push):
+ (JSC::ARMAssembler::pop):
+ (JSC::ARMAssembler::poke):
+ (JSC::ARMAssembler::peek):
+ (JSC::ARMAssembler::vmov_vfp64):
+ (JSC::ARMAssembler::vmov_arm64):
+ (JSC::ARMAssembler::vmov_vfp32):
+ (JSC::ARMAssembler::vmov_arm32):
+ (JSC::ARMAssembler::vcvt_f64_s32):
+ (JSC::ARMAssembler::vcvt_s32_f64):
+ (JSC::ARMAssembler::vcvt_u32_f64):
+ (JSC::ARMAssembler::vcvt_f64_f32):
+ (JSC::ARMAssembler::vcvt_f32_f64):
+ (JSC::ARMAssembler::clz):
+ (JSC::ARMAssembler::lslRegister):
+ (JSC::ARMAssembler::lsrRegister):
+ (JSC::ARMAssembler::asrRegister):
+ (JSC::ARMAssembler::align):
+ (JSC::ARMAssembler::loadBranchTarget):
+ (JSC::ARMAssembler::vmov):
+ * assembler/MacroAssemblerARM.cpp:
+ (JSC::MacroAssemblerARM::load32WithUnalignedHalfWords):
+ * assembler/MacroAssemblerARM.h:
+ (JSC::MacroAssemblerARM::add32):
+ (JSC::MacroAssemblerARM::and32):
+ (JSC::MacroAssemblerARM::lshift32):
+ (JSC::MacroAssemblerARM::mul32):
+ (JSC::MacroAssemblerARM::or32):
+ (JSC::MacroAssemblerARM::rshift32):
+ (JSC::MacroAssemblerARM::urshift32):
+ (JSC::MacroAssemblerARM::sub32):
+ (JSC::MacroAssemblerARM::xor32):
+ (JSC::MacroAssemblerARM::countLeadingZeros32):
+ (JSC::MacroAssemblerARM::convertibleLoadPtr):
+ (JSC::MacroAssemblerARM::load32WithAddressOffsetPatch):
+ (JSC::MacroAssemblerARM::load32WithCompactAddressOffsetPatch):
+ (JSC::MacroAssemblerARM::store32WithAddressOffsetPatch):
+ (JSC::MacroAssemblerARM::store32):
+ (JSC::MacroAssemblerARM::pop):
+ (JSC::MacroAssemblerARM::push):
+ (JSC::MacroAssemblerARM::move):
+ (JSC::MacroAssemblerARM::swap):
+ (JSC::MacroAssemblerARM::branch32):
+ (JSC::MacroAssemblerARM::branchTest32):
+ (JSC::MacroAssemblerARM::mull32):
+ (JSC::MacroAssemblerARM::branchSub32):
+ (JSC::MacroAssemblerARM::compare32):
+ (JSC::MacroAssemblerARM::test32):
+ (JSC::MacroAssemblerARM::load32):
+ (JSC::MacroAssemblerARM::relativeTableJump):
+ (JSC::MacroAssemblerARM::moveWithPatch):
+ (JSC::MacroAssemblerARM::loadDouble):
+ (JSC::MacroAssemblerARM::moveDouble):
+ (JSC::MacroAssemblerARM::addDouble):
+ (JSC::MacroAssemblerARM::divDouble):
+ (JSC::MacroAssemblerARM::subDouble):
+ (JSC::MacroAssemblerARM::mulDouble):
+ (JSC::MacroAssemblerARM::sqrtDouble):
+ (JSC::MacroAssemblerARM::absDouble):
+ (JSC::MacroAssemblerARM::negateDouble):
+ (JSC::MacroAssemblerARM::convertInt32ToDouble):
+ (JSC::MacroAssemblerARM::convertFloatToDouble):
+ (JSC::MacroAssemblerARM::convertDoubleToFloat):
+ (JSC::MacroAssemblerARM::branchDouble):
+ (JSC::MacroAssemblerARM::branchTruncateDoubleToInt32):
+ (JSC::MacroAssemblerARM::branchTruncateDoubleToUint32):
+ (JSC::MacroAssemblerARM::truncateDoubleToInt32):
+ (JSC::MacroAssemblerARM::truncateDoubleToUint32):
+ (JSC::MacroAssemblerARM::branchConvertDoubleToInt32):
+ (JSC::MacroAssemblerARM::branchDoubleNonZero):
+ (JSC::MacroAssemblerARM::branchDoubleZeroOrNaN):
+
+2012-08-13 Simon Hausmann <simon.hausmann@nokia.com>
+
+ Unreviewed, rolling out r125444.
+ http://trac.webkit.org/changeset/125444
+ https://bugs.webkit.org/show_bug.cgi?id=93872
+
+ Broke some tests
+
+ * Target.pri:
+
+2012-08-13 Simon Hausmann <simon.hausmann@nokia.com>
+
+ [Qt] Replace use of internal Weak smart pointer with JSWeakObjectMap
+ https://bugs.webkit.org/show_bug.cgi?id=93872
+
+ Reviewed by Kenneth Rohde Christiansen.
+
+ * Target.pri: Add missing JSWeakObjectMap file to build.
+
+2012-08-13 Raphael Kubo da Costa <rakuco@webkit.org>
+
+ [CMake] Remove glib-related Find modules and write single new one instead.
+ https://bugs.webkit.org/show_bug.cgi?id=93786
+
+ Reviewed by Rob Buis.
+
+ * shell/PlatformEfl.cmake: Use GLIB_* instead of Glib_*.
+
+2012-08-12 Allan Sandfeld Jensen <allan.jensen@nokia.com>
+
+ Doesn't build with ENABLE_JIT=0
+ https://bugs.webkit.org/show_bug.cgi?id=85042
+
+ Reviewed by Eric Seidel.
+
+ Include headers without which CallFrame.h does not build, and
+ fix gcc warning about comparing unsigned int with 0.
+
+ * dfg/DFGDriver.cpp:
+ * interpreter/Interpreter.cpp:
+ (JSC::Interpreter::isOpcode):
+
2012-08-10 Yong Li <yoli@rim.com>
[BlackBerry] GCActivityCallback should always schedule GC even allocated bytes is a small number
diff --git a/Source/JavaScriptCore/Configurations/FeatureDefines.xcconfig b/Source/JavaScriptCore/Configurations/FeatureDefines.xcconfig
index 40d95cb9c..9c1b8ffa7 100644
--- a/Source/JavaScriptCore/Configurations/FeatureDefines.xcconfig
+++ b/Source/JavaScriptCore/Configurations/FeatureDefines.xcconfig
@@ -48,6 +48,7 @@ ENABLE_CSS_COMPOSITING = ;
ENABLE_CSS_STICKY_POSITION = ENABLE_CSS_STICKY_POSITION;
ENABLE_CSS_VARIABLES = ;
ENABLE_CSS3_FLEXBOX = ENABLE_CSS3_FLEXBOX;
+ENABLE_CSS3_TEXT_DECORATION = ;
ENABLE_CUSTOM_SCHEME_HANDLER = ;
ENABLE_DASHBOARD_SUPPORT = $(ENABLE_DASHBOARD_SUPPORT_$(REAL_PLATFORM_NAME));
ENABLE_DASHBOARD_SUPPORT_macosx = ENABLE_DASHBOARD_SUPPORT;
@@ -139,4 +140,4 @@ ENABLE_WIDGET_REGION_macosx = ENABLE_WIDGET_REGION;
ENABLE_WORKERS = ENABLE_WORKERS;
ENABLE_XSLT = ENABLE_XSLT;
-FEATURE_DEFINES = $(ENABLE_3D_RENDERING) $(ENABLE_ACCELERATED_2D_CANVAS) $(ENABLE_ANIMATION_API) $(ENABLE_BLOB) $(ENABLE_CHANNEL_MESSAGING) $(ENABLE_CSP_NEXT) $(ENABLE_CSS_BOX_DECORATION_BREAK) $(ENABLE_CSS_EXCLUSIONS) $(ENABLE_CSS_FILTERS) $(ENABLE_CSS_HIERARCHIES) $(ENABLE_CSS_IMAGE_ORIENTATION) $(ENABLE_CSS_IMAGE_RESOLUTION) $(ENABLE_CSS_REGIONS) $(ENABLE_CSS_SHADERS) $(ENABLE_CSS_COMPOSITING) $(ENABLE_CSS_STICKY_POSITION) $(ENABLE_CSS_VARIABLES) $(ENABLE_CSS3_FLEXBOX) $(ENABLE_CUSTOM_SCHEME_HANDLER) $(ENABLE_DASHBOARD_SUPPORT) $(ENABLE_DATALIST_ELEMENT) $(ENABLE_DATA_TRANSFER_ITEMS) $(ENABLE_DETAILS_ELEMENT) $(ENABLE_DEVICE_ORIENTATION) $(ENABLE_DIALOG_ELEMENT) $(ENABLE_DIRECTORY_UPLOAD) $(ENABLE_FILE_SYSTEM) $(ENABLE_FILTERS) $(ENABLE_FULLSCREEN_API) $(ENABLE_GAMEPAD) $(ENABLE_GEOLOCATION) $(ENABLE_HIGH_DPI_CANVAS) $(ENABLE_ICONDATABASE) $(ENABLE_IFRAME_SEAMLESS) $(ENABLE_INDEXED_DATABASE) $(ENABLE_INPUT_SPEECH) $(ENABLE_INPUT_TYPE_COLOR) $(ENABLE_INPUT_TYPE_DATE) $(ENABLE_INPUT_TYPE_DATETIME) $(ENABLE_INPUT_TYPE_DATETIMELOCAL) $(ENABLE_INPUT_TYPE_MONTH) $(ENABLE_INPUT_TYPE_TIME) $(ENABLE_INPUT_TYPE_WEEK) $(ENABLE_JAVASCRIPT_DEBUGGER) $(ENABLE_LEGACY_CSS_VENDOR_PREFIXES) $(ENABLE_LEGACY_NOTIFICATIONS) $(ENABLE_LINK_PREFETCH) $(ENABLE_LINK_PRERENDER) $(ENABLE_MATHML) $(ENABLE_MEDIA_SOURCE) $(ENABLE_MEDIA_STATISTICS) $(ENABLE_METER_ELEMENT) $(ENABLE_MHTML) $(ENABLE_MICRODATA) $(ENABLE_MUTATION_OBSERVERS) $(ENABLE_NOTIFICATIONS) $(ENABLE_PAGE_VISIBILITY_API) $(ENABLE_PROGRESS_ELEMENT) $(ENABLE_QUOTA) $(ENABLE_REGISTER_PROTOCOL_HANDLER) $(ENABLE_REQUEST_ANIMATION_FRAME) $(ENABLE_SCRIPTED_SPEECH) $(ENABLE_SHADOW_DOM) $(ENABLE_SHARED_WORKERS) $(ENABLE_SQL_DATABASE) $(ENABLE_STYLE_SCOPED) $(ENABLE_SVG) $(ENABLE_SVG_DOM_OBJC_BINDINGS) $(ENABLE_SVG_FONTS) $(ENABLE_TEXT_AUTOSIZING) $(ENABLE_TEXT_NOTIFICATIONS_ONLY) $(ENABLE_TOUCH_ICON_LOADING) $(ENABLE_UNDO_MANAGER) $(ENABLE_VIDEO) $(ENABLE_VIDEO_TRACK) $(ENABLE_WEBGL) $(ENABLE_WEB_AUDIO) $(ENABLE_WEB_SOCKETS) $(ENABLE_WEB_TIMING) $(ENABLE_WIDGET_REGION) $(ENABLE_WORKERS) $(ENABLE_XSLT);
+FEATURE_DEFINES = $(ENABLE_3D_RENDERING) $(ENABLE_ACCELERATED_2D_CANVAS) $(ENABLE_ANIMATION_API) $(ENABLE_BLOB) $(ENABLE_CHANNEL_MESSAGING) $(ENABLE_CSP_NEXT) $(ENABLE_CSS_BOX_DECORATION_BREAK) $(ENABLE_CSS_EXCLUSIONS) $(ENABLE_CSS_FILTERS) $(ENABLE_CSS_HIERARCHIES) $(ENABLE_CSS_IMAGE_ORIENTATION) $(ENABLE_CSS_IMAGE_RESOLUTION) $(ENABLE_CSS_REGIONS) $(ENABLE_CSS_SHADERS) $(ENABLE_CSS_COMPOSITING) $(ENABLE_CSS_STICKY_POSITION) $(ENABLE_CSS_VARIABLES) $(ENABLE_CSS3_FLEXBOX) $(ENABLE_CSS3_TEXT_DECORATION) $(ENABLE_CUSTOM_SCHEME_HANDLER) $(ENABLE_DASHBOARD_SUPPORT) $(ENABLE_DATALIST_ELEMENT) $(ENABLE_DATA_TRANSFER_ITEMS) $(ENABLE_DETAILS_ELEMENT) $(ENABLE_DEVICE_ORIENTATION) $(ENABLE_DIALOG_ELEMENT) $(ENABLE_DIRECTORY_UPLOAD) $(ENABLE_FILE_SYSTEM) $(ENABLE_FILTERS) $(ENABLE_FULLSCREEN_API) $(ENABLE_GAMEPAD) $(ENABLE_GEOLOCATION) $(ENABLE_HIGH_DPI_CANVAS) $(ENABLE_ICONDATABASE) $(ENABLE_IFRAME_SEAMLESS) $(ENABLE_INDEXED_DATABASE) $(ENABLE_INPUT_SPEECH) $(ENABLE_INPUT_TYPE_COLOR) $(ENABLE_INPUT_TYPE_DATE) $(ENABLE_INPUT_TYPE_DATETIME) $(ENABLE_INPUT_TYPE_DATETIMELOCAL) $(ENABLE_INPUT_TYPE_MONTH) $(ENABLE_INPUT_TYPE_TIME) $(ENABLE_INPUT_TYPE_WEEK) $(ENABLE_JAVASCRIPT_DEBUGGER) $(ENABLE_LEGACY_CSS_VENDOR_PREFIXES) $(ENABLE_LEGACY_NOTIFICATIONS) $(ENABLE_LINK_PREFETCH) $(ENABLE_LINK_PRERENDER) $(ENABLE_MATHML) $(ENABLE_MEDIA_SOURCE) $(ENABLE_MEDIA_STATISTICS) $(ENABLE_METER_ELEMENT) $(ENABLE_MHTML) $(ENABLE_MICRODATA) $(ENABLE_MUTATION_OBSERVERS) $(ENABLE_NOTIFICATIONS) $(ENABLE_PAGE_VISIBILITY_API) $(ENABLE_PROGRESS_ELEMENT) $(ENABLE_QUOTA) $(ENABLE_REGISTER_PROTOCOL_HANDLER) $(ENABLE_REQUEST_ANIMATION_FRAME) $(ENABLE_SCRIPTED_SPEECH) $(ENABLE_SHADOW_DOM) $(ENABLE_SHARED_WORKERS) $(ENABLE_SQL_DATABASE) $(ENABLE_STYLE_SCOPED) $(ENABLE_SVG) $(ENABLE_SVG_DOM_OBJC_BINDINGS) $(ENABLE_SVG_FONTS) $(ENABLE_TEXT_AUTOSIZING) $(ENABLE_TEXT_NOTIFICATIONS_ONLY) $(ENABLE_TOUCH_ICON_LOADING) $(ENABLE_UNDO_MANAGER) $(ENABLE_VIDEO) $(ENABLE_VIDEO_TRACK) $(ENABLE_WEBGL) $(ENABLE_WEB_AUDIO) $(ENABLE_WEB_SOCKETS) $(ENABLE_WEB_TIMING) $(ENABLE_WIDGET_REGION) $(ENABLE_WORKERS) $(ENABLE_XSLT);
diff --git a/Source/JavaScriptCore/GNUmakefile.list.am b/Source/JavaScriptCore/GNUmakefile.list.am
index ab8b110c2..c504962cc 100644
--- a/Source/JavaScriptCore/GNUmakefile.list.am
+++ b/Source/JavaScriptCore/GNUmakefile.list.am
@@ -82,6 +82,8 @@ javascriptcore_sources += \
Source/JavaScriptCore/assembler/RepatchBuffer.h \
Source/JavaScriptCore/assembler/SH4Assembler.h \
Source/JavaScriptCore/assembler/X86Assembler.h \
+ Source/JavaScriptCore/bytecode/ArrayProfile.cpp \
+ Source/JavaScriptCore/bytecode/ArrayProfile.h \
Source/JavaScriptCore/bytecode/BytecodeConventions.h \
Source/JavaScriptCore/bytecode/CallLinkInfo.cpp \
Source/JavaScriptCore/bytecode/CallLinkInfo.h \
@@ -227,6 +229,7 @@ javascriptcore_sources += \
Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp \
Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp \
Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h \
+ Source/JavaScriptCore/dfg/DFGStructureAbstractValue.h \
Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.cpp \
Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.h \
Source/JavaScriptCore/dfg/DFGThunks.cpp \
diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj
index 2efa84059..e91baa473 100644
--- a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj
+++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj
@@ -1530,6 +1530,14 @@
Name="bytecode"
>
<File
+ RelativePath="..\..\bytecode\ArrayProfile.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\bytecode\ArrayProfile.h"
+ >
+ </File>
+ <File
RelativePath="..\..\bytecode\CallLinkInfo.cpp"
>
</File>
diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/testRegExp/testRegExp.vcproj b/Source/JavaScriptCore/JavaScriptCore.vcproj/testRegExp/testRegExp.vcproj
index b7053908d..57b9ce643 100755
--- a/Source/JavaScriptCore/JavaScriptCore.vcproj/testRegExp/testRegExp.vcproj
+++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/testRegExp/testRegExp.vcproj
@@ -50,6 +50,7 @@
/>
<Tool
Name="VCLinkerTool"
+ AdditionalOptions="/SAFESEH"
/>
<Tool
Name="VCALinkTool"
@@ -111,6 +112,7 @@
/>
<Tool
Name="VCLinkerTool"
+ AdditionalOptions="/SAFESEH"
/>
<Tool
Name="VCALinkTool"
@@ -172,6 +174,7 @@
/>
<Tool
Name="VCLinkerTool"
+ AdditionalOptions="/SAFESEH"
/>
<Tool
Name="VCALinkTool"
@@ -233,6 +236,7 @@
/>
<Tool
Name="VCLinkerTool"
+ AdditionalOptions="/SAFESEH"
/>
<Tool
Name="VCALinkTool"
@@ -295,6 +299,7 @@
/>
<Tool
Name="VCLinkerTool"
+ AdditionalOptions="/SAFESEH"
/>
<Tool
Name="VCALinkTool"
@@ -356,6 +361,7 @@
/>
<Tool
Name="VCLinkerTool"
+ AdditionalOptions="/SAFESEH"
/>
<Tool
Name="VCALinkTool"
@@ -417,6 +423,7 @@
/>
<Tool
Name="VCLinkerTool"
+ AdditionalOptions="/SAFESEH"
/>
<Tool
Name="VCALinkTool"
diff --git a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj b/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
index add311969..a41fb993b 100644
--- a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
+++ b/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
@@ -140,6 +140,9 @@
0F620179143FCD480068B77C /* DFGAbstractState.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F62016D143FCD2F0068B77C /* DFGAbstractState.cpp */; };
0F63943F15C75F19006A597C /* DFGStructureCheckHoistingPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F63943D15C75F14006A597C /* DFGStructureCheckHoistingPhase.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F63944015C75F1D006A597C /* DFGStructureCheckHoistingPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F63943C15C75F14006A597C /* DFGStructureCheckHoistingPhase.cpp */; };
+ 0F63945415D07055006A597C /* ArrayProfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F63945115D07051006A597C /* ArrayProfile.cpp */; };
+ 0F63945515D07057006A597C /* ArrayProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F63945215D07051006A597C /* ArrayProfile.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 0F63947815DCE34B006A597C /* DFGStructureAbstractValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F63947615DCE347006A597C /* DFGStructureAbstractValue.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F66E16B14DF3F1600B7B2E4 /* DFGAdjacencyList.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F66E16814DF3F1300B7B2E4 /* DFGAdjacencyList.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F66E16C14DF3F1600B7B2E4 /* DFGEdge.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F66E16914DF3F1300B7B2E4 /* DFGEdge.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F766D2815A8CC1E008F363E /* JITStubRoutine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F766D2615A8CC1B008F363E /* JITStubRoutine.cpp */; };
@@ -889,6 +892,9 @@
0F620172143FCD2F0068B77C /* DFGVariableAccessData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGVariableAccessData.h; path = dfg/DFGVariableAccessData.h; sourceTree = "<group>"; };
0F63943C15C75F14006A597C /* DFGStructureCheckHoistingPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGStructureCheckHoistingPhase.cpp; path = dfg/DFGStructureCheckHoistingPhase.cpp; sourceTree = "<group>"; };
0F63943D15C75F14006A597C /* DFGStructureCheckHoistingPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGStructureCheckHoistingPhase.h; path = dfg/DFGStructureCheckHoistingPhase.h; sourceTree = "<group>"; };
+ 0F63945115D07051006A597C /* ArrayProfile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ArrayProfile.cpp; sourceTree = "<group>"; };
+ 0F63945215D07051006A597C /* ArrayProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArrayProfile.h; sourceTree = "<group>"; };
+ 0F63947615DCE347006A597C /* DFGStructureAbstractValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGStructureAbstractValue.h; path = dfg/DFGStructureAbstractValue.h; sourceTree = "<group>"; };
0F66E16814DF3F1300B7B2E4 /* DFGAdjacencyList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGAdjacencyList.h; path = dfg/DFGAdjacencyList.h; sourceTree = "<group>"; };
0F66E16914DF3F1300B7B2E4 /* DFGEdge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGEdge.h; path = dfg/DFGEdge.h; sourceTree = "<group>"; };
0F766D1C15A5028D008F363E /* JITStubRoutine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITStubRoutine.h; sourceTree = "<group>"; };
@@ -2325,6 +2331,7 @@
86EC9DC31328DF82002B2AD7 /* DFGSpeculativeJIT.h */,
86880F1B14328BB900B08D42 /* DFGSpeculativeJIT32_64.cpp */,
86880F4C14353B2100B08D42 /* DFGSpeculativeJIT64.cpp */,
+ 0F63947615DCE347006A597C /* DFGStructureAbstractValue.h */,
0F63943C15C75F14006A597C /* DFGStructureCheckHoistingPhase.cpp */,
0F63943D15C75F14006A597C /* DFGStructureCheckHoistingPhase.h */,
0FC0979F146B28C700CF2442 /* DFGThunks.cpp */,
@@ -2407,6 +2414,8 @@
969A078F0ED1D3AE00F1F681 /* bytecode */ = {
isa = PBXGroup;
children = (
+ 0F63945115D07051006A597C /* ArrayProfile.cpp */,
+ 0F63945215D07051006A597C /* ArrayProfile.h */,
0F56A1D415001CF2002992B1 /* ExecutionCounter.cpp */,
0F56A1D115000F31002992B1 /* ExecutionCounter.h */,
0FB5467C14F5CFD3002C2989 /* MethodOfGettingAValueProfile.cpp */,
@@ -2867,6 +2876,8 @@
0F766D4415B2A3C0008F363E /* DFGRegisterSet.h in Headers */,
0F766D4615B3701F008F363E /* DFGScratchRegisterAllocator.h in Headers */,
0F63943F15C75F19006A597C /* DFGStructureCheckHoistingPhase.h in Headers */,
+ 0F63945515D07057006A597C /* ArrayProfile.h in Headers */,
+ 0F63947815DCE34B006A597C /* DFGStructureAbstractValue.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -3465,6 +3476,7 @@
0F766D3415AE2538008F363E /* JumpReplacementWatchpoint.cpp in Sources */,
0F766D3815AE4A1C008F363E /* StructureStubClearingWatchpoint.cpp in Sources */,
0F63944015C75F1D006A597C /* DFGStructureCheckHoistingPhase.cpp in Sources */,
+ 0F63945415D07055006A597C /* ArrayProfile.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
diff --git a/Source/JavaScriptCore/Target.pri b/Source/JavaScriptCore/Target.pri
index 3d0e41df4..e8622363c 100644
--- a/Source/JavaScriptCore/Target.pri
+++ b/Source/JavaScriptCore/Target.pri
@@ -40,12 +40,14 @@ SOURCES += \
API/JSObjectRef.cpp \
API/JSStringRef.cpp \
API/JSValueRef.cpp \
+ API/JSWeakObjectMapRefPrivate.cpp \
API/OpaqueJSString.cpp \
assembler/ARMAssembler.cpp \
assembler/ARMv7Assembler.cpp \
assembler/LinkBuffer.cpp \
assembler/MacroAssemblerARM.cpp \
assembler/MacroAssemblerSH4.cpp \
+ bytecode/ArrayProfile.cpp \
bytecode/CallLinkInfo.cpp \
bytecode/CallLinkStatus.cpp \
bytecode/CodeBlock.cpp \
diff --git a/Source/JavaScriptCore/assembler/ARMAssembler.cpp b/Source/JavaScriptCore/assembler/ARMAssembler.cpp
index 533640ea8..9655557a5 100644
--- a/Source/JavaScriptCore/assembler/ARMAssembler.cpp
+++ b/Source/JavaScriptCore/assembler/ARMAssembler.cpp
@@ -187,11 +187,11 @@ int ARMAssembler::genInt(int reg, ARMWord imm, bool positive)
}
if (positive) {
- mov_r(reg, imm1);
- orr_r(reg, reg, imm2);
+ mov(reg, imm1);
+ orr(reg, reg, imm2);
} else {
- mvn_r(reg, imm1);
- bic_r(reg, reg, imm2);
+ mvn(reg, imm1);
+ bic(reg, reg, imm2);
}
return 1;
@@ -210,7 +210,7 @@ ARMWord ARMAssembler::getImm(ARMWord imm, int tmpReg, bool invert)
if (tmp != InvalidImmediate) {
if (invert)
return tmp | Op2InvertedImmediate;
- mvn_r(tmpReg, tmp);
+ mvn(tmpReg, tmp);
return tmpReg;
}
@@ -224,13 +224,13 @@ void ARMAssembler::moveImm(ARMWord imm, int dest)
// Do it by 1 instruction
tmp = getOp2(imm);
if (tmp != InvalidImmediate) {
- mov_r(dest, tmp);
+ mov(dest, tmp);
return;
}
tmp = getOp2(~imm);
if (tmp != InvalidImmediate) {
- mvn_r(dest, tmp);
+ mvn(dest, tmp);
return;
}
@@ -242,11 +242,11 @@ ARMWord ARMAssembler::encodeComplexImm(ARMWord imm, int dest)
#if WTF_ARM_ARCH_AT_LEAST(7)
ARMWord tmp = getImm16Op2(imm);
if (tmp != InvalidImmediate) {
- movw_r(dest, tmp);
+ movw(dest, tmp);
return dest;
}
- movw_r(dest, getImm16Op2(imm & 0xffff));
- movt_r(dest, getImm16Op2(imm >> 16));
+ movw(dest, getImm16Op2(imm & 0xffff));
+ movt(dest, getImm16Op2(imm >> 16));
return dest;
#else
// Do it by 2 instruction
@@ -255,7 +255,7 @@ ARMWord ARMAssembler::encodeComplexImm(ARMWord imm, int dest)
if (genInt(dest, ~imm, false))
return dest;
- ldr_imm(dest, imm);
+ ldrImmediate(dest, imm);
return dest;
#endif
}
@@ -266,23 +266,23 @@ void ARMAssembler::dataTransfer32(DataTransferTypeA transferType, RegisterID src
{
if (offset >= 0) {
if (offset <= 0xfff)
- dtr_u(transferType, srcDst, base, offset);
+ dtrUp(transferType, srcDst, base, offset);
else if (offset <= 0xfffff) {
- add_r(ARMRegisters::S0, base, Op2Immediate | (offset >> 12) | (10 << 8));
- dtr_u(transferType, srcDst, ARMRegisters::S0, (offset & 0xfff));
+ add(ARMRegisters::S0, base, Op2Immediate | (offset >> 12) | (10 << 8));
+ dtrUp(transferType, srcDst, ARMRegisters::S0, (offset & 0xfff));
} else {
moveImm(offset, ARMRegisters::S0);
- dtr_ur(transferType, srcDst, base, ARMRegisters::S0);
+ dtrUpRegister(transferType, srcDst, base, ARMRegisters::S0);
}
} else {
if (offset >= -0xfff)
- dtr_d(transferType, srcDst, base, -offset);
+ dtrDown(transferType, srcDst, base, -offset);
else if (offset >= -0xfffff) {
- sub_r(ARMRegisters::S0, base, Op2Immediate | (-offset >> 12) | (10 << 8));
- dtr_d(transferType, srcDst, ARMRegisters::S0, (-offset & 0xfff));
+ sub(ARMRegisters::S0, base, Op2Immediate | (-offset >> 12) | (10 << 8));
+ dtrDown(transferType, srcDst, ARMRegisters::S0, (-offset & 0xfff));
} else {
moveImm(offset, ARMRegisters::S0);
- dtr_ur(transferType, srcDst, base, ARMRegisters::S0);
+ dtrUpRegister(transferType, srcDst, base, ARMRegisters::S0);
}
}
}
@@ -293,11 +293,11 @@ void ARMAssembler::baseIndexTransfer32(DataTransferTypeA transferType, RegisterI
ARMWord op2 = lsl(index, scale);
if (!offset) {
- dtr_ur(transferType, srcDst, base, op2);
+ dtrUpRegister(transferType, srcDst, base, op2);
return;
}
- add_r(ARMRegisters::S1, base, op2);
+ add(ARMRegisters::S1, base, op2);
dataTransfer32(transferType, srcDst, ARMRegisters::S1, offset);
}
@@ -305,23 +305,23 @@ void ARMAssembler::dataTransfer16(DataTransferTypeB transferType, RegisterID src
{
if (offset >= 0) {
if (offset <= 0xff)
- dtrh_u(transferType, srcDst, base, getOp2Half(offset));
+ halfDtrUp(transferType, srcDst, base, getOp2Half(offset));
else if (offset <= 0xffff) {
- add_r(ARMRegisters::S0, base, Op2Immediate | (offset >> 8) | (12 << 8));
- dtrh_u(transferType, srcDst, ARMRegisters::S0, getOp2Half(offset & 0xff));
+ add(ARMRegisters::S0, base, Op2Immediate | (offset >> 8) | (12 << 8));
+ halfDtrUp(transferType, srcDst, ARMRegisters::S0, getOp2Half(offset & 0xff));
} else {
moveImm(offset, ARMRegisters::S0);
- dtrh_ur(transferType, srcDst, base, ARMRegisters::S0);
+ halfDtrUpRegister(transferType, srcDst, base, ARMRegisters::S0);
}
} else {
if (offset >= -0xff)
- dtrh_d(transferType, srcDst, base, getOp2Half(-offset));
+ halfDtrDown(transferType, srcDst, base, getOp2Half(-offset));
else if (offset >= -0xffff) {
- sub_r(ARMRegisters::S0, base, Op2Immediate | (-offset >> 8) | (12 << 8));
- dtrh_d(transferType, srcDst, ARMRegisters::S0, getOp2Half(-offset & 0xff));
+ sub(ARMRegisters::S0, base, Op2Immediate | (-offset >> 8) | (12 << 8));
+ halfDtrDown(transferType, srcDst, ARMRegisters::S0, getOp2Half(-offset & 0xff));
} else {
moveImm(offset, ARMRegisters::S0);
- dtrh_ur(transferType, srcDst, base, ARMRegisters::S0);
+ halfDtrUpRegister(transferType, srcDst, base, ARMRegisters::S0);
}
}
}
@@ -329,11 +329,11 @@ void ARMAssembler::dataTransfer16(DataTransferTypeB transferType, RegisterID src
void ARMAssembler::baseIndexTransfer16(DataTransferTypeB transferType, RegisterID srcDst, RegisterID base, RegisterID index, int scale, int32_t offset)
{
if (!scale && !offset) {
- dtrh_ur(transferType, srcDst, base, index);
+ halfDtrUpRegister(transferType, srcDst, base, index);
return;
}
- add_r(ARMRegisters::S1, base, lsl(index, scale));
+ add(ARMRegisters::S1, base, lsl(index, scale));
dataTransfer16(transferType, srcDst, ARMRegisters::S1, offset);
}
@@ -342,36 +342,36 @@ void ARMAssembler::dataTransferFloat(DataTransferTypeFloat transferType, FPRegis
// VFP cannot directly access memory that is not four-byte-aligned
if (!(offset & 0x3)) {
if (offset <= 0x3ff && offset >= 0) {
- fdtr_u(transferType, srcDst, base, offset >> 2);
+ doubleDtrUp(transferType, srcDst, base, offset >> 2);
return;
}
if (offset <= 0x3ffff && offset >= 0) {
- add_r(ARMRegisters::S0, base, Op2Immediate | (offset >> 10) | (11 << 8));
- fdtr_u(transferType, srcDst, ARMRegisters::S0, (offset >> 2) & 0xff);
+ add(ARMRegisters::S0, base, Op2Immediate | (offset >> 10) | (11 << 8));
+ doubleDtrUp(transferType, srcDst, ARMRegisters::S0, (offset >> 2) & 0xff);
return;
}
offset = -offset;
if (offset <= 0x3ff && offset >= 0) {
- fdtr_d(transferType, srcDst, base, offset >> 2);
+ doubleDtrDown(transferType, srcDst, base, offset >> 2);
return;
}
if (offset <= 0x3ffff && offset >= 0) {
- sub_r(ARMRegisters::S0, base, Op2Immediate | (offset >> 10) | (11 << 8));
- fdtr_d(transferType, srcDst, ARMRegisters::S0, (offset >> 2) & 0xff);
+ sub(ARMRegisters::S0, base, Op2Immediate | (offset >> 10) | (11 << 8));
+ doubleDtrDown(transferType, srcDst, ARMRegisters::S0, (offset >> 2) & 0xff);
return;
}
offset = -offset;
}
moveImm(offset, ARMRegisters::S0);
- add_r(ARMRegisters::S0, ARMRegisters::S0, base);
- fdtr_u(transferType, srcDst, ARMRegisters::S0, 0);
+ add(ARMRegisters::S0, ARMRegisters::S0, base);
+ doubleDtrUp(transferType, srcDst, ARMRegisters::S0, 0);
}
void ARMAssembler::baseIndexTransferFloat(DataTransferTypeFloat transferType, FPRegisterID srcDst, RegisterID base, RegisterID index, int scale, int32_t offset)
{
- add_r(ARMRegisters::S1, base, lsl(index, scale));
+ add(ARMRegisters::S1, base, lsl(index, scale));
dataTransferFloat(transferType, srcDst, ARMRegisters::S1, offset);
}
diff --git a/Source/JavaScriptCore/assembler/ARMAssembler.h b/Source/JavaScriptCore/assembler/ARMAssembler.h
index ac918f31e..38d0c5e6d 100644
--- a/Source/JavaScriptCore/assembler/ARMAssembler.h
+++ b/Source/JavaScriptCore/assembler/ARMAssembler.h
@@ -268,355 +268,355 @@ namespace JSC {
| (sm >> 1) | ((sm & 0x1) << 5));
}
- void and_r(int rd, int rn, ARMWord op2, Condition cc = AL)
+ void bitAnd(int rd, int rn, ARMWord op2, Condition cc = AL)
{
emitInstruction(toARMWord(cc) | AND, rd, rn, op2);
}
- void ands_r(int rd, int rn, ARMWord op2, Condition cc = AL)
+ void bitAnds(int rd, int rn, ARMWord op2, Condition cc = AL)
{
emitInstruction(toARMWord(cc) | AND | SetConditionalCodes, rd, rn, op2);
}
- void eor_r(int rd, int rn, ARMWord op2, Condition cc = AL)
+ void eor(int rd, int rn, ARMWord op2, Condition cc = AL)
{
emitInstruction(toARMWord(cc) | EOR, rd, rn, op2);
}
- void eors_r(int rd, int rn, ARMWord op2, Condition cc = AL)
+ void eors(int rd, int rn, ARMWord op2, Condition cc = AL)
{
emitInstruction(toARMWord(cc) | EOR | SetConditionalCodes, rd, rn, op2);
}
- void sub_r(int rd, int rn, ARMWord op2, Condition cc = AL)
+ void sub(int rd, int rn, ARMWord op2, Condition cc = AL)
{
emitInstruction(toARMWord(cc) | SUB, rd, rn, op2);
}
- void subs_r(int rd, int rn, ARMWord op2, Condition cc = AL)
+ void subs(int rd, int rn, ARMWord op2, Condition cc = AL)
{
emitInstruction(toARMWord(cc) | SUB | SetConditionalCodes, rd, rn, op2);
}
- void rsb_r(int rd, int rn, ARMWord op2, Condition cc = AL)
+ void rsb(int rd, int rn, ARMWord op2, Condition cc = AL)
{
emitInstruction(toARMWord(cc) | RSB, rd, rn, op2);
}
- void rsbs_r(int rd, int rn, ARMWord op2, Condition cc = AL)
+ void rsbs(int rd, int rn, ARMWord op2, Condition cc = AL)
{
emitInstruction(toARMWord(cc) | RSB | SetConditionalCodes, rd, rn, op2);
}
- void add_r(int rd, int rn, ARMWord op2, Condition cc = AL)
+ void add(int rd, int rn, ARMWord op2, Condition cc = AL)
{
emitInstruction(toARMWord(cc) | ADD, rd, rn, op2);
}
- void adds_r(int rd, int rn, ARMWord op2, Condition cc = AL)
+ void adds(int rd, int rn, ARMWord op2, Condition cc = AL)
{
emitInstruction(toARMWord(cc) | ADD | SetConditionalCodes, rd, rn, op2);
}
- void adc_r(int rd, int rn, ARMWord op2, Condition cc = AL)
+ void adc(int rd, int rn, ARMWord op2, Condition cc = AL)
{
emitInstruction(toARMWord(cc) | ADC, rd, rn, op2);
}
- void adcs_r(int rd, int rn, ARMWord op2, Condition cc = AL)
+ void adcs(int rd, int rn, ARMWord op2, Condition cc = AL)
{
emitInstruction(toARMWord(cc) | ADC | SetConditionalCodes, rd, rn, op2);
}
- void sbc_r(int rd, int rn, ARMWord op2, Condition cc = AL)
+ void sbc(int rd, int rn, ARMWord op2, Condition cc = AL)
{
emitInstruction(toARMWord(cc) | SBC, rd, rn, op2);
}
- void sbcs_r(int rd, int rn, ARMWord op2, Condition cc = AL)
+ void sbcs(int rd, int rn, ARMWord op2, Condition cc = AL)
{
emitInstruction(toARMWord(cc) | SBC | SetConditionalCodes, rd, rn, op2);
}
- void rsc_r(int rd, int rn, ARMWord op2, Condition cc = AL)
+ void rsc(int rd, int rn, ARMWord op2, Condition cc = AL)
{
emitInstruction(toARMWord(cc) | RSC, rd, rn, op2);
}
- void rscs_r(int rd, int rn, ARMWord op2, Condition cc = AL)
+ void rscs(int rd, int rn, ARMWord op2, Condition cc = AL)
{
emitInstruction(toARMWord(cc) | RSC | SetConditionalCodes, rd, rn, op2);
}
- void tst_r(int rn, ARMWord op2, Condition cc = AL)
+ void tst(int rn, ARMWord op2, Condition cc = AL)
{
emitInstruction(toARMWord(cc) | TST | SetConditionalCodes, 0, rn, op2);
}
- void teq_r(int rn, ARMWord op2, Condition cc = AL)
+ void teq(int rn, ARMWord op2, Condition cc = AL)
{
emitInstruction(toARMWord(cc) | TEQ | SetConditionalCodes, 0, rn, op2);
}
- void cmp_r(int rn, ARMWord op2, Condition cc = AL)
+ void cmp(int rn, ARMWord op2, Condition cc = AL)
{
emitInstruction(toARMWord(cc) | CMP | SetConditionalCodes, 0, rn, op2);
}
- void cmn_r(int rn, ARMWord op2, Condition cc = AL)
+ void cmn(int rn, ARMWord op2, Condition cc = AL)
{
emitInstruction(toARMWord(cc) | CMN | SetConditionalCodes, 0, rn, op2);
}
- void orr_r(int rd, int rn, ARMWord op2, Condition cc = AL)
+ void orr(int rd, int rn, ARMWord op2, Condition cc = AL)
{
emitInstruction(toARMWord(cc) | ORR, rd, rn, op2);
}
- void orrs_r(int rd, int rn, ARMWord op2, Condition cc = AL)
+ void orrs(int rd, int rn, ARMWord op2, Condition cc = AL)
{
emitInstruction(toARMWord(cc) | ORR | SetConditionalCodes, rd, rn, op2);
}
- void mov_r(int rd, ARMWord op2, Condition cc = AL)
+ void mov(int rd, ARMWord op2, Condition cc = AL)
{
emitInstruction(toARMWord(cc) | MOV, rd, ARMRegisters::r0, op2);
}
#if WTF_ARM_ARCH_AT_LEAST(7)
- void movw_r(int rd, ARMWord op2, Condition cc = AL)
+ void movw(int rd, ARMWord op2, Condition cc = AL)
{
ASSERT((op2 | 0xf0fff) == 0xf0fff);
m_buffer.putInt(toARMWord(cc) | MOVW | RD(rd) | op2);
}
- void movt_r(int rd, ARMWord op2, Condition cc = AL)
+ void movt(int rd, ARMWord op2, Condition cc = AL)
{
ASSERT((op2 | 0xf0fff) == 0xf0fff);
m_buffer.putInt(toARMWord(cc) | MOVT | RD(rd) | op2);
}
#endif
- void movs_r(int rd, ARMWord op2, Condition cc = AL)
+ void movs(int rd, ARMWord op2, Condition cc = AL)
{
emitInstruction(toARMWord(cc) | MOV | SetConditionalCodes, rd, ARMRegisters::r0, op2);
}
- void bic_r(int rd, int rn, ARMWord op2, Condition cc = AL)
+ void bic(int rd, int rn, ARMWord op2, Condition cc = AL)
{
emitInstruction(toARMWord(cc) | BIC, rd, rn, op2);
}
- void bics_r(int rd, int rn, ARMWord op2, Condition cc = AL)
+ void bics(int rd, int rn, ARMWord op2, Condition cc = AL)
{
emitInstruction(toARMWord(cc) | BIC | SetConditionalCodes, rd, rn, op2);
}
- void mvn_r(int rd, ARMWord op2, Condition cc = AL)
+ void mvn(int rd, ARMWord op2, Condition cc = AL)
{
emitInstruction(toARMWord(cc) | MVN, rd, ARMRegisters::r0, op2);
}
- void mvns_r(int rd, ARMWord op2, Condition cc = AL)
+ void mvns(int rd, ARMWord op2, Condition cc = AL)
{
emitInstruction(toARMWord(cc) | MVN | SetConditionalCodes, rd, ARMRegisters::r0, op2);
}
- void mul_r(int rd, int rn, int rm, Condition cc = AL)
+ void mul(int rd, int rn, int rm, Condition cc = AL)
{
m_buffer.putInt(toARMWord(cc) | MUL | RN(rd) | RS(rn) | RM(rm));
}
- void muls_r(int rd, int rn, int rm, Condition cc = AL)
+ void muls(int rd, int rn, int rm, Condition cc = AL)
{
m_buffer.putInt(toARMWord(cc) | MUL | SetConditionalCodes | RN(rd) | RS(rn) | RM(rm));
}
- void mull_r(int rdhi, int rdlo, int rn, int rm, Condition cc = AL)
+ void mull(int rdhi, int rdlo, int rn, int rm, Condition cc = AL)
{
m_buffer.putInt(toARMWord(cc) | MULL | RN(rdhi) | RD(rdlo) | RS(rn) | RM(rm));
}
- void vmov_f64_r(int dd, int dm, Condition cc = AL)
+ void vmov_f64(int dd, int dm, Condition cc = AL)
{
emitDoublePrecisionInstruction(toARMWord(cc) | VMOV_F64, dd, 0, dm);
}
- void vadd_f64_r(int dd, int dn, int dm, Condition cc = AL)
+ void vadd_f64(int dd, int dn, int dm, Condition cc = AL)
{
emitDoublePrecisionInstruction(toARMWord(cc) | VADD_F64, dd, dn, dm);
}
- void vdiv_f64_r(int dd, int dn, int dm, Condition cc = AL)
+ void vdiv_f64(int dd, int dn, int dm, Condition cc = AL)
{
emitDoublePrecisionInstruction(toARMWord(cc) | VDIV_F64, dd, dn, dm);
}
- void vsub_f64_r(int dd, int dn, int dm, Condition cc = AL)
+ void vsub_f64(int dd, int dn, int dm, Condition cc = AL)
{
emitDoublePrecisionInstruction(toARMWord(cc) | VSUB_F64, dd, dn, dm);
}
- void vmul_f64_r(int dd, int dn, int dm, Condition cc = AL)
+ void vmul_f64(int dd, int dn, int dm, Condition cc = AL)
{
emitDoublePrecisionInstruction(toARMWord(cc) | VMUL_F64, dd, dn, dm);
}
- void vcmp_f64_r(int dd, int dm, Condition cc = AL)
+ void vcmp_f64(int dd, int dm, Condition cc = AL)
{
emitDoublePrecisionInstruction(toARMWord(cc) | VCMP_F64, dd, 0, dm);
}
- void vsqrt_f64_r(int dd, int dm, Condition cc = AL)
+ void vsqrt_f64(int dd, int dm, Condition cc = AL)
{
emitDoublePrecisionInstruction(toARMWord(cc) | VSQRT_F64, dd, 0, dm);
}
- void vabs_f64_r(int dd, int dm, Condition cc = AL)
+ void vabs_f64(int dd, int dm, Condition cc = AL)
{
emitDoublePrecisionInstruction(toARMWord(cc) | VABS_F64, dd, 0, dm);
}
- void vneg_f64_r(int dd, int dm, Condition cc = AL)
+ void vneg_f64(int dd, int dm, Condition cc = AL)
{
emitDoublePrecisionInstruction(toARMWord(cc) | VNEG_F64, dd, 0, dm);
}
- void ldr_imm(int rd, ARMWord imm, Condition cc = AL)
+ void ldrImmediate(int rd, ARMWord imm, Condition cc = AL)
{
m_buffer.putIntWithConstantInt(toARMWord(cc) | LoadUint32 | DataTransferUp | RN(ARMRegisters::pc) | RD(rd), imm, true);
}
- void ldr_un_imm(int rd, ARMWord imm, Condition cc = AL)
+ void ldrUniqueImmediate(int rd, ARMWord imm, Condition cc = AL)
{
m_buffer.putIntWithConstantInt(toARMWord(cc) | LoadUint32 | DataTransferUp | RN(ARMRegisters::pc) | RD(rd), imm);
}
- void dtr_u(DataTransferTypeA transferType, int rd, int rb, ARMWord op2, Condition cc = AL)
+ void dtrUp(DataTransferTypeA transferType, int rd, int rb, ARMWord op2, Condition cc = AL)
{
emitInstruction(toARMWord(cc) | transferType | DataTransferUp, rd, rb, op2);
}
- void dtr_ur(DataTransferTypeA transferType, int rd, int rb, int rm, Condition cc = AL)
+ void dtrUpRegister(DataTransferTypeA transferType, int rd, int rb, int rm, Condition cc = AL)
{
emitInstruction(toARMWord(cc) | transferType | DataTransferUp | Op2IsRegisterArgument, rd, rb, rm);
}
- void dtr_d(DataTransferTypeA transferType, int rd, int rb, ARMWord op2, Condition cc = AL)
+ void dtrDown(DataTransferTypeA transferType, int rd, int rb, ARMWord op2, Condition cc = AL)
{
emitInstruction(toARMWord(cc) | transferType, rd, rb, op2);
}
- void dtr_dr(DataTransferTypeA transferType, int rd, int rb, int rm, Condition cc = AL)
+ void dtrDownRegister(DataTransferTypeA transferType, int rd, int rb, int rm, Condition cc = AL)
{
emitInstruction(toARMWord(cc) | transferType | Op2IsRegisterArgument, rd, rb, rm);
}
- void dtrh_u(DataTransferTypeB transferType, int rd, int rb, ARMWord op2, Condition cc = AL)
+ void halfDtrUp(DataTransferTypeB transferType, int rd, int rb, ARMWord op2, Condition cc = AL)
{
emitInstruction(toARMWord(cc) | transferType | DataTransferUp, rd, rb, op2);
}
- void dtrh_ur(DataTransferTypeB transferType, int rd, int rn, int rm, Condition cc = AL)
+ void halfDtrUpRegister(DataTransferTypeB transferType, int rd, int rn, int rm, Condition cc = AL)
{
emitInstruction(toARMWord(cc) | transferType | DataTransferUp, rd, rn, rm);
}
- void dtrh_d(DataTransferTypeB transferType, int rd, int rb, ARMWord op2, Condition cc = AL)
+ void halfDtrDown(DataTransferTypeB transferType, int rd, int rb, ARMWord op2, Condition cc = AL)
{
emitInstruction(toARMWord(cc) | transferType, rd, rb, op2);
}
- void dtrh_dr(DataTransferTypeB transferType, int rd, int rn, int rm, Condition cc = AL)
+ void halfDtrDownRegister(DataTransferTypeB transferType, int rd, int rn, int rm, Condition cc = AL)
{
emitInstruction(toARMWord(cc) | transferType, rd, rn, rm);
}
- void fdtr_u(DataTransferTypeFloat type, int rd, int rb, ARMWord op2, Condition cc = AL)
+ void doubleDtrUp(DataTransferTypeFloat type, int rd, int rb, ARMWord op2, Condition cc = AL)
{
ASSERT(op2 <= 0xff && rd <= 15);
/* Only d0-d15 and s0, s2, s4 ... s30 are supported. */
m_buffer.putInt(toARMWord(cc) | DataTransferUp | type | (rd << 12) | RN(rb) | op2);
}
- void fdtr_d(DataTransferTypeFloat type, int rd, int rb, ARMWord op2, Condition cc = AL)
+ void doubleDtrDown(DataTransferTypeFloat type, int rd, int rb, ARMWord op2, Condition cc = AL)
{
ASSERT(op2 <= 0xff && rd <= 15);
/* Only d0-d15 and s0, s2, s4 ... s30 are supported. */
m_buffer.putInt(toARMWord(cc) | type | (rd << 12) | RN(rb) | op2);
}
- void push_r(int reg, Condition cc = AL)
+ void push(int reg, Condition cc = AL)
{
ASSERT(ARMWord(reg) <= 0xf);
m_buffer.putInt(toARMWord(cc) | StoreUint32 | DataTransferWriteBack | RN(ARMRegisters::sp) | RD(reg) | 0x4);
}
- void pop_r(int reg, Condition cc = AL)
+ void pop(int reg, Condition cc = AL)
{
ASSERT(ARMWord(reg) <= 0xf);
m_buffer.putInt(toARMWord(cc) | (LoadUint32 ^ DataTransferPostUpdate) | DataTransferUp | RN(ARMRegisters::sp) | RD(reg) | 0x4);
}
- inline void poke_r(int reg, Condition cc = AL)
+ inline void poke(int reg, Condition cc = AL)
{
- dtr_d(StoreUint32, ARMRegisters::sp, 0, reg, cc);
+ dtrDown(StoreUint32, ARMRegisters::sp, 0, reg, cc);
}
- inline void peek_r(int reg, Condition cc = AL)
+ inline void peek(int reg, Condition cc = AL)
{
- dtr_u(LoadUint32, reg, ARMRegisters::sp, 0, cc);
+ dtrUp(LoadUint32, reg, ARMRegisters::sp, 0, cc);
}
- void vmov_vfp64_r(int sm, int rt, int rt2, Condition cc = AL)
+ void vmov_vfp64(int sm, int rt, int rt2, Condition cc = AL)
{
ASSERT(rt != rt2);
m_buffer.putInt(toARMWord(cc) | VMOV_VFP64 | RN(rt2) | RD(rt) | (sm & 0xf) | ((sm & 0x10) << (5 - 4)));
}
- void vmov_arm64_r(int rt, int rt2, int sm, Condition cc = AL)
+ void vmov_arm64(int rt, int rt2, int sm, Condition cc = AL)
{
ASSERT(rt != rt2);
m_buffer.putInt(toARMWord(cc) | VMOV_ARM64 | RN(rt2) | RD(rt) | (sm & 0xf) | ((sm & 0x10) << (5 - 4)));
}
- void vmov_vfp32_r(int sn, int rt, Condition cc = AL)
+ void vmov_vfp32(int sn, int rt, Condition cc = AL)
{
ASSERT(rt <= 15);
emitSinglePrecisionInstruction(toARMWord(cc) | VMOV_VFP32, rt << 1, sn, 0);
}
- void vmov_arm32_r(int rt, int sn, Condition cc = AL)
+ void vmov_arm32(int rt, int sn, Condition cc = AL)
{
ASSERT(rt <= 15);
emitSinglePrecisionInstruction(toARMWord(cc) | VMOV_ARM32, rt << 1, sn, 0);
}
- void vcvt_f64_s32_r(int dd, int sm, Condition cc = AL)
+ void vcvt_f64_s32(int dd, int sm, Condition cc = AL)
{
ASSERT(!(sm & 0x1)); // sm must be divisible by 2
emitDoublePrecisionInstruction(toARMWord(cc) | VCVT_F64_S32, dd, 0, (sm >> 1));
}
- void vcvt_s32_f64_r(int sd, int dm, Condition cc = AL)
+ void vcvt_s32_f64(int sd, int dm, Condition cc = AL)
{
ASSERT(!(sd & 0x1)); // sd must be divisible by 2
emitDoublePrecisionInstruction(toARMWord(cc) | VCVT_S32_F64, (sd >> 1), 0, dm);
}
- void vcvt_u32_f64_r(int sd, int dm, Condition cc = AL)
+ void vcvt_u32_f64(int sd, int dm, Condition cc = AL)
{
ASSERT(!(sd & 0x1)); // sd must be divisible by 2
emitDoublePrecisionInstruction(toARMWord(cc) | VCVT_U32_F64, (sd >> 1), 0, dm);
}
- void vcvt_f64_f32_r(int dd, int sm, Condition cc = AL)
+ void vcvt_f64_f32(int dd, int sm, Condition cc = AL)
{
ASSERT(dd <= 15 && sm <= 15);
emitDoublePrecisionInstruction(toARMWord(cc) | VCVT_F64_F32, dd, 0, sm);
}
- void vcvt_f32_f64_r(int dd, int sm, Condition cc = AL)
+ void vcvt_f32_f64(int dd, int sm, Condition cc = AL)
{
ASSERT(dd <= 15 && sm <= 15);
emitDoublePrecisionInstruction(toARMWord(cc) | VCVT_F32_F64, dd, 0, sm);
@@ -627,7 +627,7 @@ namespace JSC {
m_buffer.putInt(toARMWord(cc) | VMRS_APSR);
}
- void clz_r(int rd, int rm, Condition cc = AL)
+ void clz(int rd, int rm, Condition cc = AL)
{
m_buffer.putInt(toARMWord(cc) | CLZ | RD(rd) | RM(rm));
}
@@ -674,21 +674,21 @@ namespace JSC {
return reg | (value << 7) | 0x40;
}
- static ARMWord lsl_r(int reg, int shiftReg)
+ static ARMWord lslRegister(int reg, int shiftReg)
{
ASSERT(reg <= ARMRegisters::pc);
ASSERT(shiftReg <= ARMRegisters::pc);
return reg | (shiftReg << 8) | 0x10;
}
- static ARMWord lsr_r(int reg, int shiftReg)
+ static ARMWord lsrRegister(int reg, int shiftReg)
{
ASSERT(reg <= ARMRegisters::pc);
ASSERT(shiftReg <= ARMRegisters::pc);
return reg | (shiftReg << 8) | 0x30;
}
- static ARMWord asr_r(int reg, int shiftReg)
+ static ARMWord asrRegister(int reg, int shiftReg)
{
ASSERT(reg <= ARMRegisters::pc);
ASSERT(shiftReg <= ARMRegisters::pc);
@@ -742,7 +742,7 @@ namespace JSC {
AssemblerLabel align(int alignment)
{
while (!m_buffer.isAligned(alignment))
- mov_r(ARMRegisters::r0, ARMRegisters::r0);
+ mov(ARMRegisters::r0, ARMRegisters::r0);
return label();
}
@@ -751,7 +751,7 @@ namespace JSC {
{
ensureSpace(sizeof(ARMWord), sizeof(ARMWord));
m_jumps.append(m_buffer.codeSize() | (useConstantPool & 0x1));
- ldr_un_imm(rd, InvalidBranchTarget, cc);
+ ldrUniqueImmediate(rd, InvalidBranchTarget, cc);
return m_buffer.label();
}
@@ -767,12 +767,12 @@ namespace JSC {
// DFG assembly helpers for moving data between fp and registers.
void vmov(RegisterID rd1, RegisterID rd2, FPRegisterID rn)
{
- vmov_arm64_r(rd1, rd2, rn);
+ vmov_arm64(rd1, rd2, rn);
}
void vmov(FPRegisterID rd, RegisterID rn1, RegisterID rn2)
{
- vmov_vfp64_r(rd, rn1, rn2);
+ vmov_vfp64(rd, rn1, rn2);
}
// Patching helpers
diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerARM.cpp b/Source/JavaScriptCore/assembler/MacroAssemblerARM.cpp
index a251a4376..98dc3e987 100644
--- a/Source/JavaScriptCore/assembler/MacroAssemblerARM.cpp
+++ b/Source/JavaScriptCore/assembler/MacroAssemblerARM.cpp
@@ -76,21 +76,21 @@ void MacroAssemblerARM::load32WithUnalignedHalfWords(BaseIndex address, Register
op2 = m_assembler.lsl(address.index, static_cast<int>(address.scale));
if (address.offset >= 0 && address.offset + 0x2 <= 0xff) {
- m_assembler.add_r(ARMRegisters::S0, address.base, op2);
- m_assembler.dtrh_u(ARMAssembler::LoadUint16, dest, ARMRegisters::S0, ARMAssembler::getOp2Half(address.offset));
- m_assembler.dtrh_u(ARMAssembler::LoadUint16, ARMRegisters::S0, ARMRegisters::S0, ARMAssembler::getOp2Half(address.offset + 0x2));
+ m_assembler.add(ARMRegisters::S0, address.base, op2);
+ m_assembler.halfDtrUp(ARMAssembler::LoadUint16, dest, ARMRegisters::S0, ARMAssembler::getOp2Half(address.offset));
+ m_assembler.halfDtrUp(ARMAssembler::LoadUint16, ARMRegisters::S0, ARMRegisters::S0, ARMAssembler::getOp2Half(address.offset + 0x2));
} else if (address.offset < 0 && address.offset >= -0xff) {
- m_assembler.add_r(ARMRegisters::S0, address.base, op2);
- m_assembler.dtrh_d(ARMAssembler::LoadUint16, dest, ARMRegisters::S0, ARMAssembler::getOp2Half(-address.offset));
- m_assembler.dtrh_d(ARMAssembler::LoadUint16, ARMRegisters::S0, ARMRegisters::S0, ARMAssembler::getOp2Half(-address.offset - 0x2));
+ m_assembler.add(ARMRegisters::S0, address.base, op2);
+ m_assembler.halfDtrDown(ARMAssembler::LoadUint16, dest, ARMRegisters::S0, ARMAssembler::getOp2Half(-address.offset));
+ m_assembler.halfDtrDown(ARMAssembler::LoadUint16, ARMRegisters::S0, ARMRegisters::S0, ARMAssembler::getOp2Half(-address.offset - 0x2));
} else {
m_assembler.moveImm(address.offset, ARMRegisters::S0);
- m_assembler.add_r(ARMRegisters::S0, ARMRegisters::S0, op2);
- m_assembler.dtrh_ur(ARMAssembler::LoadUint16, dest, address.base, ARMRegisters::S0);
- m_assembler.add_r(ARMRegisters::S0, ARMRegisters::S0, ARMAssembler::Op2Immediate | 0x2);
- m_assembler.dtrh_ur(ARMAssembler::LoadUint16, ARMRegisters::S0, address.base, ARMRegisters::S0);
+ m_assembler.add(ARMRegisters::S0, ARMRegisters::S0, op2);
+ m_assembler.halfDtrUpRegister(ARMAssembler::LoadUint16, dest, address.base, ARMRegisters::S0);
+ m_assembler.add(ARMRegisters::S0, ARMRegisters::S0, ARMAssembler::Op2Immediate | 0x2);
+ m_assembler.halfDtrUpRegister(ARMAssembler::LoadUint16, ARMRegisters::S0, address.base, ARMRegisters::S0);
}
- m_assembler.orr_r(dest, dest, m_assembler.lsl(ARMRegisters::S0, 16));
+ m_assembler.orr(dest, dest, m_assembler.lsl(ARMRegisters::S0, 16));
}
#endif
diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerARM.h b/Source/JavaScriptCore/assembler/MacroAssemblerARM.h
index 85d0ffbcc..295354119 100644
--- a/Source/JavaScriptCore/assembler/MacroAssemblerARM.h
+++ b/Source/JavaScriptCore/assembler/MacroAssemblerARM.h
@@ -86,12 +86,12 @@ public:
void add32(RegisterID src, RegisterID dest)
{
- m_assembler.adds_r(dest, dest, src);
+ m_assembler.adds(dest, dest, src);
}
void add32(RegisterID op1, RegisterID op2, RegisterID dest)
{
- m_assembler.adds_r(dest, op1, op2);
+ m_assembler.adds(dest, op1, op2);
}
void add32(TrustedImm32 imm, Address address)
@@ -103,13 +103,13 @@ public:
void add32(TrustedImm32 imm, RegisterID dest)
{
- m_assembler.adds_r(dest, dest, m_assembler.getImm(imm.m_value, ARMRegisters::S0));
+ m_assembler.adds(dest, dest, m_assembler.getImm(imm.m_value, ARMRegisters::S0));
}
void add32(AbsoluteAddress src, RegisterID dest)
{
move(TrustedImmPtr(src.m_ptr), ARMRegisters::S1);
- m_assembler.dtr_u(ARMAssembler::LoadUint32, ARMRegisters::S1, ARMRegisters::S1, 0);
+ m_assembler.dtrUp(ARMAssembler::LoadUint32, ARMRegisters::S1, ARMRegisters::S1, 0);
add32(ARMRegisters::S1, dest);
}
@@ -121,35 +121,35 @@ public:
void add32(RegisterID src, TrustedImm32 imm, RegisterID dest)
{
- m_assembler.adds_r(dest, src, m_assembler.getImm(imm.m_value, ARMRegisters::S0));
+ m_assembler.adds(dest, src, m_assembler.getImm(imm.m_value, ARMRegisters::S0));
}
void and32(RegisterID src, RegisterID dest)
{
- m_assembler.ands_r(dest, dest, src);
+ m_assembler.bitAnds(dest, dest, src);
}
void and32(RegisterID op1, RegisterID op2, RegisterID dest)
{
- m_assembler.ands_r(dest, op1, op2);
+ m_assembler.bitAnds(dest, op1, op2);
}
void and32(TrustedImm32 imm, RegisterID dest)
{
ARMWord w = m_assembler.getImm(imm.m_value, ARMRegisters::S0, true);
if (w & ARMAssembler::Op2InvertedImmediate)
- m_assembler.bics_r(dest, dest, w & ~ARMAssembler::Op2InvertedImmediate);
+ m_assembler.bics(dest, dest, w & ~ARMAssembler::Op2InvertedImmediate);
else
- m_assembler.ands_r(dest, dest, w);
+ m_assembler.bitAnds(dest, dest, w);
}
void and32(TrustedImm32 imm, RegisterID src, RegisterID dest)
{
ARMWord w = m_assembler.getImm(imm.m_value, ARMRegisters::S0, true);
if (w & ARMAssembler::Op2InvertedImmediate)
- m_assembler.bics_r(dest, src, w & ~ARMAssembler::Op2InvertedImmediate);
+ m_assembler.bics(dest, src, w & ~ARMAssembler::Op2InvertedImmediate);
else
- m_assembler.ands_r(dest, src, w);
+ m_assembler.bitAnds(dest, src, w);
}
void lshift32(RegisterID shiftAmount, RegisterID dest)
@@ -160,19 +160,19 @@ public:
void lshift32(RegisterID src, RegisterID shiftAmount, RegisterID dest)
{
ARMWord w = ARMAssembler::getOp2Byte(0x1f);
- m_assembler.and_r(ARMRegisters::S0, shiftAmount, w);
+ m_assembler.bitAnd(ARMRegisters::S0, shiftAmount, w);
- m_assembler.movs_r(dest, m_assembler.lsl_r(src, ARMRegisters::S0));
+ m_assembler.movs(dest, m_assembler.lslRegister(src, ARMRegisters::S0));
}
void lshift32(TrustedImm32 imm, RegisterID dest)
{
- m_assembler.movs_r(dest, m_assembler.lsl(dest, imm.m_value & 0x1f));
+ m_assembler.movs(dest, m_assembler.lsl(dest, imm.m_value & 0x1f));
}
void lshift32(RegisterID src, TrustedImm32 imm, RegisterID dest)
{
- m_assembler.movs_r(dest, m_assembler.lsl(src, imm.m_value & 0x1f));
+ m_assembler.movs(dest, m_assembler.lsl(src, imm.m_value & 0x1f));
}
void mul32(RegisterID op1, RegisterID op2, RegisterID dest)
@@ -188,7 +188,7 @@ public:
op2 = tmp;
}
}
- m_assembler.muls_r(dest, op1, op2);
+ m_assembler.muls(dest, op1, op2);
}
void mul32(RegisterID src, RegisterID dest)
@@ -199,32 +199,32 @@ public:
void mul32(TrustedImm32 imm, RegisterID src, RegisterID dest)
{
move(imm, ARMRegisters::S0);
- m_assembler.muls_r(dest, src, ARMRegisters::S0);
+ m_assembler.muls(dest, src, ARMRegisters::S0);
}
void neg32(RegisterID srcDest)
{
- m_assembler.rsbs_r(srcDest, srcDest, ARMAssembler::getOp2Byte(0));
+ m_assembler.rsbs(srcDest, srcDest, ARMAssembler::getOp2Byte(0));
}
void or32(RegisterID src, RegisterID dest)
{
- m_assembler.orrs_r(dest, dest, src);
+ m_assembler.orrs(dest, dest, src);
}
void or32(TrustedImm32 imm, RegisterID dest)
{
- m_assembler.orrs_r(dest, dest, m_assembler.getImm(imm.m_value, ARMRegisters::S0));
+ m_assembler.orrs(dest, dest, m_assembler.getImm(imm.m_value, ARMRegisters::S0));
}
void or32(TrustedImm32 imm, RegisterID src, RegisterID dest)
{
- m_assembler.orrs_r(dest, src, m_assembler.getImm(imm.m_value, ARMRegisters::S0));
+ m_assembler.orrs(dest, src, m_assembler.getImm(imm.m_value, ARMRegisters::S0));
}
void or32(RegisterID op1, RegisterID op2, RegisterID dest)
{
- m_assembler.orrs_r(dest, op1, op2);
+ m_assembler.orrs(dest, op1, op2);
}
void rshift32(RegisterID shiftAmount, RegisterID dest)
@@ -235,9 +235,9 @@ public:
void rshift32(RegisterID src, RegisterID shiftAmount, RegisterID dest)
{
ARMWord w = ARMAssembler::getOp2Byte(0x1f);
- m_assembler.and_r(ARMRegisters::S0, shiftAmount, w);
+ m_assembler.bitAnd(ARMRegisters::S0, shiftAmount, w);
- m_assembler.movs_r(dest, m_assembler.asr_r(src, ARMRegisters::S0));
+ m_assembler.movs(dest, m_assembler.asrRegister(src, ARMRegisters::S0));
}
void rshift32(TrustedImm32 imm, RegisterID dest)
@@ -247,7 +247,7 @@ public:
void rshift32(RegisterID src, TrustedImm32 imm, RegisterID dest)
{
- m_assembler.movs_r(dest, m_assembler.asr(src, imm.m_value & 0x1f));
+ m_assembler.movs(dest, m_assembler.asr(src, imm.m_value & 0x1f));
}
void urshift32(RegisterID shiftAmount, RegisterID dest)
@@ -258,29 +258,29 @@ public:
void urshift32(RegisterID src, RegisterID shiftAmount, RegisterID dest)
{
ARMWord w = ARMAssembler::getOp2Byte(0x1f);
- m_assembler.and_r(ARMRegisters::S0, shiftAmount, w);
+ m_assembler.bitAnd(ARMRegisters::S0, shiftAmount, w);
- m_assembler.movs_r(dest, m_assembler.lsr_r(src, ARMRegisters::S0));
+ m_assembler.movs(dest, m_assembler.lsrRegister(src, ARMRegisters::S0));
}
void urshift32(TrustedImm32 imm, RegisterID dest)
{
- m_assembler.movs_r(dest, m_assembler.lsr(dest, imm.m_value & 0x1f));
+ m_assembler.movs(dest, m_assembler.lsr(dest, imm.m_value & 0x1f));
}
void urshift32(RegisterID src, TrustedImm32 imm, RegisterID dest)
{
- m_assembler.movs_r(dest, m_assembler.lsr(src, imm.m_value & 0x1f));
+ m_assembler.movs(dest, m_assembler.lsr(src, imm.m_value & 0x1f));
}
void sub32(RegisterID src, RegisterID dest)
{
- m_assembler.subs_r(dest, dest, src);
+ m_assembler.subs(dest, dest, src);
}
void sub32(TrustedImm32 imm, RegisterID dest)
{
- m_assembler.subs_r(dest, dest, m_assembler.getImm(imm.m_value, ARMRegisters::S0));
+ m_assembler.subs(dest, dest, m_assembler.getImm(imm.m_value, ARMRegisters::S0));
}
void sub32(TrustedImm32 imm, Address address)
@@ -298,39 +298,39 @@ public:
void sub32(RegisterID src, TrustedImm32 imm, RegisterID dest)
{
- m_assembler.subs_r(dest, src, m_assembler.getImm(imm.m_value, ARMRegisters::S0));
+ m_assembler.subs(dest, src, m_assembler.getImm(imm.m_value, ARMRegisters::S0));
}
void xor32(RegisterID src, RegisterID dest)
{
- m_assembler.eors_r(dest, dest, src);
+ m_assembler.eors(dest, dest, src);
}
void xor32(RegisterID op1, RegisterID op2, RegisterID dest)
{
- m_assembler.eors_r(dest, op1, op2);
+ m_assembler.eors(dest, op1, op2);
}
void xor32(TrustedImm32 imm, RegisterID dest)
{
if (imm.m_value == -1)
- m_assembler.mvns_r(dest, dest);
+ m_assembler.mvns(dest, dest);
else
- m_assembler.eors_r(dest, dest, m_assembler.getImm(imm.m_value, ARMRegisters::S0));
+ m_assembler.eors(dest, dest, m_assembler.getImm(imm.m_value, ARMRegisters::S0));
}
void xor32(TrustedImm32 imm, RegisterID src, RegisterID dest)
{
if (imm.m_value == -1)
- m_assembler.mvns_r(dest, src);
+ m_assembler.mvns(dest, src);
else
- m_assembler.eors_r(dest, src, m_assembler.getImm(imm.m_value, ARMRegisters::S0));
+ m_assembler.eors(dest, src, m_assembler.getImm(imm.m_value, ARMRegisters::S0));
}
void countLeadingZeros32(RegisterID src, RegisterID dest)
{
#if WTF_ARM_ARCH_AT_LEAST(5)
- m_assembler.clz_r(dest, src);
+ m_assembler.clz(dest, src);
#else
UNUSED_PARAM(src);
UNUSED_PARAM(dest);
@@ -396,15 +396,15 @@ public:
{
ConvertibleLoadLabel result(this);
ASSERT(address.offset >= 0 && address.offset <= 255);
- m_assembler.dtr_u(ARMAssembler::LoadUint32, dest, address.base, address.offset);
+ m_assembler.dtrUp(ARMAssembler::LoadUint32, dest, address.base, address.offset);
return result;
}
DataLabel32 load32WithAddressOffsetPatch(Address address, RegisterID dest)
{
DataLabel32 dataLabel(this);
- m_assembler.ldr_un_imm(ARMRegisters::S0, 0);
- m_assembler.dtr_ur(ARMAssembler::LoadUint32, dest, address.base, ARMRegisters::S0);
+ m_assembler.ldrUniqueImmediate(ARMRegisters::S0, 0);
+ m_assembler.dtrUpRegister(ARMAssembler::LoadUint32, dest, address.base, ARMRegisters::S0);
return dataLabel;
}
@@ -418,17 +418,17 @@ public:
DataLabelCompact dataLabel(this);
ASSERT(isCompactPtrAlignedAddressOffset(address.offset));
if (address.offset >= 0)
- m_assembler.dtr_u(ARMAssembler::LoadUint32, dest, address.base, address.offset);
+ m_assembler.dtrUp(ARMAssembler::LoadUint32, dest, address.base, address.offset);
else
- m_assembler.dtr_d(ARMAssembler::LoadUint32, dest, address.base, address.offset);
+ m_assembler.dtrDown(ARMAssembler::LoadUint32, dest, address.base, address.offset);
return dataLabel;
}
DataLabel32 store32WithAddressOffsetPatch(RegisterID src, Address address)
{
DataLabel32 dataLabel(this);
- m_assembler.ldr_un_imm(ARMRegisters::S0, 0);
- m_assembler.dtr_ur(ARMAssembler::StoreUint32, src, address.base, ARMRegisters::S0);
+ m_assembler.ldrUniqueImmediate(ARMRegisters::S0, 0);
+ m_assembler.dtrUpRegister(ARMAssembler::StoreUint32, src, address.base, ARMRegisters::S0);
return dataLabel;
}
@@ -466,25 +466,25 @@ public:
void store32(RegisterID src, void* address)
{
- m_assembler.ldr_un_imm(ARMRegisters::S0, reinterpret_cast<ARMWord>(address));
- m_assembler.dtr_u(ARMAssembler::StoreUint32, src, ARMRegisters::S0, 0);
+ m_assembler.ldrUniqueImmediate(ARMRegisters::S0, reinterpret_cast<ARMWord>(address));
+ m_assembler.dtrUp(ARMAssembler::StoreUint32, src, ARMRegisters::S0, 0);
}
void store32(TrustedImm32 imm, void* address)
{
- m_assembler.ldr_un_imm(ARMRegisters::S0, reinterpret_cast<ARMWord>(address));
+ m_assembler.ldrUniqueImmediate(ARMRegisters::S0, reinterpret_cast<ARMWord>(address));
m_assembler.moveImm(imm.m_value, ARMRegisters::S1);
- m_assembler.dtr_u(ARMAssembler::StoreUint32, ARMRegisters::S1, ARMRegisters::S0, 0);
+ m_assembler.dtrUp(ARMAssembler::StoreUint32, ARMRegisters::S1, ARMRegisters::S0, 0);
}
void pop(RegisterID dest)
{
- m_assembler.pop_r(dest);
+ m_assembler.pop(dest);
}
void push(RegisterID src)
{
- m_assembler.push_r(src);
+ m_assembler.push(src);
}
void push(Address address)
@@ -507,7 +507,7 @@ public:
void move(RegisterID src, RegisterID dest)
{
if (src != dest)
- m_assembler.mov_r(dest, src);
+ m_assembler.mov(dest, src);
}
void move(TrustedImmPtr imm, RegisterID dest)
@@ -517,9 +517,9 @@ public:
void swap(RegisterID reg1, RegisterID reg2)
{
- m_assembler.mov_r(ARMRegisters::S0, reg1);
- m_assembler.mov_r(reg1, reg2);
- m_assembler.mov_r(reg2, ARMRegisters::S0);
+ m_assembler.mov(ARMRegisters::S0, reg1);
+ m_assembler.mov(reg1, reg2);
+ m_assembler.mov(reg2, ARMRegisters::S0);
}
void signExtend32ToPtr(RegisterID src, RegisterID dest)
@@ -549,7 +549,7 @@ public:
Jump branch32(RelationalCondition cond, RegisterID left, RegisterID right, int useConstantPool = 0)
{
- m_assembler.cmp_r(left, right);
+ m_assembler.cmp(left, right);
return Jump(m_assembler.jmp(ARMCondition(cond), useConstantPool));
}
@@ -557,9 +557,9 @@ public:
{
ARMWord tmp = (right.m_value == 0x80000000) ? ARMAssembler::InvalidImmediate : m_assembler.getOp2(-right.m_value);
if (tmp != ARMAssembler::InvalidImmediate)
- m_assembler.cmn_r(left, tmp);
+ m_assembler.cmn(left, tmp);
else
- m_assembler.cmp_r(left, m_assembler.getImm(right.m_value, ARMRegisters::S0));
+ m_assembler.cmp(left, m_assembler.getImm(right.m_value, ARMRegisters::S0));
return Jump(m_assembler.jmp(ARMCondition(cond), useConstantPool));
}
@@ -609,7 +609,7 @@ public:
Jump branchTest32(ResultCondition cond, RegisterID reg, RegisterID mask)
{
ASSERT((cond == Zero) || (cond == NonZero));
- m_assembler.tst_r(reg, mask);
+ m_assembler.tst(reg, mask);
return Jump(m_assembler.jmp(ARMCondition(cond)));
}
@@ -618,9 +618,9 @@ public:
ASSERT((cond == Zero) || (cond == NonZero));
ARMWord w = m_assembler.getImm(mask.m_value, ARMRegisters::S0, true);
if (w & ARMAssembler::Op2InvertedImmediate)
- m_assembler.bics_r(ARMRegisters::S0, reg, w & ~ARMAssembler::Op2InvertedImmediate);
+ m_assembler.bics(ARMRegisters::S0, reg, w & ~ARMAssembler::Op2InvertedImmediate);
else
- m_assembler.tst_r(reg, w);
+ m_assembler.tst(reg, w);
return Jump(m_assembler.jmp(ARMCondition(cond)));
}
@@ -705,8 +705,8 @@ public:
op2 = tmp;
}
}
- m_assembler.mull_r(ARMRegisters::S1, dest, op1, op2);
- m_assembler.cmp_r(ARMRegisters::S1, m_assembler.asr(dest, 31));
+ m_assembler.mull(ARMRegisters::S1, dest, op1, op2);
+ m_assembler.cmp(ARMRegisters::S1, m_assembler.asr(dest, 31));
}
Jump branchMul32(ResultCondition cond, RegisterID src1, RegisterID src2, RegisterID dest)
@@ -763,7 +763,7 @@ public:
Jump branchSub32(ResultCondition cond, RegisterID op1, RegisterID op2, RegisterID dest)
{
ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
- m_assembler.subs_r(dest, op1, op2);
+ m_assembler.subs(dest, op1, op2);
return Jump(m_assembler.jmp(ARMCondition(cond)));
}
@@ -809,16 +809,16 @@ public:
void compare32(RelationalCondition cond, RegisterID left, RegisterID right, RegisterID dest)
{
- m_assembler.cmp_r(left, right);
- m_assembler.mov_r(dest, ARMAssembler::getOp2Byte(0));
- m_assembler.mov_r(dest, ARMAssembler::getOp2Byte(1), ARMCondition(cond));
+ m_assembler.cmp(left, right);
+ m_assembler.mov(dest, ARMAssembler::getOp2Byte(0));
+ m_assembler.mov(dest, ARMAssembler::getOp2Byte(1), ARMCondition(cond));
}
void compare32(RelationalCondition cond, RegisterID left, TrustedImm32 right, RegisterID dest)
{
- m_assembler.cmp_r(left, m_assembler.getImm(right.m_value, ARMRegisters::S0));
- m_assembler.mov_r(dest, ARMAssembler::getOp2Byte(0));
- m_assembler.mov_r(dest, ARMAssembler::getOp2Byte(1), ARMCondition(cond));
+ m_assembler.cmp(left, m_assembler.getImm(right.m_value, ARMRegisters::S0));
+ m_assembler.mov(dest, ARMAssembler::getOp2Byte(0));
+ m_assembler.mov(dest, ARMAssembler::getOp2Byte(1), ARMCondition(cond));
}
void compare8(RelationalCondition cond, Address left, TrustedImm32 right, RegisterID dest)
@@ -830,11 +830,11 @@ public:
void test32(ResultCondition cond, RegisterID reg, TrustedImm32 mask, RegisterID dest)
{
if (mask.m_value == -1)
- m_assembler.cmp_r(0, reg);
+ m_assembler.cmp(0, reg);
else
- m_assembler.tst_r(reg, m_assembler.getImm(mask.m_value, ARMRegisters::S0));
- m_assembler.mov_r(dest, ARMAssembler::getOp2Byte(0));
- m_assembler.mov_r(dest, ARMAssembler::getOp2Byte(1), ARMCondition(cond));
+ m_assembler.tst(reg, m_assembler.getImm(mask.m_value, ARMRegisters::S0));
+ m_assembler.mov(dest, ARMAssembler::getOp2Byte(0));
+ m_assembler.mov(dest, ARMAssembler::getOp2Byte(1), ARMCondition(cond));
}
void test32(ResultCondition cond, Address address, TrustedImm32 mask, RegisterID dest)
@@ -851,31 +851,31 @@ public:
void add32(TrustedImm32 imm, RegisterID src, RegisterID dest)
{
- m_assembler.add_r(dest, src, m_assembler.getImm(imm.m_value, ARMRegisters::S0));
+ m_assembler.add(dest, src, m_assembler.getImm(imm.m_value, ARMRegisters::S0));
}
void add32(TrustedImm32 imm, AbsoluteAddress address)
{
- m_assembler.ldr_un_imm(ARMRegisters::S1, reinterpret_cast<ARMWord>(address.m_ptr));
- m_assembler.dtr_u(ARMAssembler::LoadUint32, ARMRegisters::S1, ARMRegisters::S1, 0);
+ m_assembler.ldrUniqueImmediate(ARMRegisters::S1, reinterpret_cast<ARMWord>(address.m_ptr));
+ m_assembler.dtrUp(ARMAssembler::LoadUint32, ARMRegisters::S1, ARMRegisters::S1, 0);
add32(imm, ARMRegisters::S1);
- m_assembler.ldr_un_imm(ARMRegisters::S0, reinterpret_cast<ARMWord>(address.m_ptr));
- m_assembler.dtr_u(ARMAssembler::StoreUint32, ARMRegisters::S1, ARMRegisters::S0, 0);
+ m_assembler.ldrUniqueImmediate(ARMRegisters::S0, reinterpret_cast<ARMWord>(address.m_ptr));
+ m_assembler.dtrUp(ARMAssembler::StoreUint32, ARMRegisters::S1, ARMRegisters::S0, 0);
}
void sub32(TrustedImm32 imm, AbsoluteAddress address)
{
- m_assembler.ldr_un_imm(ARMRegisters::S1, reinterpret_cast<ARMWord>(address.m_ptr));
- m_assembler.dtr_u(ARMAssembler::LoadUint32, ARMRegisters::S1, ARMRegisters::S1, 0);
+ m_assembler.ldrUniqueImmediate(ARMRegisters::S1, reinterpret_cast<ARMWord>(address.m_ptr));
+ m_assembler.dtrUp(ARMAssembler::LoadUint32, ARMRegisters::S1, ARMRegisters::S1, 0);
sub32(imm, ARMRegisters::S1);
- m_assembler.ldr_un_imm(ARMRegisters::S0, reinterpret_cast<ARMWord>(address.m_ptr));
- m_assembler.dtr_u(ARMAssembler::StoreUint32, ARMRegisters::S1, ARMRegisters::S0, 0);
+ m_assembler.ldrUniqueImmediate(ARMRegisters::S0, reinterpret_cast<ARMWord>(address.m_ptr));
+ m_assembler.dtrUp(ARMAssembler::StoreUint32, ARMRegisters::S1, ARMRegisters::S0, 0);
}
void load32(const void* address, RegisterID dest)
{
- m_assembler.ldr_un_imm(ARMRegisters::S0, reinterpret_cast<ARMWord>(address));
- m_assembler.dtr_u(ARMAssembler::LoadUint32, dest, ARMRegisters::S0, 0);
+ m_assembler.ldrUniqueImmediate(ARMRegisters::S0, reinterpret_cast<ARMWord>(address));
+ m_assembler.dtrUp(ARMAssembler::LoadUint32, dest, ARMRegisters::S0, 0);
}
Jump branch32(RelationalCondition cond, AbsoluteAddress left, RegisterID right)
@@ -893,10 +893,10 @@ public:
void relativeTableJump(RegisterID index, int scale)
{
ASSERT(scale >= 0 && scale <= 31);
- m_assembler.add_r(ARMRegisters::pc, ARMRegisters::pc, m_assembler.lsl(index, scale));
+ m_assembler.add(ARMRegisters::pc, ARMRegisters::pc, m_assembler.lsl(index, scale));
// NOP the default prefetching
- m_assembler.mov_r(ARMRegisters::r0, ARMRegisters::r0);
+ m_assembler.mov(ARMRegisters::r0, ARMRegisters::r0);
}
Call call()
@@ -919,7 +919,7 @@ public:
DataLabelPtr moveWithPatch(TrustedImmPtr initialValue, RegisterID dest)
{
DataLabelPtr dataLabel(this);
- m_assembler.ldr_un_imm(dest, reinterpret_cast<ARMWord>(initialValue.m_value));
+ m_assembler.ldrUniqueImmediate(dest, reinterpret_cast<ARMWord>(initialValue.m_value));
return dataLabel;
}
@@ -985,7 +985,7 @@ public:
void loadDouble(const void* address, FPRegisterID dest)
{
move(TrustedImm32(reinterpret_cast<ARMWord>(address)), ARMRegisters::S0);
- m_assembler.fdtr_u(ARMAssembler::LoadDouble, dest, ARMRegisters::S0, 0);
+ m_assembler.doubleDtrUp(ARMAssembler::LoadDouble, dest, ARMRegisters::S0, 0);
}
void storeFloat(FPRegisterID src, BaseIndex address)
@@ -1012,17 +1012,17 @@ public:
void moveDouble(FPRegisterID src, FPRegisterID dest)
{
if (src != dest)
- m_assembler.vmov_f64_r(dest, src);
+ m_assembler.vmov_f64(dest, src);
}
void addDouble(FPRegisterID src, FPRegisterID dest)
{
- m_assembler.vadd_f64_r(dest, dest, src);
+ m_assembler.vadd_f64(dest, dest, src);
}
void addDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
{
- m_assembler.vadd_f64_r(dest, op1, op2);
+ m_assembler.vadd_f64(dest, op1, op2);
}
void addDouble(Address src, FPRegisterID dest)
@@ -1039,12 +1039,12 @@ public:
void divDouble(FPRegisterID src, FPRegisterID dest)
{
- m_assembler.vdiv_f64_r(dest, dest, src);
+ m_assembler.vdiv_f64(dest, dest, src);
}
void divDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
{
- m_assembler.vdiv_f64_r(dest, op1, op2);
+ m_assembler.vdiv_f64(dest, op1, op2);
}
void divDouble(Address src, FPRegisterID dest)
@@ -1056,12 +1056,12 @@ public:
void subDouble(FPRegisterID src, FPRegisterID dest)
{
- m_assembler.vsub_f64_r(dest, dest, src);
+ m_assembler.vsub_f64(dest, dest, src);
}
void subDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
{
- m_assembler.vsub_f64_r(dest, op1, op2);
+ m_assembler.vsub_f64(dest, op1, op2);
}
void subDouble(Address src, FPRegisterID dest)
@@ -1072,7 +1072,7 @@ public:
void mulDouble(FPRegisterID src, FPRegisterID dest)
{
- m_assembler.vmul_f64_r(dest, dest, src);
+ m_assembler.vmul_f64(dest, dest, src);
}
void mulDouble(Address src, FPRegisterID dest)
@@ -1083,28 +1083,28 @@ public:
void mulDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
{
- m_assembler.vmul_f64_r(dest, op1, op2);
+ m_assembler.vmul_f64(dest, op1, op2);
}
void sqrtDouble(FPRegisterID src, FPRegisterID dest)
{
- m_assembler.vsqrt_f64_r(dest, src);
+ m_assembler.vsqrt_f64(dest, src);
}
void absDouble(FPRegisterID src, FPRegisterID dest)
{
- m_assembler.vabs_f64_r(dest, src);
+ m_assembler.vabs_f64(dest, src);
}
void negateDouble(FPRegisterID src, FPRegisterID dest)
{
- m_assembler.vneg_f64_r(dest, src);
+ m_assembler.vneg_f64(dest, src);
}
void convertInt32ToDouble(RegisterID src, FPRegisterID dest)
{
- m_assembler.vmov_vfp32_r(dest << 1, src);
- m_assembler.vcvt_f64_s32_r(dest, dest << 1);
+ m_assembler.vmov_vfp32(dest << 1, src);
+ m_assembler.vcvt_f64_s32(dest, dest << 1);
}
void convertInt32ToDouble(Address src, FPRegisterID dest)
@@ -1122,20 +1122,20 @@ public:
void convertFloatToDouble(FPRegisterID src, FPRegisterID dst)
{
- m_assembler.vcvt_f64_f32_r(dst, src);
+ m_assembler.vcvt_f64_f32(dst, src);
}
void convertDoubleToFloat(FPRegisterID src, FPRegisterID dst)
{
- m_assembler.vcvt_f32_f64_r(dst, src);
+ m_assembler.vcvt_f32_f64(dst, src);
}
Jump branchDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right)
{
- m_assembler.vcmp_f64_r(left, right);
+ m_assembler.vcmp_f64(left, right);
m_assembler.vmrs_apsr();
if (cond & DoubleConditionBitSpecial)
- m_assembler.cmp_r(ARMRegisters::S0, ARMRegisters::S0, ARMAssembler::VS);
+ m_assembler.cmp(ARMRegisters::S0, ARMRegisters::S0, ARMAssembler::VS);
return Jump(m_assembler.jmp(static_cast<ARMAssembler::Condition>(cond & ~DoubleConditionMask)));
}
@@ -1148,12 +1148,12 @@ public:
{
truncateDoubleToInt32(src, dest);
- m_assembler.add_r(ARMRegisters::S0, dest, ARMAssembler::getOp2Byte(1));
- m_assembler.bic_r(ARMRegisters::S0, ARMRegisters::S0, ARMAssembler::getOp2Byte(1));
+ m_assembler.add(ARMRegisters::S0, dest, ARMAssembler::getOp2Byte(1));
+ m_assembler.bic(ARMRegisters::S0, ARMRegisters::S0, ARMAssembler::getOp2Byte(1));
ARMWord w = ARMAssembler::getOp2(0x80000000);
ASSERT(w != ARMAssembler::InvalidImmediate);
- m_assembler.cmp_r(ARMRegisters::S0, w);
+ m_assembler.cmp(ARMRegisters::S0, w);
return Jump(m_assembler.jmp(branchType == BranchIfTruncateFailed ? ARMAssembler::EQ : ARMAssembler::NE));
}
@@ -1161,24 +1161,24 @@ public:
{
truncateDoubleToUint32(src, dest);
- m_assembler.add_r(ARMRegisters::S0, dest, ARMAssembler::getOp2Byte(1));
- m_assembler.bic_r(ARMRegisters::S0, ARMRegisters::S0, ARMAssembler::getOp2Byte(1));
+ m_assembler.add(ARMRegisters::S0, dest, ARMAssembler::getOp2Byte(1));
+ m_assembler.bic(ARMRegisters::S0, ARMRegisters::S0, ARMAssembler::getOp2Byte(1));
- m_assembler.cmp_r(ARMRegisters::S0, ARMAssembler::getOp2Byte(0));
+ m_assembler.cmp(ARMRegisters::S0, ARMAssembler::getOp2Byte(0));
return Jump(m_assembler.jmp(branchType == BranchIfTruncateFailed ? ARMAssembler::EQ : ARMAssembler::NE));
}
// Result is undefined if the value is outside of the integer range.
void truncateDoubleToInt32(FPRegisterID src, RegisterID dest)
{
- m_assembler.vcvt_s32_f64_r(ARMRegisters::SD0 << 1, src);
- m_assembler.vmov_arm32_r(dest, ARMRegisters::SD0 << 1);
+ m_assembler.vcvt_s32_f64(ARMRegisters::SD0 << 1, src);
+ m_assembler.vmov_arm32(dest, ARMRegisters::SD0 << 1);
}
void truncateDoubleToUint32(FPRegisterID src, RegisterID dest)
{
- m_assembler.vcvt_u32_f64_r(ARMRegisters::SD0 << 1, src);
- m_assembler.vmov_arm32_r(dest, ARMRegisters::SD0 << 1);
+ m_assembler.vcvt_u32_f64(ARMRegisters::SD0 << 1, src);
+ m_assembler.vmov_arm32(dest, ARMRegisters::SD0 << 1);
}
// Convert 'src' to an integer, and places the resulting 'dest'.
@@ -1187,11 +1187,11 @@ public:
// (specifically, in this case, 0).
void branchConvertDoubleToInt32(FPRegisterID src, RegisterID dest, JumpList& failureCases, FPRegisterID fpTemp)
{
- m_assembler.vcvt_s32_f64_r(ARMRegisters::SD0 << 1, src);
- m_assembler.vmov_arm32_r(dest, ARMRegisters::SD0 << 1);
+ m_assembler.vcvt_s32_f64(ARMRegisters::SD0 << 1, src);
+ m_assembler.vmov_arm32(dest, ARMRegisters::SD0 << 1);
// Convert the integer result back to float & compare to the original value - if not equal or unordered (NaN) then jump.
- m_assembler.vcvt_f64_s32_r(ARMRegisters::SD0, ARMRegisters::SD0 << 1);
+ m_assembler.vcvt_f64_s32(ARMRegisters::SD0, ARMRegisters::SD0 << 1);
failureCases.append(branchDouble(DoubleNotEqualOrUnordered, src, ARMRegisters::SD0));
// If the result is zero, it might have been -0.0, and 0.0 equals to -0.0
@@ -1200,14 +1200,14 @@ public:
Jump branchDoubleNonZero(FPRegisterID reg, FPRegisterID scratch)
{
- m_assembler.mov_r(ARMRegisters::S0, ARMAssembler::getOp2Byte(0));
+ m_assembler.mov(ARMRegisters::S0, ARMAssembler::getOp2Byte(0));
convertInt32ToDouble(ARMRegisters::S0, scratch);
return branchDouble(DoubleNotEqual, reg, scratch);
}
Jump branchDoubleZeroOrNaN(FPRegisterID reg, FPRegisterID scratch)
{
- m_assembler.mov_r(ARMRegisters::S0, ARMAssembler::getOp2Byte(0));
+ m_assembler.mov(ARMRegisters::S0, ARMAssembler::getOp2Byte(0));
convertInt32ToDouble(ARMRegisters::S0, scratch);
return branchDouble(DoubleEqualOrUnordered, reg, scratch);
}
diff --git a/Source/JavaScriptCore/bytecode/ArrayProfile.cpp b/Source/JavaScriptCore/bytecode/ArrayProfile.cpp
new file mode 100644
index 000000000..6b97f7806
--- /dev/null
+++ b/Source/JavaScriptCore/bytecode/ArrayProfile.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ArrayProfile.h"
+
+namespace JSC {
+
+void ArrayProfile::computeUpdatedPrediction(OperationInProgress operation)
+{
+ if (m_lastSeenStructure) {
+ m_observedArrayModes |= arrayModeFromStructure(m_lastSeenStructure);
+ if (!m_structureIsPolymorphic) {
+ if (!m_expectedStructure)
+ m_expectedStructure = m_lastSeenStructure;
+ else if (m_expectedStructure != m_lastSeenStructure) {
+ m_expectedStructure = 0;
+ m_structureIsPolymorphic = true;
+ }
+ }
+ m_lastSeenStructure = 0;
+ }
+
+ if (operation == Collection
+ && m_expectedStructure
+ && !Heap::isMarked(m_expectedStructure)) {
+ m_expectedStructure = 0;
+ m_structureIsPolymorphic = true;
+ }
+}
+
+} // namespace JSC
+
diff --git a/Source/JavaScriptCore/bytecode/ArrayProfile.h b/Source/JavaScriptCore/bytecode/ArrayProfile.h
new file mode 100644
index 000000000..5a656e2dd
--- /dev/null
+++ b/Source/JavaScriptCore/bytecode/ArrayProfile.h
@@ -0,0 +1,104 @@
+/*
+ * 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 ArrayProfile_h
+#define ArrayProfile_h
+
+#include "JSArray.h"
+#include "Structure.h"
+#include <wtf/HashMap.h>
+#include <wtf/SegmentedVector.h>
+
+namespace JSC {
+
+class LLIntOffsetsExtractor;
+
+typedef unsigned ArrayModes;
+
+static const unsigned IsNotArray = 1;
+static const unsigned IsJSArray = 2;
+
+inline ArrayModes arrayModeFromStructure(Structure* structure)
+{
+ if (structure->classInfo() == &JSArray::s_info)
+ return IsJSArray;
+ return IsNotArray;
+}
+
+class ArrayProfile {
+public:
+ ArrayProfile()
+ : m_bytecodeOffset(std::numeric_limits<unsigned>::max())
+ , m_lastSeenStructure(0)
+ , m_expectedStructure(0)
+ , m_structureIsPolymorphic(false)
+ , m_observedArrayModes(0)
+ {
+ }
+
+ ArrayProfile(unsigned bytecodeOffset)
+ : m_bytecodeOffset(bytecodeOffset)
+ , m_lastSeenStructure(0)
+ , m_expectedStructure(0)
+ , m_structureIsPolymorphic(false)
+ , m_observedArrayModes(0)
+ {
+ }
+
+ unsigned bytecodeOffset() const { return m_bytecodeOffset; }
+
+ Structure** addressOfLastSeenStructure() { return &m_lastSeenStructure; }
+
+ void observeStructure(Structure* structure)
+ {
+ m_lastSeenStructure = structure;
+ }
+
+ void computeUpdatedPrediction(OperationInProgress operation = NoOperation);
+
+ Structure* expectedStructure() const { return m_expectedStructure; }
+ bool structureIsPolymorphic() const { return m_structureIsPolymorphic; }
+ bool hasDefiniteStructure() const
+ {
+ return !structureIsPolymorphic() && m_expectedStructure;
+ }
+ ArrayModes observedArrayModes() const { return m_observedArrayModes; }
+
+private:
+ friend class LLIntOffsetsExtractor;
+
+ unsigned m_bytecodeOffset;
+ Structure* m_lastSeenStructure;
+ Structure* m_expectedStructure;
+ bool m_structureIsPolymorphic;
+ ArrayModes m_observedArrayModes;
+};
+
+typedef SegmentedVector<ArrayProfile, 4, 0> ArrayProfileVector;
+
+} // namespace JSC
+
+#endif // ArrayProfile_h
+
diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.cpp b/Source/JavaScriptCore/bytecode/CodeBlock.cpp
index 0e2a98bc5..2ea969fcf 100644
--- a/Source/JavaScriptCore/bytecode/CodeBlock.cpp
+++ b/Source/JavaScriptCore/bytecode/CodeBlock.cpp
@@ -1155,6 +1155,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
dataLog("[%4d] get_by_val\t %s, %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data());
dumpBytecodeCommentAndNewLine(location);
it++;
+ it++;
break;
}
case op_get_argument_by_val: {
@@ -1164,6 +1165,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
dataLog("[%4d] get_argument_by_val\t %s, %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data());
dumpBytecodeCommentAndNewLine(location);
++it;
+ ++it;
break;
}
case op_get_by_pname: {
@@ -1183,6 +1185,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
int r2 = (++it)->u.operand;
dataLog("[%4d] put_by_val\t %s, %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data());
dumpBytecodeCommentAndNewLine(location);
+ ++it;
break;
}
case op_del_by_val: {
@@ -2577,6 +2580,60 @@ void CodeBlock::unlinkIncomingCalls()
m_incomingCalls.begin()->unlink(*m_globalData, repatchBuffer);
}
+#if ENABLE(LLINT)
+Instruction* CodeBlock::adjustPCIfAtCallSite(Instruction* potentialReturnPC)
+{
+ ASSERT(potentialReturnPC);
+
+ unsigned returnPCOffset = potentialReturnPC - instructions().begin();
+ Instruction* adjustedPC;
+ unsigned opcodeLength;
+
+ // If we are at a callsite, the LLInt stores the PC after the call
+ // instruction rather than the PC of the call instruction. This requires
+ // some correcting. If so, we can rely on the fact that the preceding
+ // instruction must be one of the call instructions, so either it's a
+ // call_varargs or it's a call, construct, or eval.
+ //
+ // If we are not at a call site, then we need to guard against the
+ // possibility of peeking past the start of the bytecode range for this
+ // codeBlock. Hence, we do a bounds check before we peek at the
+ // potential "preceding" instruction.
+ // The bounds check is done by comparing the offset of the potential
+ // returnPC with the length of the opcode. If there is room for a call
+ // instruction before the returnPC, then the offset of the returnPC must
+ // be greater than the size of the call opcode we're looking for.
+
+ // The determination of the call instruction present (if we are at a
+ // callsite) depends on the following assumptions. So, assert that
+ // they are still true:
+ ASSERT(OPCODE_LENGTH(op_call_varargs) <= OPCODE_LENGTH(op_call));
+ ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_construct));
+ ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_call_eval));
+
+ // Check for the case of a preceeding op_call_varargs:
+ opcodeLength = OPCODE_LENGTH(op_call_varargs);
+ adjustedPC = potentialReturnPC - opcodeLength;
+ if ((returnPCOffset >= opcodeLength)
+ && (adjustedPC->u.pointer == bitwise_cast<void*>(llint_op_call_varargs))) {
+ return adjustedPC;
+ }
+
+ // Check for the case of the other 3 call instructions:
+ opcodeLength = OPCODE_LENGTH(op_call);
+ adjustedPC = potentialReturnPC - opcodeLength;
+ if ((returnPCOffset >= opcodeLength)
+ && (adjustedPC->u.pointer == bitwise_cast<void*>(llint_op_call)
+ || adjustedPC->u.pointer == bitwise_cast<void*>(llint_op_construct)
+ || adjustedPC->u.pointer == bitwise_cast<void*>(llint_op_call_eval))) {
+ return adjustedPC;
+ }
+
+ // Not a call site. No need to adjust PC. Just return the original.
+ return potentialReturnPC;
+}
+#endif
+
unsigned CodeBlock::bytecodeOffset(ExecState* exec, ReturnAddressPtr returnAddress)
{
#if ENABLE(LLINT)
@@ -2587,28 +2644,8 @@ unsigned CodeBlock::bytecodeOffset(ExecState* exec, ReturnAddressPtr returnAddre
ASSERT(JITCode::isBaselineCode(getJITType()));
Instruction* instruction = exec->currentVPC();
ASSERT(instruction);
-
- // The LLInt stores the PC after the call instruction rather than the PC of
- // the call instruction. This requires some correcting. We rely on the fact
- // that the preceding instruction must be one of the call instructions, so
- // either it's a call_varargs or it's a call, construct, or eval.
- ASSERT(OPCODE_LENGTH(op_call_varargs) <= OPCODE_LENGTH(op_call));
- ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_construct));
- ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_call_eval));
- if (instruction[-OPCODE_LENGTH(op_call_varargs)].u.pointer == bitwise_cast<void*>(llint_op_call_varargs)) {
- // We know that the preceding instruction must be op_call_varargs because there is no way that
- // the pointer to the call_varargs could be an operand to the call.
- instruction -= OPCODE_LENGTH(op_call_varargs);
- ASSERT(instruction[-OPCODE_LENGTH(op_call)].u.pointer != bitwise_cast<void*>(llint_op_call)
- && instruction[-OPCODE_LENGTH(op_call)].u.pointer != bitwise_cast<void*>(llint_op_construct)
- && instruction[-OPCODE_LENGTH(op_call)].u.pointer != bitwise_cast<void*>(llint_op_call_eval));
- } else {
- // Must be that the last instruction was some op_call.
- ASSERT(instruction[-OPCODE_LENGTH(op_call)].u.pointer == bitwise_cast<void*>(llint_op_call)
- || instruction[-OPCODE_LENGTH(op_call)].u.pointer == bitwise_cast<void*>(llint_op_construct)
- || instruction[-OPCODE_LENGTH(op_call)].u.pointer == bitwise_cast<void*>(llint_op_call_eval));
- instruction -= OPCODE_LENGTH(op_call);
- }
+
+ instruction = adjustPCIfAtCallSite(instruction);
return bytecodeOffset(instruction);
}
@@ -2684,27 +2721,27 @@ CodeBlock* FunctionCodeBlock::replacement()
return &static_cast<FunctionExecutable*>(ownerExecutable())->generatedBytecodeFor(m_isConstructor ? CodeForConstruct : CodeForCall);
}
-JSObject* ProgramCodeBlock::compileOptimized(ExecState* exec, ScopeChainNode* scopeChainNode)
+JSObject* ProgramCodeBlock::compileOptimized(ExecState* exec, ScopeChainNode* scopeChainNode, unsigned bytecodeIndex)
{
if (replacement()->getJITType() == JITCode::nextTierJIT(getJITType()))
return 0;
- JSObject* error = static_cast<ProgramExecutable*>(ownerExecutable())->compileOptimized(exec, scopeChainNode);
+ JSObject* error = static_cast<ProgramExecutable*>(ownerExecutable())->compileOptimized(exec, scopeChainNode, bytecodeIndex);
return error;
}
-JSObject* EvalCodeBlock::compileOptimized(ExecState* exec, ScopeChainNode* scopeChainNode)
+JSObject* EvalCodeBlock::compileOptimized(ExecState* exec, ScopeChainNode* scopeChainNode, unsigned bytecodeIndex)
{
if (replacement()->getJITType() == JITCode::nextTierJIT(getJITType()))
return 0;
- JSObject* error = static_cast<EvalExecutable*>(ownerExecutable())->compileOptimized(exec, scopeChainNode);
+ JSObject* error = static_cast<EvalExecutable*>(ownerExecutable())->compileOptimized(exec, scopeChainNode, bytecodeIndex);
return error;
}
-JSObject* FunctionCodeBlock::compileOptimized(ExecState* exec, ScopeChainNode* scopeChainNode)
+JSObject* FunctionCodeBlock::compileOptimized(ExecState* exec, ScopeChainNode* scopeChainNode, unsigned bytecodeIndex)
{
if (replacement()->getJITType() == JITCode::nextTierJIT(getJITType()))
return 0;
- JSObject* error = static_cast<FunctionExecutable*>(ownerExecutable())->compileOptimizedFor(exec, scopeChainNode, m_isConstructor ? CodeForConstruct : CodeForCall);
+ JSObject* error = static_cast<FunctionExecutable*>(ownerExecutable())->compileOptimizedFor(exec, scopeChainNode, bytecodeIndex, m_isConstructor ? CodeForConstruct : CodeForCall);
return error;
}
@@ -2769,6 +2806,23 @@ bool FunctionCodeBlock::jitCompileImpl(ExecState* exec)
#endif
#if ENABLE(VALUE_PROFILER)
+ArrayProfile* CodeBlock::getArrayProfile(unsigned bytecodeOffset)
+{
+ for (unsigned i = 0; i < m_arrayProfiles.size(); ++i) {
+ if (m_arrayProfiles[i].bytecodeOffset() == bytecodeOffset)
+ return &m_arrayProfiles[i];
+ }
+ return 0;
+}
+
+ArrayProfile* CodeBlock::getOrAddArrayProfile(unsigned bytecodeOffset)
+{
+ ArrayProfile* result = getArrayProfile(bytecodeOffset);
+ if (result)
+ return result;
+ return addArrayProfile(bytecodeOffset);
+}
+
void CodeBlock::updateAllPredictionsAndCountLiveness(
OperationInProgress operation, unsigned& numberOfLiveNonArgumentValueProfiles, unsigned& numberOfSamplesInProfiles)
{
@@ -2792,6 +2846,12 @@ void CodeBlock::updateAllPredictionsAndCountLiveness(
#if ENABLE(DFG_JIT)
m_lazyOperandValueProfiles.computeUpdatedPredictions(operation);
#endif
+
+ // Don't count the array profiles towards statistics, since each array profile
+ // site also has a value profile site - so we already know whether or not it's
+ // live.
+ for (unsigned i = m_arrayProfiles.size(); i--;)
+ m_arrayProfiles[i].computeUpdatedPrediction(operation);
}
void CodeBlock::updateAllPredictions(OperationInProgress operation)
diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.h b/Source/JavaScriptCore/bytecode/CodeBlock.h
index 2a7d2120a..a8b2a5871 100644
--- a/Source/JavaScriptCore/bytecode/CodeBlock.h
+++ b/Source/JavaScriptCore/bytecode/CodeBlock.h
@@ -30,6 +30,7 @@
#ifndef CodeBlock_h
#define CodeBlock_h
+#include "ArrayProfile.h"
#include "BytecodeConventions.h"
#include "CallLinkInfo.h"
#include "CallReturnOffsetToBytecodeOffset.h"
@@ -229,6 +230,9 @@ namespace JSC {
return *(binarySearch<MethodCallLinkInfo, unsigned, getMethodCallLinkInfoBytecodeIndex>(m_methodCallLinkInfos.begin(), m_methodCallLinkInfos.size(), bytecodeIndex));
}
+#if ENABLE(LLINT)
+ Instruction* adjustPCIfAtCallSite(Instruction*);
+#endif
unsigned bytecodeOffset(ExecState*, ReturnAddressPtr);
unsigned bytecodeOffsetForCallAtIndex(unsigned index)
@@ -441,7 +445,7 @@ namespace JSC {
MacroAssemblerCodePtr getJITCodeWithArityCheck() { return m_jitCodeWithArityCheck; }
JITCode::JITType getJITType() { return m_jitCode.jitType(); }
ExecutableMemoryHandle* executableMemory() { return getJITCode().getExecutableMemory(); }
- virtual JSObject* compileOptimized(ExecState*, ScopeChainNode*) = 0;
+ virtual JSObject* compileOptimized(ExecState*, ScopeChainNode*, unsigned bytecodeIndex) = 0;
virtual void jettison() = 0;
enum JITCompilationResult { AlreadyCompiled, CouldNotCompile, CompiledSuccessfully };
JITCompilationResult jitCompile(ExecState* exec)
@@ -751,8 +755,18 @@ namespace JSC {
}
unsigned executionEntryCount() const { return m_executionEntryCount; }
-#endif
+ unsigned numberOfArrayProfiles() const { return m_arrayProfiles.size(); }
+ const ArrayProfileVector& arrayProfiles() { return m_arrayProfiles; }
+ ArrayProfile* addArrayProfile(unsigned bytecodeOffset)
+ {
+ m_arrayProfiles.append(ArrayProfile(bytecodeOffset));
+ return &m_arrayProfiles.last();
+ }
+ ArrayProfile* getArrayProfile(unsigned bytecodeOffset);
+ ArrayProfile* getOrAddArrayProfile(unsigned bytecodeOffset);
+#endif
+
unsigned globalResolveInfoCount() const
{
#if ENABLE(JIT)
@@ -1333,6 +1347,7 @@ namespace JSC {
SegmentedVector<ValueProfile, 8> m_valueProfiles;
SegmentedVector<RareCaseProfile, 8> m_rareCaseProfiles;
SegmentedVector<RareCaseProfile, 8> m_specialFastCaseProfiles;
+ ArrayProfileVector m_arrayProfiles;
unsigned m_executionEntryCount;
#endif
@@ -1436,7 +1451,7 @@ namespace JSC {
#if ENABLE(JIT)
protected:
- virtual JSObject* compileOptimized(ExecState*, ScopeChainNode*);
+ virtual JSObject* compileOptimized(ExecState*, ScopeChainNode*, unsigned bytecodeIndex);
virtual void jettison();
virtual bool jitCompileImpl(ExecState*);
virtual CodeBlock* replacement();
@@ -1471,7 +1486,7 @@ namespace JSC {
#if ENABLE(JIT)
protected:
- virtual JSObject* compileOptimized(ExecState*, ScopeChainNode*);
+ virtual JSObject* compileOptimized(ExecState*, ScopeChainNode*, unsigned bytecodeIndex);
virtual void jettison();
virtual bool jitCompileImpl(ExecState*);
virtual CodeBlock* replacement();
@@ -1509,7 +1524,7 @@ namespace JSC {
#if ENABLE(JIT)
protected:
- virtual JSObject* compileOptimized(ExecState*, ScopeChainNode*);
+ virtual JSObject* compileOptimized(ExecState*, ScopeChainNode*, unsigned bytecodeIndex);
virtual void jettison();
virtual bool jitCompileImpl(ExecState*);
virtual CodeBlock* replacement();
diff --git a/Source/JavaScriptCore/bytecode/Instruction.h b/Source/JavaScriptCore/bytecode/Instruction.h
index 2e94b452c..6c1260abc 100644
--- a/Source/JavaScriptCore/bytecode/Instruction.h
+++ b/Source/JavaScriptCore/bytecode/Instruction.h
@@ -46,6 +46,7 @@ namespace JSC {
// curently actually use PolymorphicAccessStructureLists, which we should). Anyway, this seems like the best
// solution for now - will need to something smarter if/when we actually want mixed-mode operation.
+ class ArrayProfile;
class JSCell;
class Structure;
class StructureChain;
@@ -190,6 +191,7 @@ namespace JSC {
Instruction(LLIntCallLinkInfo* callLinkInfo) { u.callLinkInfo = callLinkInfo; }
Instruction(ValueProfile* profile) { u.profile = profile; }
+ Instruction(ArrayProfile* profile) { u.arrayProfile = profile; }
Instruction(WriteBarrier<Unknown>* registerPointer) { u.registerPointer = registerPointer; }
@@ -205,6 +207,7 @@ namespace JSC {
PropertySlot::GetValueFunc getterFunc;
LLIntCallLinkInfo* callLinkInfo;
ValueProfile* profile;
+ ArrayProfile* arrayProfile;
void* pointer;
bool* predicatePointer;
} u;
diff --git a/Source/JavaScriptCore/bytecode/Opcode.h b/Source/JavaScriptCore/bytecode/Opcode.h
index 4308e79df..777b4876f 100644
--- a/Source/JavaScriptCore/bytecode/Opcode.h
+++ b/Source/JavaScriptCore/bytecode/Opcode.h
@@ -132,10 +132,10 @@ namespace JSC {
macro(op_put_by_id_replace, 9) \
macro(op_put_by_id_generic, 9) \
macro(op_del_by_id, 4) \
- macro(op_get_by_val, 5) /* has value profiling */ \
- macro(op_get_argument_by_val, 5) /* must be the same size as op_get_by_val */ \
+ macro(op_get_by_val, 6) /* has value profiling */ \
+ macro(op_get_argument_by_val, 6) /* must be the same size as op_get_by_val */ \
macro(op_get_by_pname, 7) \
- macro(op_put_by_val, 4) \
+ macro(op_put_by_val, 5) \
macro(op_del_by_val, 4) \
macro(op_put_by_index, 4) \
macro(op_put_getter_setter, 5) \
diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
index 14a69b530..c8cfa74b6 100644
--- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
+++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
@@ -708,6 +708,15 @@ void BytecodeGenerator::prependComment(const char* string)
}
#endif
+ArrayProfile* BytecodeGenerator::newArrayProfile()
+{
+#if ENABLE(VALUE_PROFILER)
+ return m_codeBlock->addArrayProfile(instructions().size());
+#else
+ return 0;
+#endif
+}
+
ValueProfile* BytecodeGenerator::emitProfiledOpcode(OpcodeID opcodeID)
{
#if ENABLE(VALUE_PROFILER)
@@ -1455,9 +1464,7 @@ RegisterID* BytecodeGenerator::emitResolveWithBase(RegisterID* baseDst, Register
#if ENABLE(JIT)
m_codeBlock->addGlobalResolveInfo(instructions().size());
#endif
-#if ENABLE(CLASSIC_INTERPRETER)
m_codeBlock->addGlobalResolveInstruction(instructions().size());
-#endif
ValueProfile* profile = emitProfiledOpcode(op_resolve_global);
instructions().append(propDst->index());
instructions().append(addConstant(property));
@@ -1669,11 +1676,13 @@ RegisterID* BytecodeGenerator::emitDeleteById(RegisterID* dst, RegisterID* base,
RegisterID* BytecodeGenerator::emitGetArgumentByVal(RegisterID* dst, RegisterID* base, RegisterID* property)
{
+ ArrayProfile* arrayProfile = newArrayProfile();
ValueProfile* profile = emitProfiledOpcode(op_get_argument_by_val);
instructions().append(dst->index());
ASSERT(base->index() == m_codeBlock->argumentsRegister());
instructions().append(base->index());
instructions().append(property->index());
+ instructions().append(arrayProfile);
instructions().append(profile);
return dst;
}
@@ -1693,20 +1702,24 @@ RegisterID* BytecodeGenerator::emitGetByVal(RegisterID* dst, RegisterID* base, R
return dst;
}
}
+ ArrayProfile* arrayProfile = newArrayProfile();
ValueProfile* profile = emitProfiledOpcode(op_get_by_val);
instructions().append(dst->index());
instructions().append(base->index());
instructions().append(property->index());
+ instructions().append(arrayProfile);
instructions().append(profile);
return dst;
}
RegisterID* BytecodeGenerator::emitPutByVal(RegisterID* base, RegisterID* property, RegisterID* value)
{
+ ArrayProfile* arrayProfile = newArrayProfile();
emitOpcode(op_put_by_val);
instructions().append(base->index());
instructions().append(property->index());
instructions().append(value->index());
+ instructions().append(arrayProfile);
return value;
}
diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
index 490991fa7..9c094414d 100644
--- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
+++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
@@ -555,6 +555,7 @@ namespace JSC {
#endif
void emitOpcode(OpcodeID);
+ ArrayProfile* newArrayProfile();
ValueProfile* emitProfiledOpcode(OpcodeID);
void retrieveLastBinaryOp(int& dstIndex, int& src1Index, int& src2Index);
void retrieveLastUnaryOp(int& dstIndex, int& srcIndex);
diff --git a/Source/JavaScriptCore/config.h b/Source/JavaScriptCore/config.h
index 1e49c96bf..7f7eda0f1 100644
--- a/Source/JavaScriptCore/config.h
+++ b/Source/JavaScriptCore/config.h
@@ -69,12 +69,7 @@
#include <wtf/FastMalloc.h>
#endif
-// this breaks compilation of <QFontDatabase>, at least, so turn it off for now
-// Also generates errors on wx on Windows and QNX, because these functions
-// are used from wx and QNX headers.
-#if !PLATFORM(QT) && !PLATFORM(WX) && !OS(QNX)
#include <wtf/DisallowCType.h>
-#endif
#if COMPILER(MSVC)
#define SKIP_STATIC_CONSTRUCTORS_ON_MSVC 1
diff --git a/Source/JavaScriptCore/dfg/DFGAbstractState.cpp b/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
index 4f02ee793..5c53f6d78 100644
--- a/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
+++ b/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
@@ -62,13 +62,13 @@ void AbstractState::beginBasicBlock(BasicBlock* basicBlock)
m_variables = basicBlock->valuesAtHead;
m_haveStructures = false;
for (size_t i = 0; i < m_variables.numberOfArguments(); ++i) {
- if (m_variables.argument(i).m_structure.isNeitherClearNorTop()) {
+ if (m_variables.argument(i).m_currentKnownStructure.isNeitherClearNorTop()) {
m_haveStructures = true;
break;
}
}
for (size_t i = 0; i < m_variables.numberOfLocals(); ++i) {
- if (m_variables.local(i).m_structure.isNeitherClearNorTop()) {
+ if (m_variables.local(i).m_currentKnownStructure.isNeitherClearNorTop()) {
m_haveStructures = true;
break;
}
@@ -106,8 +106,6 @@ void AbstractState::initialize(Graph& graph)
SpeculatedType prediction = node.variableAccessData()->prediction();
if (isInt32Speculation(prediction))
root->valuesAtHead.argument(i).set(SpecInt32);
- else if (isArraySpeculation(prediction))
- root->valuesAtHead.argument(i).set(SpecArray);
else if (isBooleanSpeculation(prediction))
root->valuesAtHead.argument(i).set(SpecBoolean);
else if (isInt8ArraySpeculation(prediction))
@@ -160,6 +158,16 @@ void AbstractState::initialize(Graph& graph)
block->valuesAtHead.local(i).clear();
block->valuesAtTail.local(i).clear();
}
+ if (!block->isOSRTarget)
+ continue;
+ if (block->bytecodeBegin != graph.m_osrEntryBytecodeIndex)
+ continue;
+ for (size_t i = 0; i < graph.m_mustHandleValues.size(); ++i) {
+ AbstractValue value;
+ value.setMostSpecific(graph.m_mustHandleValues[i]);
+ block->valuesAtHead.operand(graph.m_mustHandleValues.operandForIndex(i)).merge(value);
+ }
+ block->cfaShouldRevisit = true;
}
}
@@ -290,10 +298,7 @@ bool AbstractState::execute(unsigned indexInBlock)
SpeculatedType predictedType = node.variableAccessData()->argumentAwarePrediction();
if (isInt32Speculation(predictedType))
speculateInt32Unary(node);
- else if (isArraySpeculation(predictedType)) {
- node.setCanExit(!isArraySpeculation(forNode(node.child1()).m_type));
- forNode(node.child1()).filter(SpecArray);
- } else if (isCellSpeculation(predictedType)) {
+ else if (isCellSpeculation(predictedType)) {
node.setCanExit(!isCellSpeculation(forNode(node.child1()).m_type));
forNode(node.child1()).filter(SpecCell);
} else if (isBooleanSpeculation(predictedType))
@@ -867,7 +872,7 @@ bool AbstractState::execute(unsigned indexInBlock)
m_isValid = false;
break;
}
- if (!isActionableArraySpeculation(m_graph[node.child1()].prediction()) || !m_graph[node.child2()].shouldSpeculateInteger()) {
+ if (!m_graph[node.child2()].shouldSpeculateInteger() || (!node.child3() && !m_graph[node.child1()].shouldSpeculateArguments())) {
clobberWorld(node.codeOrigin, indexInBlock);
forNode(nodeIndex).makeTop();
break;
@@ -942,8 +947,7 @@ bool AbstractState::execute(unsigned indexInBlock)
forNode(nodeIndex).set(SpecDouble);
break;
}
- ASSERT(m_graph[node.child1()].shouldSpeculateArray());
- forNode(node.child1()).filter(SpecArray);
+ forNode(node.child1()).filter(SpecCell);
forNode(node.child2()).filter(SpecInt32);
forNode(nodeIndex).makeTop();
break;
@@ -962,7 +966,7 @@ bool AbstractState::execute(unsigned indexInBlock)
m_isValid = false;
break;
}
- if (!m_graph[child2].shouldSpeculateInteger() || !isActionableMutableArraySpeculation(m_graph[child1].prediction())
+ if (!m_graph[child2].shouldSpeculateInteger()
#if USE(JSVALUE32_64)
|| m_graph[child1].shouldSpeculateArguments()
#endif
@@ -1053,8 +1057,7 @@ bool AbstractState::execute(unsigned indexInBlock)
forNode(child3).filter(SpecNumber);
break;
}
- ASSERT(m_graph[child1].shouldSpeculateArray());
- forNode(child1).filter(SpecArray);
+ forNode(child1).filter(SpecCell);
forNode(child2).filter(SpecInt32);
if (node.op() == PutByValSafe)
clobberWorld(node.codeOrigin, indexInBlock);
@@ -1063,13 +1066,13 @@ bool AbstractState::execute(unsigned indexInBlock)
case ArrayPush:
node.setCanExit(true);
- forNode(node.child1()).filter(SpecArray);
+ forNode(node.child1()).filter(SpecCell);
forNode(nodeIndex).set(SpecNumber);
break;
case ArrayPop:
node.setCanExit(true);
- forNode(node.child1()).filter(SpecArray);
+ forNode(node.child1()).filter(SpecCell);
forNode(nodeIndex).makeTop();
break;
@@ -1354,7 +1357,7 @@ bool AbstractState::execute(unsigned indexInBlock)
case GetArrayLength:
node.setCanExit(true);
- forNode(node.child1()).filter(SpecArray);
+ forNode(node.child1()).filter(SpecCell);
forNode(nodeIndex).set(SpecInt32);
break;
@@ -1420,19 +1423,52 @@ bool AbstractState::execute(unsigned indexInBlock)
case ForwardCheckStructure: {
// FIXME: We should be able to propagate the structure sets of constants (i.e. prototypes).
AbstractValue& value = forNode(node.child1());
+ // If this structure check is attempting to prove knowledge already held in
+ // the futurePossibleStructure set then the constant folding phase should
+ // turn this into a watchpoint instead.
+ StructureSet& set = node.structureSet();
+ if (value.m_futurePossibleStructure.isSubsetOf(set))
+ m_foundConstants = true;
node.setCanExit(
- !value.m_structure.isSubsetOf(node.structureSet())
+ !value.m_currentKnownStructure.isSubsetOf(set)
|| !isCellSpeculation(value.m_type));
- value.filter(node.structureSet());
+ value.filter(set);
+ // This is likely to be unnecessary, but it's conservative, and that's a good thing.
+ // This is trying to avoid situations where the CFA proves that this structure check
+ // must fail due to a future structure proof. We have two options at that point. We
+ // can either compile all subsequent code as we would otherwise, or we can ensure
+ // that the subsequent code is never reachable. The former is correct because the
+ // Proof Is Infallible (TM) -- hence even if we don't force the subsequent code to
+ // be unreachable, it must be unreachable nonetheless. But imagine what would happen
+ // if the proof was borked. In the former case, we'd get really bizarre bugs where
+ // we assumed that the structure of this object was known even though it wasn't. In
+ // the latter case, we'd have a slight performance pathology because this would be
+ // turned into an OSR exit unnecessarily. Which would you rather have?
+ if (value.m_currentKnownStructure.isClear()
+ || value.m_futurePossibleStructure.isClear())
+ m_isValid = false;
m_haveStructures = true;
break;
}
- case StructureTransitionWatchpoint: {
- // FIXME: Turn CheckStructure into StructureTransitionWatchpoint when possible!
+ case StructureTransitionWatchpoint:
+ case ForwardStructureTransitionWatchpoint: {
AbstractValue& value = forNode(node.child1());
+
+ // It's only valid to issue a structure transition watchpoint if we already
+ // know that the watchpoint covers a superset of the structures known to
+ // belong to the set of future structures that this value may have.
+ // Currently, we only issue singleton watchpoints (that check one structure)
+ // and our futurePossibleStructure set can only contain zero, one, or an
+ // infinity of structures.
+ ASSERT(value.m_futurePossibleStructure.isSubsetOf(StructureSet(node.structure())));
+
ASSERT(value.isClear() || isCellSpeculation(value.m_type)); // Value could be clear if we've proven must-exit due to a speculation statically known to be bad.
value.filter(node.structure());
+ // See comment in CheckStructure for why this is here.
+ if (value.m_currentKnownStructure.isClear()
+ || value.m_futurePossibleStructure.isClear())
+ m_isValid = false;
m_haveStructures = true;
node.setCanExit(true);
break;
@@ -1453,12 +1489,9 @@ bool AbstractState::execute(unsigned indexInBlock)
forNode(nodeIndex).clear(); // The result is not a JS value.
break;
case GetIndexedPropertyStorage: {
+ ASSERT(m_graph[node.child1()].prediction());
+ ASSERT(m_graph[node.child2()].shouldSpeculateInteger());
node.setCanExit(true); // Lies, but this is (almost) always followed by GetByVal, which does exit. So no point in trying to be more precise.
- SpeculatedType basePrediction = m_graph[node.child2()].prediction();
- if (!(basePrediction & SpecInt32) && basePrediction) {
- forNode(nodeIndex).clear();
- break;
- }
if (m_graph[node.child1()].shouldSpeculateArguments()) {
ASSERT_NOT_REACHED();
break;
@@ -1514,7 +1547,7 @@ bool AbstractState::execute(unsigned indexInBlock)
forNode(nodeIndex).clear();
break;
}
- forNode(node.child1()).filter(SpecArray);
+ forNode(node.child1()).filter(SpecCell);
forNode(nodeIndex).clear();
break;
}
diff --git a/Source/JavaScriptCore/dfg/DFGAbstractValue.h b/Source/JavaScriptCore/dfg/DFGAbstractValue.h
index 402fd0fcd..ff1c6d205 100644
--- a/Source/JavaScriptCore/dfg/DFGAbstractValue.h
+++ b/Source/JavaScriptCore/dfg/DFGAbstractValue.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2011, 2012 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -30,283 +30,13 @@
#if ENABLE(DFG_JIT)
+#include "DFGStructureAbstractValue.h"
#include "JSCell.h"
#include "SpeculatedType.h"
#include "StructureSet.h"
namespace JSC { namespace DFG {
-class StructureAbstractValue {
-public:
- StructureAbstractValue()
- : m_structure(0)
- {
- }
-
- StructureAbstractValue(Structure* structure)
- : m_structure(structure)
- {
- }
-
- StructureAbstractValue(const StructureSet& set)
- {
- switch (set.size()) {
- case 0:
- m_structure = 0;
- break;
-
- case 1:
- m_structure = set[0];
- break;
-
- default:
- m_structure = topValue();
- break;
- }
- }
-
- void clear()
- {
- m_structure = 0;
- }
-
- void makeTop()
- {
- m_structure = topValue();
- }
-
- static StructureAbstractValue top()
- {
- StructureAbstractValue value;
- value.makeTop();
- return value;
- }
-
- void add(Structure* structure)
- {
- ASSERT(!contains(structure) && !isTop());
- if (m_structure)
- makeTop();
- else
- m_structure = structure;
- }
-
- bool addAll(const StructureSet& other)
- {
- if (isTop() || !other.size())
- return false;
- if (other.size() > 1) {
- makeTop();
- return true;
- }
- if (!m_structure) {
- m_structure = other[0];
- return true;
- }
- if (m_structure == other[0])
- return false;
- makeTop();
- return true;
- }
-
- bool addAll(const StructureAbstractValue& other)
- {
- if (!other.m_structure)
- return false;
- if (isTop())
- return false;
- if (other.isTop()) {
- makeTop();
- return true;
- }
- if (m_structure) {
- if (m_structure == other.m_structure)
- return false;
- makeTop();
- return true;
- }
- m_structure = other.m_structure;
- return true;
- }
-
- bool contains(Structure* structure) const
- {
- if (isTop())
- return true;
- if (m_structure == structure)
- return true;
- return false;
- }
-
- bool isSubsetOf(const StructureSet& other) const
- {
- if (isTop())
- return false;
- if (!m_structure)
- return true;
- return other.contains(m_structure);
- }
-
- bool doesNotContainAnyOtherThan(Structure* structure) const
- {
- if (isTop())
- return false;
- if (!m_structure)
- return true;
- return m_structure == structure;
- }
-
- bool isSupersetOf(const StructureSet& other) const
- {
- if (isTop())
- return true;
- if (!other.size())
- return true;
- if (other.size() > 1)
- return false;
- return m_structure == other[0];
- }
-
- bool isSubsetOf(const StructureAbstractValue& other) const
- {
- if (other.isTop())
- return true;
- if (isTop())
- return false;
- if (m_structure) {
- if (other.m_structure)
- return m_structure == other.m_structure;
- return false;
- }
- return true;
- }
-
- bool isSupersetOf(const StructureAbstractValue& other) const
- {
- return other.isSubsetOf(*this);
- }
-
- void filter(const StructureSet& other)
- {
- if (!m_structure)
- return;
-
- if (isTop()) {
- switch (other.size()) {
- case 0:
- m_structure = 0;
- return;
-
- case 1:
- m_structure = other[0];
- return;
-
- default:
- return;
- }
- }
-
- if (other.contains(m_structure))
- return;
-
- m_structure = 0;
- }
-
- void filter(const StructureAbstractValue& other)
- {
- if (isTop()) {
- m_structure = other.m_structure;
- return;
- }
- if (m_structure == other.m_structure)
- return;
- if (other.isTop())
- return;
- m_structure = 0;
- }
-
- void filter(SpeculatedType other)
- {
- if (!(other & SpecCell)) {
- clear();
- return;
- }
-
- if (isClearOrTop())
- return;
-
- if (!(speculationFromStructure(m_structure) & other))
- m_structure = 0;
- }
-
- bool isClear() const
- {
- return !m_structure;
- }
-
- bool isTop() const { return m_structure == topValue(); }
-
- bool isClearOrTop() const { return m_structure <= topValue(); }
- bool isNeitherClearNorTop() const { return !isClearOrTop(); }
-
- size_t size() const
- {
- ASSERT(!isTop());
- return !!m_structure;
- }
-
- Structure* at(size_t i) const
- {
- ASSERT(!isTop());
- ASSERT(m_structure);
- ASSERT_UNUSED(i, !i);
- return m_structure;
- }
-
- Structure* operator[](size_t i) const
- {
- return at(i);
- }
-
- Structure* last() const
- {
- return at(0);
- }
-
- SpeculatedType speculationFromStructures() const
- {
- if (isTop())
- return SpecCell;
- if (isClear())
- return SpecNone;
- return speculationFromStructure(m_structure);
- }
-
- bool operator==(const StructureAbstractValue& other) const
- {
- return m_structure == other.m_structure;
- }
-
- void dump(FILE* out) const
- {
- if (isTop()) {
- fprintf(out, "TOP");
- return;
- }
-
- fprintf(out, "[");
- if (m_structure)
- fprintf(out, "%p", m_structure);
- fprintf(out, "]");
- }
-
-private:
- static Structure* topValue() { return reinterpret_cast<Structure*>(1); }
-
- // This can only remember one structure at a time.
- Structure* m_structure;
-};
-
struct AbstractValue {
AbstractValue()
: m_type(SpecNone)
@@ -316,15 +46,15 @@ struct AbstractValue {
void clear()
{
m_type = SpecNone;
- m_structure.clear();
- m_unclobberedStructure.clear();
+ m_currentKnownStructure.clear();
+ m_futurePossibleStructure.clear();
m_value = JSValue();
checkConsistency();
}
bool isClear() const
{
- bool result = m_type == SpecNone && m_structure.isClear() && m_unclobberedStructure.isClear();
+ bool result = m_type == SpecNone && m_currentKnownStructure.isClear() && m_futurePossibleStructure.isClear();
if (result)
ASSERT(!m_value);
return result;
@@ -333,8 +63,8 @@ struct AbstractValue {
void makeTop()
{
m_type = SpecTop;
- m_structure.makeTop();
- m_unclobberedStructure.makeTop();
+ m_currentKnownStructure.makeTop();
+ m_futurePossibleStructure.makeTop();
m_value = JSValue();
checkConsistency();
}
@@ -342,9 +72,9 @@ struct AbstractValue {
void clobberStructures()
{
if (m_type & SpecCell)
- m_structure.makeTop();
+ m_currentKnownStructure.makeTop();
else
- ASSERT(m_structure.isClear());
+ ASSERT(m_currentKnownStructure.isClear());
checkConsistency();
}
@@ -355,7 +85,7 @@ struct AbstractValue {
bool isTop() const
{
- return m_type == SpecTop && m_structure.isTop() && m_unclobberedStructure.isTop();
+ return m_type == SpecTop && m_currentKnownStructure.isTop() && m_futurePossibleStructure.isTop();
}
bool valueIsTop() const
@@ -375,20 +105,29 @@ struct AbstractValue {
return result;
}
- void set(JSValue value)
+ void setFuturePossibleStructure(Structure* structure)
+ {
+ if (structure->transitionWatchpointSetIsStillValid())
+ m_futurePossibleStructure = structure;
+ else
+ m_futurePossibleStructure.makeTop();
+ }
+
+ void filterFuturePossibleStructure(Structure* structure)
+ {
+ if (structure->transitionWatchpointSetIsStillValid())
+ m_futurePossibleStructure.filter(StructureAbstractValue(structure));
+ }
+
+ void setMostSpecific(JSValue value)
{
if (!!value && value.isCell()) {
- // Have to be careful here! It's tempting to set the structure to the
- // value's structure, but that would be wrong, since that would
- // constitute a proof that this value will always have the same
- // structure. The whole point of a value having a structure is that
- // it may change in the future - for example between when we compile
- // the code and when we run it.
- m_structure.makeTop();
- m_unclobberedStructure.makeTop(); // FIXME: Consider not clobbering this.
+ Structure* structure = value.asCell()->structure();
+ m_currentKnownStructure = structure;
+ setFuturePossibleStructure(structure);
} else {
- m_structure.clear();
- m_unclobberedStructure.clear();
+ m_currentKnownStructure.clear();
+ m_futurePossibleStructure.clear();
}
m_type = speculationFromValue(value);
@@ -397,14 +136,26 @@ struct AbstractValue {
checkConsistency();
}
- void set(Structure* structure)
+ void set(JSValue value)
{
- m_structure.clear();
- m_structure.add(structure);
+ if (!!value && value.isCell()) {
+ m_currentKnownStructure.makeTop();
+ setFuturePossibleStructure(value.asCell()->structure());
+ } else {
+ m_currentKnownStructure.clear();
+ m_futurePossibleStructure.clear();
+ }
- m_unclobberedStructure.clear();
- m_unclobberedStructure.add(structure);
+ m_type = speculationFromValue(value);
+ m_value = value;
+ checkConsistency();
+ }
+
+ void set(Structure* structure)
+ {
+ m_currentKnownStructure = structure;
+ setFuturePossibleStructure(structure);
m_type = speculationFromStructure(structure);
m_value = JSValue();
@@ -414,11 +165,11 @@ struct AbstractValue {
void set(SpeculatedType type)
{
if (type & SpecCell) {
- m_structure.makeTop();
- m_unclobberedStructure.makeTop();
+ m_currentKnownStructure.makeTop();
+ m_futurePossibleStructure.makeTop();
} else {
- m_structure.clear();
- m_unclobberedStructure.clear();
+ m_currentKnownStructure.clear();
+ m_futurePossibleStructure.clear();
}
m_type = type;
m_value = JSValue();
@@ -428,8 +179,8 @@ struct AbstractValue {
bool operator==(const AbstractValue& other) const
{
return m_type == other.m_type
- && m_structure == other.m_structure
- && m_unclobberedStructure == other.m_unclobberedStructure
+ && m_currentKnownStructure == other.m_currentKnownStructure
+ && m_futurePossibleStructure == other.m_futurePossibleStructure
&& m_value == other.m_value;
}
bool operator!=(const AbstractValue& other) const
@@ -448,8 +199,8 @@ struct AbstractValue {
result = !other.isClear();
} else {
result |= mergeSpeculation(m_type, other.m_type);
- result |= m_structure.addAll(other.m_structure);
- result |= m_unclobberedStructure.addAll(other.m_unclobberedStructure);
+ result |= m_currentKnownStructure.addAll(other.m_currentKnownStructure);
+ result |= m_futurePossibleStructure.addAll(other.m_futurePossibleStructure);
if (m_value != other.m_value) {
result |= !!m_value;
m_value = JSValue();
@@ -465,8 +216,8 @@ struct AbstractValue {
mergeSpeculation(m_type, type);
if (type & SpecCell) {
- m_structure.makeTop();
- m_unclobberedStructure.makeTop();
+ m_currentKnownStructure.makeTop();
+ m_futurePossibleStructure.makeTop();
}
m_value = JSValue();
@@ -476,19 +227,21 @@ struct AbstractValue {
void filter(const StructureSet& other)
{
m_type &= other.speculationFromStructures();
- m_structure.filter(other);
- m_unclobberedStructure.filter(other);
+ m_currentKnownStructure.filter(other);
+ if (m_currentKnownStructure.isClear())
+ m_futurePossibleStructure.clear();
+ else if (m_currentKnownStructure.hasSingleton())
+ filterFuturePossibleStructure(m_currentKnownStructure.singleton());
// It's possible that prior to the above two statements we had (Foo, TOP), where
// Foo is a SpeculatedType that is disjoint with the passed StructureSet. In that
// case, we will now have (None, [someStructure]). In general, we need to make
// sure that new information gleaned from the SpeculatedType needs to be fed back
// into the information gleaned from the StructureSet.
- m_structure.filter(m_type);
- m_unclobberedStructure.filter(m_type);
+ m_currentKnownStructure.filter(m_type);
+ m_futurePossibleStructure.filter(m_type);
- if (!!m_value && !validateIgnoringValue(m_value))
- clear();
+ filterValueByType();
checkConsistency();
}
@@ -503,47 +256,38 @@ struct AbstractValue {
// the passed type is Array. At this point we'll have (None, TOP). The best way
// to ensure that the structure filtering does the right thing is to filter on
// the new type (None) rather than the one passed (Array).
- m_structure.filter(m_type);
- m_unclobberedStructure.filter(m_type);
+ m_currentKnownStructure.filter(m_type);
+ m_futurePossibleStructure.filter(m_type);
- if (!!m_value && !validateIgnoringValue(m_value))
- clear();
+ filterValueByType();
checkConsistency();
}
- bool validateIgnoringValue(JSValue value) const
+ // We could go further, and ensure that if the futurePossibleStructure contravenes
+ // the value, then we could clear both of those things. But that's unlikely to help
+ // in any realistic scenario, so we don't do it. Simpler is better.
+ void filterValueByType()
{
- if (isTop())
- return true;
-
- if (mergeSpeculations(m_type, speculationFromValue(value)) != m_type)
- return false;
-
- if (value.isEmpty()) {
- ASSERT(m_type & SpecEmpty);
- return true;
- }
-
- if (m_structure.isTop())
- return true;
-
- if (!!value && value.isCell()) {
- ASSERT(m_type & SpecCell);
- return m_structure.contains(value.asCell()->structure());
+ if (!!m_type) {
+ // The type is still non-empty. This implies that regardless of what filtering
+ // was done, we either didn't have a value to begin with, or that value is still
+ // valid.
+ ASSERT(!m_value || validateType(m_value));
+ return;
}
- return true;
+ // The type has been rendered empty. That means that the value must now be invalid,
+ // as well.
+ ASSERT(!m_value || !validateType(m_value));
+ m_value = JSValue();
}
- bool validate(JSValue value) const
+ bool validateType(JSValue value) const
{
if (isTop())
return true;
- if (!!m_value && m_value != value)
- return false;
-
if (mergeSpeculations(m_type, speculationFromValue(value)) != m_type)
return false;
@@ -552,18 +296,10 @@ struct AbstractValue {
return true;
}
- if (m_structure.isTop())
- return true;
-
- if (!!value && value.isCell()) {
- ASSERT(m_type & SpecCell);
- return m_structure.contains(value.asCell()->structure());
- }
-
return true;
}
- bool validateForEntry(JSValue value) const
+ bool validate(JSValue value) const
{
if (isTop())
return true;
@@ -579,12 +315,11 @@ struct AbstractValue {
return true;
}
- if (m_unclobberedStructure.isTop())
- return true;
-
if (!!value && value.isCell()) {
ASSERT(m_type & SpecCell);
- return m_unclobberedStructure.contains(value.asCell()->structure());
+ Structure* structure = value.asCell()->structure();
+ return m_currentKnownStructure.contains(structure)
+ && m_futurePossibleStructure.contains(structure);
}
return true;
@@ -593,8 +328,8 @@ struct AbstractValue {
void checkConsistency() const
{
if (!(m_type & SpecCell)) {
- ASSERT(m_structure.isClear());
- ASSERT(m_unclobberedStructure.isClear());
+ ASSERT(m_currentKnownStructure.isClear());
+ ASSERT(m_futurePossibleStructure.isClear());
}
if (isClear())
@@ -612,17 +347,102 @@ struct AbstractValue {
void dump(FILE* out) const
{
fprintf(out, "(%s, ", speculationToString(m_type));
- m_structure.dump(out);
+ m_currentKnownStructure.dump(out);
dataLog(", ");
- m_unclobberedStructure.dump(out);
+ m_futurePossibleStructure.dump(out);
if (!!m_value)
fprintf(out, ", %s", m_value.description());
fprintf(out, ")");
}
+
+ // A great way to think about the difference between m_currentKnownStructure and
+ // m_futurePossibleStructure is to consider these four examples:
+ //
+ // 1) x = foo();
+ //
+ // In this case x's m_currentKnownStructure and m_futurePossibleStructure will
+ // both be TOP, since we don't know anything about x for sure, yet.
+ //
+ // 2) x = foo();
+ // y = x.f;
+ //
+ // Where x will later have a new property added to it, 'g'. Because of the
+ // known but not-yet-executed property addition, x's currently structure will
+ // not be watchpointable; hence we have no way of statically bounding the set
+ // of possible structures that x may have if a clobbering event happens. So,
+ // x's m_currentKnownStructure will be whatever structure we check to get
+ // property 'f', and m_futurePossibleStructure will be TOP.
+ //
+ // 3) x = foo();
+ // y = x.f;
+ //
+ // Where x has a terminal structure that is still watchpointable. In this case,
+ // x's m_currentKnownStructure and m_futurePossibleStructure will both be
+ // whatever structure we checked for when getting 'f'.
+ //
+ // 4) x = foo();
+ // y = x.f;
+ // bar();
+ //
+ // Where x has a terminal structure that is still watchpointable. In this
+ // case, m_currentKnownStructure will be TOP because bar() may potentially
+ // change x's structure and we have no way of proving otherwise, but
+ // x's m_futurePossibleStructure will be whatever structure we had checked
+ // when getting property 'f'.
- StructureAbstractValue m_structure;
- StructureAbstractValue m_unclobberedStructure;
+ // This is a proven constraint on the structures that this value can have right
+ // now. The structure of the current value must belong to this set. The set may
+ // be TOP, indicating that it is the set of all possible structures, in which
+ // case the current value can have any structure. The set may be BOTTOM (empty)
+ // in which case this value cannot be a cell. This is all subject to change
+ // anytime a new value is assigned to this one, anytime there is a control flow
+ // merge, or most crucially, anytime a side-effect or structure check happens.
+ // In case of a side-effect, we typically must assume that any value may have
+ // had its structure changed, hence contravening our proof. We make the proof
+ // valid again by switching this to TOP (i.e. claiming that we have proved that
+ // this value may have any structure). Of note is that the proof represented by
+ // this field is not subject to structure transition watchpoints - even if one
+ // fires, we can be sure that this proof is still valid.
+ StructureAbstractValue m_currentKnownStructure;
+
+ // This is a proven constraint on the structures that this value can have now
+ // or any time in the future subject to the structure transition watchpoints of
+ // all members of this set not having fired. This set is impervious to side-
+ // effects; even if one happens the side-effect can only cause the value to
+ // change to at worst another structure that is also a member of this set. But,
+ // the theorem being proved by this field is predicated upon there not being
+ // any new structure transitions introduced into any members of this set. In
+ // cases where there is no way for us to guard this happening, the set must be
+ // TOP. But in cases where we can guard new structure transitions (all members
+ // of the set have still-valid structure transition watchpoints) then this set
+ // will be finite. Anytime that we make use of the finite nature of this set,
+ // we must first issue a structure transition watchpoint, which will effectively
+ // result in m_currentKnownStructure being filtered according to
+ // m_futurePossibleStructure.
+ StructureAbstractValue m_futurePossibleStructure;
+
+ // This is a proven constraint on the possible types that this value can have
+ // now or any time in the future, unless it is reassigned. This field is
+ // impervious to side-effects unless the side-effect can reassign the value
+ // (for example if we're talking about a captured variable). The relationship
+ // between this field, and the structure fields above, is as follows. The
+ // fields above constraint the structures that a cell may have, but they say
+ // nothing about whether or not the value is known to be a cell. More formally,
+ // the m_currentKnownStructure is itself an abstract value that consists of the
+ // union of the set of all non-cell values and the set of cell values that have
+ // the given structure. This abstract value is then the intersection of the
+ // m_currentKnownStructure and the set of values whose type is m_type. So, for
+ // example if m_type is SpecFinal|SpecInt32 and m_currentKnownStructure is
+ // [0x12345] then this abstract value corresponds to the set of all integers
+ // unified with the set of all objects with structure 0x12345.
SpeculatedType m_type;
+
+ // This is a proven constraint on the possible values that this value can
+ // have now or any time in the future, unless it is reassigned. Note that this
+ // implies nothing about the structure. Oddly, JSValue() (i.e. the empty value)
+ // means either BOTTOM or TOP depending on the state of m_type: if m_type is
+ // BOTTOM then JSValue() means BOTTOM; if m_type is not BOTTOM then JSValue()
+ // means TOP.
JSValue m_value;
};
diff --git a/Source/JavaScriptCore/dfg/DFGArgumentsSimplificationPhase.cpp b/Source/JavaScriptCore/dfg/DFGArgumentsSimplificationPhase.cpp
index 9208cde1b..000e1a938 100644
--- a/Source/JavaScriptCore/dfg/DFGArgumentsSimplificationPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGArgumentsSimplificationPhase.cpp
@@ -317,6 +317,17 @@ public:
// PhantomArguments and OSR exit will still do the right things.
break;
+ case CheckStructure:
+ case ForwardCheckStructure:
+ case StructureTransitionWatchpoint:
+ case ForwardStructureTransitionWatchpoint:
+ // We don't care about these because if we get uses of the relevant
+ // variable then we can safely get rid of these, too. This of course
+ // relies on there not being any information transferred by the CFA
+ // from a CheckStructure on one variable to the information about the
+ // structures of another variable.
+ break;
+
default:
observeBadArgumentsUses(node);
break;
@@ -471,6 +482,19 @@ public:
break;
}
+ case CheckStructure:
+ case ForwardCheckStructure:
+ case StructureTransitionWatchpoint:
+ case ForwardStructureTransitionWatchpoint: {
+ // We can just get rid of this node, if it references a phantom argument.
+ if (!isOKToOptimize(m_graph[node.child1()]))
+ break;
+ m_graph.deref(node.child1());
+ node.setOpAndDefaultFlags(Phantom);
+ node.children.setChild1(Edge());
+ break;
+ }
+
case GetByVal: {
if (!node.prediction()
|| !m_graph[node.child1()].prediction()
diff --git a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
index b7f48aa4b..f7536f87f 100644
--- a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
+++ b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
@@ -118,7 +118,7 @@ private:
template<PhiStackType stackType>
void processPhiStack();
- void fixVariableAccessSpeculations();
+ void fixVariableAccessPredictions();
// Add spill locations to nodes.
void allocateVirtualRegisters();
@@ -2149,6 +2149,10 @@ bool ByteCodeParser::parseBlock(unsigned limit)
NodeIndex base = get(currentInstruction[2].u.operand);
NodeIndex property = get(currentInstruction[3].u.operand);
+ ArrayProfile* profile = currentInstruction[4].u.arrayProfile;
+ profile->computeUpdatedPrediction();
+ if (profile->hasDefiniteStructure())
+ addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(profile->expectedStructure())), base);
NodeIndex propertyStorage = addToGraph(GetIndexedPropertyStorage, base, property);
NodeIndex getByVal = addToGraph(GetByVal, OpInfo(0), OpInfo(prediction), base, property, propertyStorage);
set(currentInstruction[1].u.operand, getByVal);
@@ -2160,6 +2164,15 @@ bool ByteCodeParser::parseBlock(unsigned limit)
NodeIndex base = get(currentInstruction[1].u.operand);
NodeIndex property = get(currentInstruction[2].u.operand);
NodeIndex value = get(currentInstruction[3].u.operand);
+
+ ArrayProfile* profile = currentInstruction[4].u.arrayProfile;
+ profile->computeUpdatedPrediction();
+ if (profile->hasDefiniteStructure())
+ addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(profile->expectedStructure())), base);
+
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+ dataLog("Slow case profile for bc#%u: %u\n", m_currentIndex, m_inlineStackTop->m_profiledBlock->rareCaseProfileForBytecodeOffset(m_currentIndex)->m_counter);
+#endif
bool makeSafe =
m_inlineStackTop->m_profiledBlock->couldTakeSlowCase(m_currentIndex)
@@ -3017,7 +3030,7 @@ void ByteCodeParser::processPhiStack()
}
}
-void ByteCodeParser::fixVariableAccessSpeculations()
+void ByteCodeParser::fixVariableAccessPredictions()
{
for (unsigned i = 0; i < m_graph.m_variableAccessData.size(); ++i) {
VariableAccessData* data = &m_graph.m_variableAccessData[i];
@@ -3349,7 +3362,27 @@ bool ByteCodeParser::parse()
m_graph.m_blocks[blockIndex].clear();
}
- fixVariableAccessSpeculations();
+ fixVariableAccessPredictions();
+
+ for (BlockIndex blockIndex = 0; blockIndex < m_graph.m_blocks.size(); ++blockIndex) {
+ BasicBlock* block = m_graph.m_blocks[blockIndex].get();
+ if (!block)
+ continue;
+ if (!block->isOSRTarget)
+ continue;
+ if (block->bytecodeBegin != m_graph.m_osrEntryBytecodeIndex)
+ continue;
+ for (size_t i = 0; i < m_graph.m_mustHandleValues.size(); ++i) {
+ NodeIndex nodeIndex = block->variablesAtHead.operand(
+ m_graph.m_mustHandleValues.operandForIndex(i));
+ if (nodeIndex == NoNode)
+ continue;
+ Node& node = m_graph[nodeIndex];
+ ASSERT(node.hasLocal());
+ node.variableAccessData()->predict(
+ speculationFromValue(m_graph.m_mustHandleValues[i]));
+ }
+ }
m_graph.m_preservedVars = m_preservedVars;
m_graph.m_localVars = m_numLocals;
diff --git a/Source/JavaScriptCore/dfg/DFGCFGSimplificationPhase.cpp b/Source/JavaScriptCore/dfg/DFGCFGSimplificationPhase.cpp
index dc1632dc4..f054707e2 100644
--- a/Source/JavaScriptCore/dfg/DFGCFGSimplificationPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGCFGSimplificationPhase.cpp
@@ -613,7 +613,9 @@ private:
ASSERT(node.shouldGenerate());
Node& possibleLocalOp = m_graph[node.child1()];
- if (possibleLocalOp.hasLocal() && !possibleLocalOp.variableAccessData()->isCaptured()) {
+ if (possibleLocalOp.op() != GetLocal
+ && possibleLocalOp.hasLocal()
+ && !possibleLocalOp.variableAccessData()->isCaptured()) {
NodeIndex setLocalIndex =
firstBlock->variablesAtTail.operand(possibleLocalOp.local());
Node& setLocal = m_graph[setLocalIndex];
diff --git a/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp b/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp
index e9b1e0d8b..b78ddc89d 100644
--- a/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp
@@ -345,6 +345,7 @@ private:
break;
case StructureTransitionWatchpoint:
+ case ForwardStructureTransitionWatchpoint:
if (node.child1() == child1
&& structureSet.contains(node.structure()))
return true;
@@ -418,6 +419,7 @@ private:
return false;
case StructureTransitionWatchpoint:
+ case ForwardStructureTransitionWatchpoint:
if (node.structure() == structure && node.child1() == child1)
return true;
break;
@@ -843,6 +845,8 @@ private:
// At this point we will eliminate all references to this node.
m_replacements[m_compileIndex] = replacement;
+ m_changed = true;
+
return true;
}
@@ -856,6 +860,8 @@ private:
ASSERT(node.refCount() == 1);
ASSERT(node.mustGenerate());
node.setOpAndDefaultFlags(Phantom);
+
+ m_changed = true;
}
void eliminate(NodeIndex nodeIndex, NodeType phantomType = Phantom)
@@ -867,6 +873,8 @@ private:
return;
ASSERT(node.mustGenerate());
node.setOpAndDefaultFlags(phantomType);
+
+ m_changed = true;
}
void performNodeCSE(Node& node)
@@ -944,7 +952,7 @@ private:
case GetLocal: {
VariableAccessData* variableAccessData = node.variableAccessData();
- if (m_fixpointState == FixpointNotConverged && !variableAccessData->isCaptured())
+ if (!variableAccessData->isCaptured())
break;
NodeIndex relevantLocalOp;
NodeIndex possibleReplacement = getLocalLoadElimination(variableAccessData->local(), relevantLocalOp, variableAccessData->isCaptured());
@@ -982,7 +990,7 @@ private:
case GetLocalUnlinked: {
NodeIndex relevantLocalOpIgnored;
- m_changed |= setReplacement(getLocalLoadElimination(node.unlinkedLocal(), relevantLocalOpIgnored, true));
+ setReplacement(getLocalLoadElimination(node.unlinkedLocal(), relevantLocalOpIgnored, true));
break;
}
@@ -1117,6 +1125,7 @@ private:
break;
case StructureTransitionWatchpoint:
+ case ForwardStructureTransitionWatchpoint:
if (structureTransitionWatchpointElimination(node.structure(), node.child1().index()))
eliminate();
break;
diff --git a/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp b/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp
index a8eb9ee5c..68d5534e0 100644
--- a/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp
@@ -91,7 +91,16 @@ private:
break;
}
- // FIXME: This would be a great place to remove CheckStructure's.
+ case CheckStructure:
+ case ForwardCheckStructure: {
+ AbstractValue& value = m_state.forNode(node.child1());
+ StructureAbstractValue& structureValue = value.m_futurePossibleStructure;
+ if (structureValue.isSubsetOf(node.structureSet())
+ && structureValue.hasSingleton()
+ && isCellSpeculation(value.m_type))
+ node.convertToStructureTransitionWatchpoint(structureValue.singleton());
+ break;
+ }
default:
break;
@@ -103,9 +112,7 @@ private:
}
m_state.execute(indexInBlock);
- if (!node.shouldGenerate()
- || m_state.didClobber()
- || node.hasConstant())
+ if (!node.shouldGenerate() || m_state.didClobber() || node.hasConstant())
continue;
JSValue value = m_state.forNode(nodeIndex).value();
if (!value)
diff --git a/Source/JavaScriptCore/dfg/DFGDriver.cpp b/Source/JavaScriptCore/dfg/DFGDriver.cpp
index ddad4f864..ccef65208 100644
--- a/Source/JavaScriptCore/dfg/DFGDriver.cpp
+++ b/Source/JavaScriptCore/dfg/DFGDriver.cpp
@@ -26,6 +26,10 @@
#include "config.h"
#include "DFGDriver.h"
+#include "JSObject.h"
+#include "JSString.h"
+#include "ScopeChain.h"
+
#if ENABLE(DFG_JIT)
#include "DFGArgumentsSimplificationPhase.h"
@@ -53,7 +57,7 @@ unsigned getNumCompilations()
}
enum CompileMode { CompileFunction, CompileOther };
-inline bool compile(CompileMode compileMode, ExecState* exec, CodeBlock* codeBlock, JITCode& jitCode, MacroAssemblerCodePtr* jitCodeWithArityCheck)
+inline bool compile(CompileMode compileMode, ExecState* exec, CodeBlock* codeBlock, JITCode& jitCode, MacroAssemblerCodePtr* jitCodeWithArityCheck, unsigned osrEntryBytecodeIndex)
{
SamplingRegion samplingRegion("DFG Compilation (Driver)");
@@ -62,6 +66,8 @@ inline bool compile(CompileMode compileMode, ExecState* exec, CodeBlock* codeBlo
ASSERT(codeBlock);
ASSERT(codeBlock->alternative());
ASSERT(codeBlock->alternative()->getJITType() == JITCode::BaselineJIT);
+
+ ASSERT(osrEntryBytecodeIndex != UINT_MAX);
if (!Options::useDFGJIT())
return false;
@@ -70,7 +76,30 @@ inline bool compile(CompileMode compileMode, ExecState* exec, CodeBlock* codeBlo
dataLog("DFG compiling code block %p(%p) for executable %p, number of instructions = %u.\n", codeBlock, codeBlock->alternative(), codeBlock->ownerExecutable(), codeBlock->instructionCount());
#endif
- Graph dfg(exec->globalData(), codeBlock);
+ // Derive our set of must-handle values. The compilation must be at least conservative
+ // enough to allow for OSR entry with these values.
+ unsigned numVarsWithValues;
+ if (osrEntryBytecodeIndex)
+ numVarsWithValues = codeBlock->m_numVars;
+ else
+ numVarsWithValues = 0;
+ Operands<JSValue> mustHandleValues(codeBlock->numParameters(), numVarsWithValues);
+ for (size_t i = 0; i < mustHandleValues.size(); ++i) {
+ int operand = mustHandleValues.operandForIndex(i);
+ if (operandIsArgument(operand)
+ && !operandToArgument(operand)
+ && compileMode == CompileFunction
+ && codeBlock->specializationKind() == CodeForConstruct) {
+ // Ugh. If we're in a constructor, the 'this' argument may hold garbage. It will
+ // also never be used. It doesn't matter what we put into the value for this,
+ // but it has to be an actual value that can be grokked by subsequent DFG passes,
+ // so we sanitize it here by turning it into Undefined.
+ mustHandleValues[i] = jsUndefined();
+ } else
+ mustHandleValues[i] = exec->uncheckedR(operand).jsValue();
+ }
+
+ Graph dfg(exec->globalData(), codeBlock, osrEntryBytecodeIndex, mustHandleValues);
if (!parse(exec, dfg))
return false;
@@ -86,6 +115,7 @@ inline bool compile(CompileMode compileMode, ExecState* exec, CodeBlock* codeBlo
validate(dfg);
performPredictionPropagation(dfg);
performFixup(dfg);
+ performStructureCheckHoisting(dfg);
unsigned cnt = 1;
for (;; ++cnt) {
#if DFG_ENABLE(DEBUG_VERBOSE)
@@ -102,10 +132,7 @@ inline bool compile(CompileMode compileMode, ExecState* exec, CodeBlock* codeBlo
dfg.resetExitStates();
performFixup(dfg);
}
- bool shouldRedoCFA = performStructureCheckHoisting(dfg);
performCSE(dfg, FixpointConverged);
- if (shouldRedoCFA)
- performCFA(dfg);
#if DFG_ENABLE(DEBUG_VERBOSE)
dataLog("DFG optimization fixpoint converged in %u iterations.\n", cnt);
#endif
@@ -135,14 +162,14 @@ inline bool compile(CompileMode compileMode, ExecState* exec, CodeBlock* codeBlo
return result;
}
-bool tryCompile(ExecState* exec, CodeBlock* codeBlock, JITCode& jitCode)
+bool tryCompile(ExecState* exec, CodeBlock* codeBlock, JITCode& jitCode, unsigned bytecodeIndex)
{
- return compile(CompileOther, exec, codeBlock, jitCode, 0);
+ return compile(CompileOther, exec, codeBlock, jitCode, 0, bytecodeIndex);
}
-bool tryCompileFunction(ExecState* exec, CodeBlock* codeBlock, JITCode& jitCode, MacroAssemblerCodePtr& jitCodeWithArityCheck)
+bool tryCompileFunction(ExecState* exec, CodeBlock* codeBlock, JITCode& jitCode, MacroAssemblerCodePtr& jitCodeWithArityCheck, unsigned bytecodeIndex)
{
- return compile(CompileFunction, exec, codeBlock, jitCode, &jitCodeWithArityCheck);
+ return compile(CompileFunction, exec, codeBlock, jitCode, &jitCodeWithArityCheck, bytecodeIndex);
}
} } // namespace JSC::DFG
diff --git a/Source/JavaScriptCore/dfg/DFGDriver.h b/Source/JavaScriptCore/dfg/DFGDriver.h
index a6e82fef5..1964ec34a 100644
--- a/Source/JavaScriptCore/dfg/DFGDriver.h
+++ b/Source/JavaScriptCore/dfg/DFGDriver.h
@@ -41,11 +41,11 @@ namespace DFG {
JS_EXPORT_PRIVATE unsigned getNumCompilations();
#if ENABLE(DFG_JIT)
-bool tryCompile(ExecState*, CodeBlock*, JITCode&);
-bool tryCompileFunction(ExecState*, CodeBlock*, JITCode&, MacroAssemblerCodePtr& jitCodeWithArityCheck);
+bool tryCompile(ExecState*, CodeBlock*, JITCode&, unsigned bytecodeIndex);
+bool tryCompileFunction(ExecState*, CodeBlock*, JITCode&, MacroAssemblerCodePtr& jitCodeWithArityCheck, unsigned bytecodeIndex);
#else
-inline bool tryCompile(ExecState*, CodeBlock*, JITCode&) { return false; }
-inline bool tryCompileFunction(ExecState*, CodeBlock*, JITCode&, MacroAssemblerCodePtr&) { return false; }
+inline bool tryCompile(ExecState*, CodeBlock*, JITCode&, unsigned) { return false; }
+inline bool tryCompileFunction(ExecState*, CodeBlock*, JITCode&, MacroAssemblerCodePtr&, unsigned) { return false; }
#endif
} } // namespace JSC::DFG
diff --git a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
index 4e3cd5782..f7b10fc43 100644
--- a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
@@ -96,9 +96,29 @@ private:
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
dataLog(" @%u -> %s", m_compileIndex, isArray ? "GetArrayLength" : "GetStringLength");
#endif
- if (isArray)
+ if (isArray) {
node.setOp(GetArrayLength);
- else if (isArguments)
+ ASSERT(node.flags() & NodeMustGenerate);
+ node.clearFlags(NodeMustGenerate);
+ m_graph.deref(m_compileIndex);
+
+ ArrayProfile* arrayProfile =
+ m_graph.baselineCodeBlockFor(node.codeOrigin)->getArrayProfile(
+ node.codeOrigin.bytecodeIndex);
+ if (!arrayProfile)
+ break;
+ arrayProfile->computeUpdatedPrediction();
+ if (!arrayProfile->hasDefiniteStructure())
+ break;
+ m_graph.ref(node.child1());
+ Node checkStructure(CheckStructure, node.codeOrigin, OpInfo(m_graph.addStructureSet(arrayProfile->expectedStructure())), node.child1().index());
+ checkStructure.ref();
+ NodeIndex checkStructureIndex = m_graph.size();
+ m_graph.append(checkStructure);
+ m_insertionSet.append(m_indexInBlock, checkStructureIndex);
+ break;
+ }
+ if (isArguments)
node.setOp(GetArgumentsLength);
else if (isString)
node.setOp(GetStringLength);
@@ -129,10 +149,9 @@ private:
break;
}
case GetIndexedPropertyStorage: {
- SpeculatedType basePrediction = m_graph[node.child2()].prediction();
- if ((!(basePrediction & SpecInt32) && basePrediction)
- || m_graph[node.child1()].shouldSpeculateArguments()
- || !isActionableArraySpeculation(m_graph[node.child1()].prediction())) {
+ if (!m_graph[node.child1()].prediction()
+ || !m_graph[node.child2()].shouldSpeculateInteger()
+ || m_graph[node.child1()].shouldSpeculateArguments()) {
node.setOpAndDefaultFlags(Nop);
m_graph.clearAndDerefChild1(node);
m_graph.clearAndDerefChild2(node);
diff --git a/Source/JavaScriptCore/dfg/DFGGraph.h b/Source/JavaScriptCore/dfg/DFGGraph.h
index fdb78cf9b..8d164a299 100644
--- a/Source/JavaScriptCore/dfg/DFGGraph.h
+++ b/Source/JavaScriptCore/dfg/DFGGraph.h
@@ -76,11 +76,13 @@ struct ResolveGlobalData {
// Nodes that are 'dead' remain in the vector with refCount 0.
class Graph : public Vector<Node, 64> {
public:
- Graph(JSGlobalData& globalData, CodeBlock* codeBlock)
+ Graph(JSGlobalData& globalData, CodeBlock* codeBlock, unsigned osrEntryBytecodeIndex, const Operands<JSValue>& mustHandleValues)
: m_globalData(globalData)
, m_codeBlock(codeBlock)
, m_profiledBlock(codeBlock->alternative())
, m_hasArguments(false)
+ , m_osrEntryBytecodeIndex(osrEntryBytecodeIndex)
+ , m_mustHandleValues(mustHandleValues)
{
ASSERT(m_profiledBlock);
}
@@ -137,6 +139,20 @@ public:
edge = newEdge;
}
+ void compareAndSwap(Edge& edge, NodeIndex oldIndex, NodeIndex newIndex, bool changeRef)
+ {
+ if (edge.index() != oldIndex)
+ return;
+ changeIndex(edge, newIndex, changeRef);
+ }
+
+ void compareAndSwap(Edge& edge, Edge oldEdge, Edge newEdge, bool changeRef)
+ {
+ if (edge != oldEdge)
+ return;
+ changeEdge(edge, newEdge, changeRef);
+ }
+
void clearAndDerefChild1(Node& node)
{
if (!node.child1())
@@ -614,6 +630,69 @@ public:
vote(node.child3(), ballot);
}
+ template<typename T> // T = NodeIndex or Edge
+ void substitute(BasicBlock& block, unsigned startIndexInBlock, T oldThing, T newThing)
+ {
+ for (unsigned indexInBlock = startIndexInBlock; indexInBlock < block.size(); ++indexInBlock) {
+ NodeIndex nodeIndex = block[indexInBlock];
+ Node& node = at(nodeIndex);
+ if (node.flags() & NodeHasVarArgs) {
+ for (unsigned childIdx = node.firstChild(); childIdx < node.firstChild() + node.numChildren(); ++childIdx)
+ compareAndSwap(m_varArgChildren[childIdx], oldThing, newThing, node.shouldGenerate());
+ continue;
+ }
+ if (!node.child1())
+ continue;
+ compareAndSwap(node.children.child1(), oldThing, newThing, node.shouldGenerate());
+ if (!node.child2())
+ continue;
+ compareAndSwap(node.children.child2(), oldThing, newThing, node.shouldGenerate());
+ if (!node.child3())
+ continue;
+ compareAndSwap(node.children.child3(), oldThing, newThing, node.shouldGenerate());
+ }
+ }
+
+ // Use this if you introduce a new GetLocal and you know that you introduced it *before*
+ // any GetLocals in the basic block.
+ // FIXME: it may be appropriate, in the future, to generalize this to handle GetLocals
+ // introduced anywhere in the basic block.
+ void substituteGetLocal(BasicBlock& block, unsigned startIndexInBlock, VariableAccessData* variableAccessData, NodeIndex newGetLocal)
+ {
+ if (variableAccessData->isCaptured()) {
+ // Let CSE worry about this one.
+ return;
+ }
+ for (unsigned indexInBlock = startIndexInBlock; indexInBlock < block.size(); ++indexInBlock) {
+ NodeIndex nodeIndex = block[indexInBlock];
+ Node& node = at(nodeIndex);
+ bool shouldContinue = true;
+ switch (node.op()) {
+ case SetLocal: {
+ if (node.local() == variableAccessData->local())
+ shouldContinue = false;
+ break;
+ }
+
+ case GetLocal: {
+ if (node.variableAccessData() != variableAccessData)
+ continue;
+ substitute(block, indexInBlock, nodeIndex, newGetLocal);
+ NodeIndex oldTailIndex = block.variablesAtTail.operand(variableAccessData->local());
+ if (oldTailIndex == nodeIndex)
+ block.variablesAtTail.operand(variableAccessData->local()) = newGetLocal;
+ shouldContinue = false;
+ break;
+ }
+
+ default:
+ break;
+ }
+ if (!shouldContinue)
+ break;
+ }
+ }
+
JSGlobalData& m_globalData;
CodeBlock* m_codeBlock;
CodeBlock* m_profiledBlock;
@@ -633,6 +712,8 @@ public:
Dominators m_dominators;
unsigned m_localVars;
unsigned m_parameterSlots;
+ unsigned m_osrEntryBytecodeIndex;
+ Operands<JSValue> m_mustHandleValues;
private:
void handleSuccessor(Vector<BlockIndex, 16>& worklist, BlockIndex blockIndex, BlockIndex successorIndex);
diff --git a/Source/JavaScriptCore/dfg/DFGNode.h b/Source/JavaScriptCore/dfg/DFGNode.h
index 60cdd4b50..dac855be0 100644
--- a/Source/JavaScriptCore/dfg/DFGNode.h
+++ b/Source/JavaScriptCore/dfg/DFGNode.h
@@ -245,11 +245,19 @@ struct Node {
children.reset();
}
+ void convertToStructureTransitionWatchpoint(Structure* structure)
+ {
+ ASSERT(m_op == CheckStructure || m_op == ForwardCheckStructure);
+ m_opInfo = bitwise_cast<uintptr_t>(structure);
+ if (m_op == CheckStructure)
+ m_op = StructureTransitionWatchpoint;
+ else
+ m_op = ForwardStructureTransitionWatchpoint;
+ }
+
void convertToStructureTransitionWatchpoint()
{
- ASSERT(m_op == CheckStructure);
- m_opInfo = bitwise_cast<uintptr_t>(structureSet().singletonStructure());
- m_op = StructureTransitionWatchpoint;
+ convertToStructureTransitionWatchpoint(structureSet().singletonStructure());
}
JSCell* weakConstant()
@@ -675,7 +683,13 @@ struct Node {
bool hasStructure()
{
- return op() == StructureTransitionWatchpoint;
+ switch (op()) {
+ case StructureTransitionWatchpoint:
+ case ForwardStructureTransitionWatchpoint:
+ return true;
+ default:
+ return false;
+ }
}
Structure* structure()
diff --git a/Source/JavaScriptCore/dfg/DFGNodeType.h b/Source/JavaScriptCore/dfg/DFGNodeType.h
index 7657663a9..f0f8cb1d0 100644
--- a/Source/JavaScriptCore/dfg/DFGNodeType.h
+++ b/Source/JavaScriptCore/dfg/DFGNodeType.h
@@ -133,6 +133,7 @@ namespace JSC { namespace DFG {
/* the object's structure does not need to be rechecked due to side-effecting */\
/* (clobbering) operations. */\
macro(StructureTransitionWatchpoint, NodeMustGenerate) \
+ macro(ForwardStructureTransitionWatchpoint, NodeMustGenerate) \
macro(PutStructure, NodeMustGenerate) \
macro(PhantomPutStructure, NodeMustGenerate | NodeDoesNotExit) \
macro(AllocatePropertyStorage, NodeMustGenerate | NodeDoesNotExit | NodeResultStorage) \
diff --git a/Source/JavaScriptCore/dfg/DFGOSREntry.cpp b/Source/JavaScriptCore/dfg/DFGOSREntry.cpp
index 97061bfb2..9a7bc96cc 100644
--- a/Source/JavaScriptCore/dfg/DFGOSREntry.cpp
+++ b/Source/JavaScriptCore/dfg/DFGOSREntry.cpp
@@ -99,7 +99,7 @@ void* prepareOSREntry(ExecState* exec, CodeBlock* codeBlock, unsigned bytecodeIn
else
value = exec->argument(argument - 1);
- if (!entry->m_expectedValues.argument(argument).validateForEntry(value)) {
+ if (!entry->m_expectedValues.argument(argument).validate(value)) {
#if ENABLE(JIT_VERBOSE_OSR)
dataLog(" OSR failed because argument %zu is %s, expected ", argument, value.description());
entry->m_expectedValues.argument(argument).dump(WTF::dataFile());
@@ -119,7 +119,7 @@ void* prepareOSREntry(ExecState* exec, CodeBlock* codeBlock, unsigned bytecodeIn
}
continue;
}
- if (!entry->m_expectedValues.local(local).validateForEntry(exec->registers()[local].jsValue())) {
+ if (!entry->m_expectedValues.local(local).validate(exec->registers()[local].jsValue())) {
#if ENABLE(JIT_VERBOSE_OSR)
dataLog(" OSR failed because variable %zu is %s, expected ", local, exec->registers()[local].jsValue().description());
entry->m_expectedValues.local(local).dump(WTF::dataFile());
diff --git a/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp b/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
index 94f69abc2..1247528e8 100644
--- a/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
@@ -675,6 +675,7 @@ private:
case CheckStructure:
case ForwardCheckStructure:
case StructureTransitionWatchpoint:
+ case ForwardStructureTransitionWatchpoint:
case CheckFunction:
case PutStructure:
case TearOffActivation:
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
index f17e2d7e4..6c6615716 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
@@ -119,11 +119,8 @@ JumpReplacementWatchpoint* SpeculativeJIT::speculationWatchpoint(ExitKind kind)
return speculationWatchpoint(kind, JSValueSource(), NoNode);
}
-void SpeculativeJIT::forwardSpeculationCheck(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex, MacroAssembler::Jump jumpToFail, const ValueRecovery& valueRecovery)
+void SpeculativeJIT::convertLastOSRExitToForward(const ValueRecovery& valueRecovery)
{
- ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes);
- speculationCheck(kind, jsValueSource, nodeIndex, jumpToFail);
-
#if !ASSERT_DISABLED
if (!valueRecovery) {
// Check that the preceding node was a SetLocal with the same code origin.
@@ -155,6 +152,10 @@ void SpeculativeJIT::forwardSpeculationCheck(ExitKind kind, JSValueSource jsValu
ASSERT(setLocal->codeOrigin == at(m_compileIndex).codeOrigin);
Node* nextNode = &at(m_jit.graph().m_blocks[m_block]->at(setLocalIndexInBlock + 1));
+ if (nextNode->op() == Jump && nextNode->codeOrigin == at(m_compileIndex).codeOrigin) {
+ // We're at an inlined return. Use a backward speculation instead.
+ return;
+ }
ASSERT(nextNode->codeOrigin != at(m_compileIndex).codeOrigin);
OSRExit& exit = m_jit.codeBlock()->lastOSRExit();
@@ -167,6 +168,28 @@ void SpeculativeJIT::forwardSpeculationCheck(ExitKind kind, JSValueSource jsValu
new ValueRecoveryOverride(setLocal->local(), valueRecovery));
}
+JumpReplacementWatchpoint* SpeculativeJIT::forwardSpeculationWatchpoint(ExitKind kind)
+{
+ JumpReplacementWatchpoint* result = speculationWatchpoint(kind);
+ convertLastOSRExitToForward();
+ return result;
+}
+
+JumpReplacementWatchpoint* SpeculativeJIT::speculationWatchpointWithConditionalDirection(ExitKind kind, bool isForward)
+{
+ JumpReplacementWatchpoint* result = speculationWatchpoint(kind);
+ if (isForward)
+ convertLastOSRExitToForward();
+ return result;
+}
+
+void SpeculativeJIT::forwardSpeculationCheck(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex, MacroAssembler::Jump jumpToFail, const ValueRecovery& valueRecovery)
+{
+ ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes);
+ speculationCheck(kind, jsValueSource, nodeIndex, jumpToFail);
+ convertLastOSRExitToForward(valueRecovery);
+}
+
void SpeculativeJIT::forwardSpeculationCheck(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex, MacroAssembler::JumpList& jumpsToFail, const ValueRecovery& valueRecovery)
{
ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes);
@@ -246,6 +269,24 @@ void SpeculativeJIT::clearGenerationInfo()
m_fprs = RegisterBank<FPRInfo>();
}
+void SpeculativeJIT::speculateArray(Edge edge, GPRReg baseReg)
+{
+ AbstractValue& arrayValue = m_state.forNode(edge);
+ if (arrayValue.m_currentKnownStructure.hasSingleton()
+ && arrayValue.m_currentKnownStructure.singleton()->classInfo() == &JSArray::s_info)
+ return;
+
+ GPRTemporary temp(this);
+ m_jit.loadPtr(
+ MacroAssembler::Address(baseReg, JSCell::structureOffset()), temp.gpr());
+ speculationCheck(
+ Uncountable, JSValueRegs(), NoNode,
+ m_jit.branchPtr(
+ MacroAssembler::NotEqual,
+ MacroAssembler::Address(temp.gpr(), Structure::classInfoOffset()),
+ MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
+}
+
GPRReg SpeculativeJIT::fillStorage(NodeIndex nodeIndex)
{
Node& node = m_jit.graph()[nodeIndex];
@@ -1220,7 +1261,7 @@ void SpeculativeJIT::compile(BasicBlock& block)
valueSource = ValueSource(DoubleInRegisterFile);
else if (isInt32Speculation(argumentPosition.prediction()))
valueSource = ValueSource(Int32InRegisterFile);
- else if (isArraySpeculation(argumentPosition.prediction()) || isCellSpeculation(argumentPosition.prediction()))
+ else if (isCellSpeculation(argumentPosition.prediction()))
valueSource = ValueSource(CellInRegisterFile);
else if (isBooleanSpeculation(argumentPosition.prediction()))
valueSource = ValueSource(BooleanInRegisterFile);
@@ -1343,12 +1384,7 @@ void SpeculativeJIT::checkArgumentTypes()
#if USE(JSVALUE64)
if (isInt32Speculation(predictedType))
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::Below, JITCompiler::addressFor(virtualRegister), GPRInfo::tagTypeNumberRegister));
- else if (isArraySpeculation(predictedType)) {
- GPRTemporary temp(this);
- m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
- speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
- speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
- } else if (isBooleanSpeculation(predictedType)) {
+ else if (isBooleanSpeculation(predictedType)) {
GPRTemporary temp(this);
m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), temp.gpr());
@@ -1403,13 +1439,7 @@ void SpeculativeJIT::checkArgumentTypes()
#else
if (isInt32Speculation(predictedType))
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::Int32Tag)));
- else if (isArraySpeculation(predictedType)) {
- GPRTemporary temp(this);
- m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
- speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
- m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
- speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
- } else if (isBooleanSpeculation(predictedType))
+ else if (isBooleanSpeculation(predictedType))
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::BooleanTag)));
else if (isInt8ArraySpeculation(predictedType)) {
GPRTemporary temp(this);
@@ -1591,7 +1621,6 @@ void SpeculativeJIT::compileGetByValOnString(Node& node)
GPRReg storageReg = storage.gpr();
if (!isStringSpeculation(m_state.forNode(node.child1()).m_type)) {
- ASSERT(!(at(node.child1()).prediction() & SpecString));
terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
noResult(m_compileIndex);
return;
@@ -3037,22 +3066,12 @@ bool SpeculativeJIT::compileStrictEq(Node& node)
void SpeculativeJIT::compileGetIndexedPropertyStorage(Node& node)
{
- if (!node.prediction() || !at(node.child1()).prediction() || !at(node.child2()).prediction()) {
- terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), NoNode);
- return;
- }
+ ASSERT(at(node.child1()).prediction());
+ ASSERT(at(node.child2()).shouldSpeculateInteger());
SpeculateCellOperand base(this, node.child1());
GPRReg baseReg = base.gpr();
- SpeculatedType basePrediction = at(node.child2()).prediction();
- if (!(basePrediction & SpecInt32) && basePrediction) {
- ASSERT_NOT_REACHED();
- terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
- noResult(m_compileIndex);
- return;
- }
-
GPRTemporary storage(this);
GPRReg storageReg = storage.gpr();
if (at(node.child1()).shouldSpeculateArguments()) {
@@ -3113,8 +3132,7 @@ void SpeculativeJIT::compileGetIndexedPropertyStorage(Node& node)
speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
} else {
- if (!isArraySpeculation(m_state.forNode(node.child1()).m_type))
- speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
+ speculateArray(node.child1(), baseReg);
m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg);
}
storageResult(storageReg, m_compileIndex);
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
index 96f2fec0a..073dbb42c 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
@@ -2181,6 +2181,10 @@ public:
// act of firing a watchpoint invalidates it. So, future recompilations will not
// attempt to set this watchpoint again.
JumpReplacementWatchpoint* speculationWatchpoint(ExitKind = UncountableWatchpoint);
+
+ // It is generally a good idea to not use this directly.
+ void convertLastOSRExitToForward(const ValueRecovery& = ValueRecovery());
+
// Note: not specifying the valueRecovery argument (leaving it as ValueRecovery()) implies
// that you've ensured that there exists a MovHint prior to your use of forwardSpeculationCheck().
void forwardSpeculationCheck(ExitKind, JSValueSource, NodeIndex, MacroAssembler::Jump jumpToFail, const ValueRecovery& = ValueRecovery());
@@ -2190,6 +2194,12 @@ public:
void terminateSpeculativeExecution(ExitKind, JSValueRegs, NodeIndex);
void terminateSpeculativeExecution(ExitKind, JSValueRegs, Edge);
void terminateSpeculativeExecutionWithConditionalDirection(ExitKind, JSValueRegs, NodeIndex, bool isForward);
+ // Issue a forward speculation watchpoint, which will exit to the next instruction rather
+ // than the current one.
+ JumpReplacementWatchpoint* forwardSpeculationWatchpoint(ExitKind = UncountableWatchpoint);
+ JumpReplacementWatchpoint* speculationWatchpointWithConditionalDirection(ExitKind, bool isForward);
+
+ void speculateArray(Edge baseEdge, GPRReg baseReg);
template<bool strict>
GPRReg fillSpeculateIntInternal(NodeIndex, DataFormat& returnFormat);
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
index bf3503d6d..7a9ba1e41 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
@@ -1530,7 +1530,7 @@ void SpeculativeJIT::compileObjectToObjectOrOtherEquality(
// We know that within this branch, rightChild must not be a cell. Check if that is enough to
// prove that it is either null or undefined.
- if (!isOtherSpeculation(m_state.forNode(rightChild).m_type & ~SpecCell)) {
+ if (!isOtherOrEmptySpeculation(m_state.forNode(rightChild).m_type & ~SpecCell)) {
m_jit.move(op2TagGPR, resultGPR);
m_jit.or32(TrustedImm32(1), resultGPR);
@@ -1602,7 +1602,7 @@ void SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality(
// We know that within this branch, rightChild must not be a cell. Check if that is enough to
// prove that it is either null or undefined.
- if (isOtherSpeculation(m_state.forNode(rightChild).m_type & ~SpecCell))
+ if (isOtherOrEmptySpeculation(m_state.forNode(rightChild).m_type & ~SpecCell))
rightNotCell.link(&m_jit);
else {
jump(notTaken, ForceJump);
@@ -1918,7 +1918,7 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- if (isArraySpeculation(value.m_type) || isCellSpeculation(value.m_type)) {
+ if (isCellSpeculation(value.m_type)) {
GPRTemporary result(this);
m_jit.load32(JITCompiler::payloadFor(node.local()), result.gpr());
@@ -2036,16 +2036,6 @@ void SpeculativeJIT::compile(Node& node)
recordSetLocal(node.local(), ValueSource(Int32InRegisterFile));
break;
}
- if (isArraySpeculation(predictedType)) {
- SpeculateCellOperand cell(this, node.child1());
- GPRReg cellGPR = cell.gpr();
- if (!isArraySpeculation(m_state.forNode(node.child1()).m_type))
- speculationCheck(BadType, JSValueSource::unboxedCell(cellGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(cellGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
- m_jit.storePtr(cellGPR, JITCompiler::payloadFor(node.local()));
- noResult(m_compileIndex);
- recordSetLocal(node.local(), ValueSource(CellInRegisterFile));
- break;
- }
if (isCellSpeculation(predictedType)) {
SpeculateCellOperand cell(this, node.child1());
GPRReg cellGPR = cell.gpr();
@@ -2356,7 +2346,7 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- if (!at(node.child2()).shouldSpeculateInteger() || !isActionableArraySpeculation(at(node.child1()).prediction())) {
+ if (!at(node.child2()).shouldSpeculateInteger() || (!node.child3() && !at(node.child1()).shouldSpeculateArguments())) {
SpeculateCellOperand base(this, node.child1()); // Save a register, speculate cell. We'll probably be right.
JSValueOperand property(this, node.child2());
GPRReg baseGPR = base.gpr();
@@ -2449,8 +2439,6 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- ASSERT(at(node.child1()).shouldSpeculateArray());
-
SpeculateStrictInt32Operand property(this, node.child2());
StorageOperand storage(this, node.child3());
GPRReg propertyReg = property.gpr();
@@ -2464,17 +2452,13 @@ void SpeculativeJIT::compile(Node& node)
{
SpeculateCellOperand base(this, node.child1());
GPRReg baseReg = base.gpr();
- if (!isArraySpeculation(m_state.forNode(node.child1()).m_type))
- speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
+ // We've already speculated that it's some kind of array, at this point.
speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, JSArray::vectorLengthOffset())));
}
GPRTemporary resultTag(this);
GPRTemporary resultPayload(this);
- // FIXME: In cases where there are subsequent by_val accesses to the same base it might help to cache
- // the storage pointer - especially if there happens to be another register free right now. If we do so,
- // then we'll need to allocate a new temporary for result.
m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTag.gpr());
speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::Equal, resultTag.gpr(), TrustedImm32(JSValue::EmptyValueTag)));
m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayload.gpr());
@@ -2495,7 +2479,6 @@ void SpeculativeJIT::compile(Node& node)
}
if (!at(child2).shouldSpeculateInteger()
- || !isActionableMutableArraySpeculation(at(child1).prediction())
|| at(child1).shouldSpeculateArguments()) {
SpeculateCellOperand base(this, child1); // Save a register, speculate cell. We'll probably be right.
JSValueOperand property(this, child2);
@@ -2578,27 +2561,23 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- ASSERT(at(child1).shouldSpeculateArray());
-
JSValueOperand value(this, child3);
- GPRTemporary scratch(this);
-
// Map base, property & value into registers, allocate a scratch register.
GPRReg baseReg = base.gpr();
GPRReg propertyReg = property.gpr();
GPRReg valueTagReg = value.tagGPR();
GPRReg valuePayloadReg = value.payloadGPR();
- GPRReg scratchReg = scratch.gpr();
if (!m_compileOkay)
return;
-
- writeBarrier(baseReg, valueTagReg, child3, WriteBarrierForPropertyAccess, scratchReg);
- // Check that base is an array, and that property is contained within m_vector (< m_vectorLength).
- // If we have predicted the base to be type array, we can skip the check.
- if (!isArraySpeculation(m_state.forNode(child1).m_type))
- speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), child1, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
+ {
+ GPRTemporary scratch(this);
+ GPRReg scratchReg = scratch.gpr();
+ writeBarrier(baseReg, valueTagReg, child3, WriteBarrierForPropertyAccess, scratchReg);
+ }
+
+ speculateArray(child1, baseReg);
MacroAssembler::Jump beyondArrayBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, JSArray::vectorLengthOffset()));
if (node.op() == PutByVal)
@@ -2609,7 +2588,8 @@ void SpeculativeJIT::compile(Node& node)
value.use();
// Get the array storage.
- GPRReg storageReg = scratchReg;
+ GPRTemporary storage(this);
+ GPRReg storageReg = storage.gpr();
m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg);
// Check if we're writing to a hole; if so increment m_numValuesInVector.
@@ -2795,20 +2775,23 @@ void SpeculativeJIT::compile(Node& node)
case ArrayPush: {
SpeculateCellOperand base(this, node.child1());
JSValueOperand value(this, node.child2());
- GPRTemporary storage(this);
GPRTemporary storageLength(this);
GPRReg baseGPR = base.gpr();
GPRReg valueTagGPR = value.tagGPR();
GPRReg valuePayloadGPR = value.payloadGPR();
- GPRReg storageGPR = storage.gpr();
GPRReg storageLengthGPR = storageLength.gpr();
- writeBarrier(baseGPR, valueTagGPR, node.child2(), WriteBarrierForPropertyAccess, storageGPR, storageLengthGPR);
+ {
+ GPRTemporary scratch(this);
+ writeBarrier(baseGPR, valueTagGPR, node.child2(), WriteBarrierForPropertyAccess, scratch.gpr(), storageLengthGPR);
+ }
- if (!isArraySpeculation(m_state.forNode(node.child1()).m_type))
- speculationCheck(BadType, JSValueSource::unboxedCell(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
+ speculateArray(node.child1(), baseGPR);
+ GPRTemporary storage(this);
+ GPRReg storageGPR = storage.gpr();
+
m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), storageGPR);
m_jit.load32(MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_length)), storageLengthGPR);
@@ -2844,8 +2827,7 @@ void SpeculativeJIT::compile(Node& node)
GPRReg storageGPR = storage.gpr();
GPRReg storageLengthGPR = storageLength.gpr();
- if (!isArraySpeculation(m_state.forNode(node.child1()).m_type))
- speculationCheck(BadType, JSValueSource::unboxedCell(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
+ speculateArray(node.child1(), baseGPR);
m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), storageGPR);
m_jit.load32(MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_length)), storageLengthGPR);
@@ -3395,8 +3377,7 @@ void SpeculativeJIT::compile(Node& node)
SpeculateCellOperand base(this, node.child1());
GPRReg baseGPR = base.gpr();
- if (!isArraySpeculation(m_state.forNode(node.child1()).m_type))
- speculationCheck(BadType, JSValueSource::unboxedCell(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
+ speculateArray(node.child1(), baseGPR);
GPRTemporary result(this);
GPRReg resultGPR = result.gpr();
@@ -3478,7 +3459,7 @@ void SpeculativeJIT::compile(Node& node)
case CheckStructure:
case ForwardCheckStructure: {
AbstractValue& value = m_state.forNode(node.child1());
- if (value.m_structure.isSubsetOf(node.structureSet())
+ if (value.m_currentKnownStructure.isSubsetOf(node.structureSet())
&& isCellSpeculation(value.m_type)) {
noResult(m_compileIndex);
break;
@@ -3519,9 +3500,12 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- case StructureTransitionWatchpoint: {
+ case StructureTransitionWatchpoint:
+ case ForwardStructureTransitionWatchpoint: {
m_jit.addWeakReference(node.structure());
- node.structure()->addTransitionWatchpoint(speculationWatchpoint(BadCache));
+ node.structure()->addTransitionWatchpoint(
+ speculationWatchpointWithConditionalDirection(
+ BadCache, node.op() == ForwardStructureTransitionWatchpoint));
#if !ASSERT_DISABLED
SpeculateCellOperand op1(this, node.child1());
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
index 5541113f2..c2151088c 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
@@ -2072,16 +2072,6 @@ void SpeculativeJIT::compile(Node& node)
recordSetLocal(node.local(), ValueSource(Int32InRegisterFile));
break;
}
- if (isArraySpeculation(predictedType)) {
- SpeculateCellOperand cell(this, node.child1());
- GPRReg cellGPR = cell.gpr();
- if (!isArraySpeculation(m_state.forNode(node.child1()).m_type))
- speculationCheck(BadType, JSValueRegs(cellGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(cellGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
- m_jit.storePtr(cellGPR, JITCompiler::addressFor(node.local()));
- noResult(m_compileIndex);
- recordSetLocal(node.local(), ValueSource(CellInRegisterFile));
- break;
- }
if (isCellSpeculation(predictedType)) {
SpeculateCellOperand cell(this, node.child1());
GPRReg cellGPR = cell.gpr();
@@ -2389,7 +2379,7 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- if (!at(node.child2()).shouldSpeculateInteger() || !isActionableArraySpeculation(at(node.child1()).prediction())) {
+ if (!at(node.child2()).shouldSpeculateInteger() || (!node.child3() && !at(node.child1()).shouldSpeculateArguments())) {
JSValueOperand base(this, node.child1());
JSValueOperand property(this, node.child2());
GPRReg baseGPR = base.gpr();
@@ -2480,8 +2470,6 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- ASSERT(at(node.child1()).shouldSpeculateArray());
-
SpeculateCellOperand base(this, node.child1());
SpeculateStrictInt32Operand property(this, node.child2());
StorageOperand storage(this, node.child3());
@@ -2493,13 +2481,11 @@ void SpeculativeJIT::compile(Node& node)
if (!m_compileOkay)
return;
- if (!isArraySpeculation(m_state.forNode(node.child1()).m_type))
- speculationCheck(BadType, JSValueRegs(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
+ // We will have already speculated that the base is some kind of array,
+ // at this point.
+
speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, JSArray::vectorLengthOffset())));
- // FIXME: In cases where there are subsequent by_val accesses to the same base it might help to cache
- // the storage pointer - especially if there happens to be another register free right now. If we do so,
- // then we'll need to allocate a new temporary for result.
GPRTemporary result(this);
m_jit.loadPtr(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), result.gpr());
speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchTestPtr(MacroAssembler::Zero, result.gpr()));
@@ -2519,7 +2505,7 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- if (!at(child2).shouldSpeculateInteger() || !isActionableMutableArraySpeculation(at(child1).prediction())) {
+ if (!at(child2).shouldSpeculateInteger()) {
JSValueOperand arg1(this, child1);
JSValueOperand arg2(this, child2);
JSValueOperand arg3(this, child3);
@@ -2537,9 +2523,8 @@ void SpeculativeJIT::compile(Node& node)
SpeculateCellOperand base(this, child1);
SpeculateStrictInt32Operand property(this, child2);
if (at(child1).shouldSpeculateArguments()) {
+ dataLog(" in here ");
JSValueOperand value(this, child3);
- SpeculateCellOperand base(this, child1);
- SpeculateStrictInt32Operand property(this, child2);
GPRTemporary scratch(this);
GPRTemporary scratch2(this);
@@ -2656,8 +2641,6 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- ASSERT(at(child1).shouldSpeculateArray());
-
JSValueOperand value(this, child3);
GPRTemporary scratch(this);
@@ -2672,11 +2655,8 @@ void SpeculativeJIT::compile(Node& node)
writeBarrier(baseReg, value.gpr(), child3, WriteBarrierForPropertyAccess, scratchReg);
- // Check that base is an array, and that property is contained within m_vector (< m_vectorLength).
- // If we have predicted the base to be type array, we can skip the check.
- if (!isArraySpeculation(m_state.forNode(child1).m_type))
- speculationCheck(BadType, JSValueRegs(baseReg), child1, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
-
+ speculateArray(child1, baseReg);
+
MacroAssembler::Jump beyondArrayBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, JSArray::vectorLengthOffset()));
if (node.op() == PutByVal)
speculationCheck(OutOfBounds, JSValueRegs(), NoNode, beyondArrayBounds);
@@ -2879,9 +2859,8 @@ void SpeculativeJIT::compile(Node& node)
writeBarrier(baseGPR, valueGPR, node.child2(), WriteBarrierForPropertyAccess, storageGPR, storageLengthGPR);
- if (!isArraySpeculation(m_state.forNode(node.child1()).m_type))
- speculationCheck(BadType, JSValueRegs(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
-
+ speculateArray(node.child1(), baseGPR);
+
m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), storageGPR);
m_jit.load32(MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_length)), storageLengthGPR);
@@ -2917,9 +2896,8 @@ void SpeculativeJIT::compile(Node& node)
GPRReg storageGPR = storage.gpr();
GPRReg storageLengthGPR = storageLength.gpr();
- if (!isArraySpeculation(m_state.forNode(node.child1()).m_type))
- speculationCheck(BadType, JSValueRegs(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
-
+ speculateArray(node.child1(), baseGPR);
+
m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), storageGPR);
m_jit.load32(MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_length)), storageLengthGPR);
@@ -3415,9 +3393,8 @@ void SpeculativeJIT::compile(Node& node)
GPRReg baseGPR = base.gpr();
GPRReg resultGPR = result.gpr();
- if (!isArraySpeculation(m_state.forNode(node.child1()).m_type))
- speculationCheck(BadType, JSValueRegs(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
-
+ speculateArray(node.child1(), baseGPR);
+
m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), resultGPR);
m_jit.load32(MacroAssembler::Address(resultGPR, OBJECT_OFFSETOF(ArrayStorage, m_length)), resultGPR);
@@ -3493,7 +3470,7 @@ void SpeculativeJIT::compile(Node& node)
case CheckStructure:
case ForwardCheckStructure: {
AbstractValue& value = m_state.forNode(node.child1());
- if (value.m_structure.isSubsetOf(node.structureSet())
+ if (value.m_currentKnownStructure.isSubsetOf(node.structureSet())
&& isCellSpeculation(value.m_type)) {
noResult(m_compileIndex);
break;
@@ -3534,9 +3511,12 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- case StructureTransitionWatchpoint: {
+ case StructureTransitionWatchpoint:
+ case ForwardStructureTransitionWatchpoint: {
m_jit.addWeakReference(node.structure());
- node.structure()->addTransitionWatchpoint(speculationWatchpoint(BadCache));
+ node.structure()->addTransitionWatchpoint(
+ speculationWatchpointWithConditionalDirection(
+ BadCache, node.op() == ForwardStructureTransitionWatchpoint));
#if !ASSERT_DISABLED
SpeculateCellOperand op1(this, node.child1());
diff --git a/Source/JavaScriptCore/dfg/DFGStructureAbstractValue.h b/Source/JavaScriptCore/dfg/DFGStructureAbstractValue.h
new file mode 100644
index 000000000..b3082de1a
--- /dev/null
+++ b/Source/JavaScriptCore/dfg/DFGStructureAbstractValue.h
@@ -0,0 +1,327 @@
+/*
+ * Copyright (C) 2011, 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 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 DFGStructureAbstractValue_h
+#define DFGStructureAbstractValue_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(DFG_JIT)
+
+#include "JSCell.h"
+#include "SpeculatedType.h"
+#include "StructureSet.h"
+
+namespace JSC { namespace DFG {
+
+class StructureAbstractValue {
+public:
+ StructureAbstractValue()
+ : m_structure(0)
+ {
+ }
+
+ StructureAbstractValue(Structure* structure)
+ : m_structure(structure)
+ {
+ }
+
+ StructureAbstractValue(const StructureSet& set)
+ {
+ switch (set.size()) {
+ case 0:
+ m_structure = 0;
+ break;
+
+ case 1:
+ m_structure = set[0];
+ break;
+
+ default:
+ m_structure = topValue();
+ break;
+ }
+ }
+
+ void clear()
+ {
+ m_structure = 0;
+ }
+
+ void makeTop()
+ {
+ m_structure = topValue();
+ }
+
+ static StructureAbstractValue top()
+ {
+ StructureAbstractValue value;
+ value.makeTop();
+ return value;
+ }
+
+ void add(Structure* structure)
+ {
+ ASSERT(!contains(structure) && !isTop());
+ if (m_structure)
+ makeTop();
+ else
+ m_structure = structure;
+ }
+
+ bool addAll(const StructureSet& other)
+ {
+ if (isTop() || !other.size())
+ return false;
+ if (other.size() > 1) {
+ makeTop();
+ return true;
+ }
+ if (!m_structure) {
+ m_structure = other[0];
+ return true;
+ }
+ if (m_structure == other[0])
+ return false;
+ makeTop();
+ return true;
+ }
+
+ bool addAll(const StructureAbstractValue& other)
+ {
+ if (!other.m_structure)
+ return false;
+ if (isTop())
+ return false;
+ if (other.isTop()) {
+ makeTop();
+ return true;
+ }
+ if (m_structure) {
+ if (m_structure == other.m_structure)
+ return false;
+ makeTop();
+ return true;
+ }
+ m_structure = other.m_structure;
+ return true;
+ }
+
+ bool contains(Structure* structure) const
+ {
+ if (isTop())
+ return true;
+ if (m_structure == structure)
+ return true;
+ return false;
+ }
+
+ bool isSubsetOf(const StructureSet& other) const
+ {
+ if (isTop())
+ return false;
+ if (!m_structure)
+ return true;
+ return other.contains(m_structure);
+ }
+
+ bool doesNotContainAnyOtherThan(Structure* structure) const
+ {
+ if (isTop())
+ return false;
+ if (!m_structure)
+ return true;
+ return m_structure == structure;
+ }
+
+ bool isSupersetOf(const StructureSet& other) const
+ {
+ if (isTop())
+ return true;
+ if (!other.size())
+ return true;
+ if (other.size() > 1)
+ return false;
+ return m_structure == other[0];
+ }
+
+ bool isSubsetOf(const StructureAbstractValue& other) const
+ {
+ if (other.isTop())
+ return true;
+ if (isTop())
+ return false;
+ if (m_structure) {
+ if (other.m_structure)
+ return m_structure == other.m_structure;
+ return false;
+ }
+ return true;
+ }
+
+ bool isSupersetOf(const StructureAbstractValue& other) const
+ {
+ return other.isSubsetOf(*this);
+ }
+
+ void filter(const StructureSet& other)
+ {
+ if (!m_structure)
+ return;
+
+ if (isTop()) {
+ switch (other.size()) {
+ case 0:
+ m_structure = 0;
+ return;
+
+ case 1:
+ m_structure = other[0];
+ return;
+
+ default:
+ return;
+ }
+ }
+
+ if (other.contains(m_structure))
+ return;
+
+ m_structure = 0;
+ }
+
+ void filter(const StructureAbstractValue& other)
+ {
+ if (isTop()) {
+ m_structure = other.m_structure;
+ return;
+ }
+ if (m_structure == other.m_structure)
+ return;
+ if (other.isTop())
+ return;
+ m_structure = 0;
+ }
+
+ void filter(SpeculatedType other)
+ {
+ if (!(other & SpecCell)) {
+ clear();
+ return;
+ }
+
+ if (isClearOrTop())
+ return;
+
+ if (!(speculationFromStructure(m_structure) & other))
+ m_structure = 0;
+ }
+
+ bool isClear() const
+ {
+ return !m_structure;
+ }
+
+ bool isTop() const { return m_structure == topValue(); }
+
+ bool isClearOrTop() const { return m_structure <= topValue(); }
+ bool isNeitherClearNorTop() const { return !isClearOrTop(); }
+
+ size_t size() const
+ {
+ ASSERT(!isTop());
+ return !!m_structure;
+ }
+
+ Structure* at(size_t i) const
+ {
+ ASSERT(!isTop());
+ ASSERT(m_structure);
+ ASSERT_UNUSED(i, !i);
+ return m_structure;
+ }
+
+ Structure* operator[](size_t i) const
+ {
+ return at(i);
+ }
+
+ Structure* last() const
+ {
+ return at(0);
+ }
+
+ SpeculatedType speculationFromStructures() const
+ {
+ if (isTop())
+ return SpecCell;
+ if (isClear())
+ return SpecNone;
+ return speculationFromStructure(m_structure);
+ }
+
+ bool hasSingleton() const
+ {
+ return isNeitherClearNorTop();
+ }
+
+ Structure* singleton() const
+ {
+ ASSERT(isNeitherClearNorTop());
+ return m_structure;
+ }
+
+ bool operator==(const StructureAbstractValue& other) const
+ {
+ return m_structure == other.m_structure;
+ }
+
+ void dump(FILE* out) const
+ {
+ if (isTop()) {
+ fprintf(out, "TOP");
+ return;
+ }
+
+ fprintf(out, "[");
+ if (m_structure)
+ fprintf(out, "%p", m_structure);
+ fprintf(out, "]");
+ }
+
+private:
+ static Structure* topValue() { return reinterpret_cast<Structure*>(1); }
+
+ // This can only remember one structure at a time.
+ Structure* m_structure;
+};
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
+#endif // DFGStructureAbstractValue_h
+
+
diff --git a/Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.cpp b/Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.cpp
index e86c57dff..68627f95c 100644
--- a/Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.cpp
@@ -82,6 +82,7 @@ public:
}
case ForwardCheckStructure:
+ case ForwardStructureTransitionWatchpoint:
// We currently rely on the fact that we're the only ones who would
// insert this node.
ASSERT_NOT_REACHED();
@@ -94,6 +95,12 @@ public:
case AllocatePropertyStorage:
case ReallocatePropertyStorage:
case GetPropertyStorage:
+ case GetByVal:
+ case PutByVal:
+ case PutByValAlias:
+ case PutByValSafe:
+ case GetArrayLength:
+ case Phantom:
// Don't count these uses.
break;
@@ -215,17 +222,22 @@ public:
break;
case PutByVal:
- case PutByValAlias: {
+ case PutByValAlias:
+ case PutByValSafe: {
Edge child1 = m_graph.varArgChild(node, 0);
Edge child2 = m_graph.varArgChild(node, 1);
if (!m_graph[child1].prediction() || !m_graph[child2].prediction())
break;
- if (!m_graph[child2].shouldSpeculateInteger() || !isActionableMutableArraySpeculation(m_graph[child1].prediction())) {
+ if (!m_graph[child2].shouldSpeculateInteger()
+#if USE(JSVALUE32_64)
+ || m_graph[child1].shouldSpeculateArguments()
+#endif
+ ) {
clobber(live);
break;
}
- if (node.op() == PutByValAlias)
+ if (node.op() != PutByValSafe)
break;
if (m_graph[child1].shouldSpeculateArguments())
break;
@@ -291,7 +303,7 @@ public:
dataLog("Hoisting checks for %s\n", m_graph.nameOfVariableAccessData(it->first));
}
#endif // DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
-
+
// Make changes:
// 1) If a variable's live range does not span a clobber, then inject structure
// checks before the SetLocal.
@@ -348,6 +360,8 @@ public:
if (block->variablesAtTail.operand(variable->local()) == nodeIndex)
block->variablesAtTail.operand(variable->local()) = getLocalIndex;
+ m_graph.substituteGetLocal(*block, indexInBlock, variable, getLocalIndex);
+
changed = true;
break;
}
diff --git a/Source/JavaScriptCore/interpreter/Interpreter.cpp b/Source/JavaScriptCore/interpreter/Interpreter.cpp
index 51f22bedd..a9118f43b 100644
--- a/Source/JavaScriptCore/interpreter/Interpreter.cpp
+++ b/Source/JavaScriptCore/interpreter/Interpreter.cpp
@@ -712,7 +712,7 @@ bool Interpreter::isOpcode(Opcode opcode)
#if ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER) || ENABLE(LLINT)
#if !ENABLE(LLINT)
if (!m_classicEnabled)
- return opcode >= 0 && static_cast<OpcodeID>(bitwise_cast<uintptr_t>(opcode)) <= op_end;
+ return static_cast<OpcodeID>(bitwise_cast<uintptr_t>(opcode)) <= op_end;
#endif
return opcode != HashTraits<Opcode>::emptyValue()
&& !HashTraits<Opcode>::isDeletedValue(opcode)
diff --git a/Source/JavaScriptCore/jit/JITDriver.h b/Source/JavaScriptCore/jit/JITDriver.h
index 6c50f4bd1..7b5cc28eb 100644
--- a/Source/JavaScriptCore/jit/JITDriver.h
+++ b/Source/JavaScriptCore/jit/JITDriver.h
@@ -38,7 +38,7 @@
namespace JSC {
template<typename CodeBlockType>
-inline bool jitCompileIfAppropriate(ExecState* exec, OwnPtr<CodeBlockType>& codeBlock, JITCode& jitCode, JITCode::JITType jitType, JITCompilationEffort effort)
+inline bool jitCompileIfAppropriate(ExecState* exec, OwnPtr<CodeBlockType>& codeBlock, JITCode& jitCode, JITCode::JITType jitType, unsigned bytecodeIndex, JITCompilationEffort effort)
{
JSGlobalData& globalData = exec->globalData();
@@ -54,7 +54,7 @@ inline bool jitCompileIfAppropriate(ExecState* exec, OwnPtr<CodeBlockType>& code
bool dfgCompiled = false;
if (jitType == JITCode::DFGJIT)
- dfgCompiled = DFG::tryCompile(exec, codeBlock.get(), jitCode);
+ dfgCompiled = DFG::tryCompile(exec, codeBlock.get(), jitCode, bytecodeIndex);
if (dfgCompiled) {
if (codeBlock->alternative())
codeBlock->alternative()->unlinkIncomingCalls();
@@ -75,7 +75,7 @@ inline bool jitCompileIfAppropriate(ExecState* exec, OwnPtr<CodeBlockType>& code
return true;
}
-inline bool jitCompileFunctionIfAppropriate(ExecState* exec, OwnPtr<FunctionCodeBlock>& codeBlock, JITCode& jitCode, MacroAssemblerCodePtr& jitCodeWithArityCheck, SharedSymbolTable*& symbolTable, JITCode::JITType jitType, JITCompilationEffort effort)
+inline bool jitCompileFunctionIfAppropriate(ExecState* exec, OwnPtr<FunctionCodeBlock>& codeBlock, JITCode& jitCode, MacroAssemblerCodePtr& jitCodeWithArityCheck, SharedSymbolTable*& symbolTable, JITCode::JITType jitType, unsigned bytecodeIndex, JITCompilationEffort effort)
{
JSGlobalData& globalData = exec->globalData();
@@ -92,7 +92,7 @@ inline bool jitCompileFunctionIfAppropriate(ExecState* exec, OwnPtr<FunctionCode
bool dfgCompiled = false;
if (jitType == JITCode::DFGJIT)
- dfgCompiled = DFG::tryCompileFunction(exec, codeBlock.get(), jitCode, jitCodeWithArityCheck);
+ dfgCompiled = DFG::tryCompileFunction(exec, codeBlock.get(), jitCode, jitCodeWithArityCheck, bytecodeIndex);
if (dfgCompiled) {
if (codeBlock->alternative())
codeBlock->alternative()->unlinkIncomingCalls();
diff --git a/Source/JavaScriptCore/jit/JITPropertyAccess.cpp b/Source/JavaScriptCore/jit/JITPropertyAccess.cpp
index dfb2dc8ec..16af9125b 100644
--- a/Source/JavaScriptCore/jit/JITPropertyAccess.cpp
+++ b/Source/JavaScriptCore/jit/JITPropertyAccess.cpp
@@ -110,7 +110,11 @@ void JIT::emit_op_get_by_val(Instruction* currentInstruction)
zeroExtend32ToPtr(regT1, regT1);
emitJumpSlowCaseIfNotJSCell(regT0, base);
- addSlowCase(branchPtr(NotEqual, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSArray::s_info)));
+ loadPtr(Address(regT0, JSCell::structureOffset()), regT2);
+#if ENABLE(VALUE_PROFILER)
+ storePtr(regT2, currentInstruction[4].u.arrayProfile->addressOfLastSeenStructure());
+#endif
+ addSlowCase(branchPtr(NotEqual, Address(regT2, Structure::classInfoOffset()), TrustedImmPtr(&JSArray::s_info)));
loadPtr(Address(regT0, JSArray::storageOffset()), regT2);
addSlowCase(branch32(AboveOrEqual, regT1, Address(regT0, JSArray::vectorLengthOffset())));
@@ -231,7 +235,11 @@ void JIT::emit_op_put_by_val(Instruction* currentInstruction)
// See comment in op_get_by_val.
zeroExtend32ToPtr(regT1, regT1);
emitJumpSlowCaseIfNotJSCell(regT0, base);
- addSlowCase(branchPtr(NotEqual, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSArray::s_info)));
+ loadPtr(Address(regT0, JSCell::structureOffset()), regT2);
+#if ENABLE(VALUE_PROFILER)
+ storePtr(regT2, currentInstruction[4].u.arrayProfile->addressOfLastSeenStructure());
+#endif
+ addSlowCase(branchPtr(NotEqual, Address(regT2, Structure::classInfoOffset()), TrustedImmPtr(&JSArray::s_info)));
addSlowCase(branch32(AboveOrEqual, regT1, Address(regT0, JSArray::vectorLengthOffset())));
loadPtr(Address(regT0, JSArray::storageOffset()), regT2);
@@ -645,7 +653,11 @@ void JIT::privateCompilePatchGetArrayLength(ReturnAddressPtr returnAddress)
StructureStubInfo* stubInfo = &m_codeBlock->getStubInfo(returnAddress);
// Check eax is an array
- Jump failureCases1 = branchPtr(NotEqual, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSArray::s_info));
+ loadPtr(Address(regT0, JSCell::structureOffset()), regT3);
+#if ENABLE(VALUE_PROFILER)
+ storePtr(regT3, m_codeBlock->getOrAddArrayProfile(stubInfo->bytecodeIndex)->addressOfLastSeenStructure());
+#endif
+ Jump failureCases1 = branchPtr(NotEqual, Address(regT3, Structure::classInfoOffset()), TrustedImmPtr(&JSArray::s_info));
// Checks out okay! - get the length from the storage
loadPtr(Address(regT0, JSArray::storageOffset()), regT3);
diff --git a/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp b/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp
index b506f4ecb..6ef25046f 100644
--- a/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp
+++ b/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp
@@ -209,7 +209,11 @@ void JIT::emit_op_get_by_val(Instruction* currentInstruction)
addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
emitJumpSlowCaseIfNotJSCell(base, regT1);
- addSlowCase(branchPtr(NotEqual, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSArray::s_info)));
+ loadPtr(Address(regT0, JSCell::structureOffset()), regT1);
+#if ENABLE(VALUE_PROFILER)
+ storePtr(regT1, currentInstruction[4].u.arrayProfile->addressOfLastSeenStructure());
+#endif
+ addSlowCase(branchPtr(NotEqual, Address(regT1, JSCell::classInfoOffset()), TrustedImmPtr(&JSArray::s_info)));
loadPtr(Address(regT0, JSArray::storageOffset()), regT3);
addSlowCase(branch32(AboveOrEqual, regT2, Address(regT0, JSArray::vectorLengthOffset())));
@@ -264,7 +268,11 @@ void JIT::emit_op_put_by_val(Instruction* currentInstruction)
addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
emitJumpSlowCaseIfNotJSCell(base, regT1);
- addSlowCase(branchPtr(NotEqual, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSArray::s_info)));
+ loadPtr(Address(regT0, JSCell::structureOffset()), regT1);
+#if ENABLE(VALUE_PROFILER)
+ storePtr(regT1, currentInstruction[4].u.arrayProfile->addressOfLastSeenStructure());
+#endif
+ addSlowCase(branchPtr(NotEqual, Address(regT1, Structure::classInfoOffset()), TrustedImmPtr(&JSArray::s_info)));
addSlowCase(branch32(AboveOrEqual, regT2, Address(regT0, JSArray::vectorLengthOffset())));
emitWriteBarrier(regT0, regT1, regT1, regT3, UnconditionalWriteBarrier, WriteBarrierForPropertyAccess);
@@ -608,7 +616,11 @@ void JIT::privateCompilePatchGetArrayLength(ReturnAddressPtr returnAddress)
// regT0 holds a JSCell*
// Check for array
- Jump failureCases1 = branchPtr(NotEqual, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSArray::s_info));
+ loadPtr(Address(regT0, JSCell::structureOffset()), regT2);
+#if ENABLE(VALUE_PROFILER)
+ storePtr(regT2, m_codeBlock->getOrAddArrayProfile(stubInfo->bytecodeIndex)->addressOfLastSeenStructure());
+#endif
+ Jump failureCases1 = branchPtr(NotEqual, Address(regT2, Structure::classInfoOffset()), TrustedImmPtr(&JSArray::s_info));
// Checks out okay! - get the length from the storage
loadPtr(Address(regT0, JSArray::storageOffset()), regT2);
diff --git a/Source/JavaScriptCore/jit/JITStubs.cpp b/Source/JavaScriptCore/jit/JITStubs.cpp
index 8b8546994..cb5adc2fa 100644
--- a/Source/JavaScriptCore/jit/JITStubs.cpp
+++ b/Source/JavaScriptCore/jit/JITStubs.cpp
@@ -2022,8 +2022,7 @@ DEFINE_STUB_FUNCTION(void, optimize)
}
ScopeChainNode* scopeChain = callFrame->scopeChain();
-
- JSObject* error = codeBlock->compileOptimized(callFrame, scopeChain);
+ JSObject* error = codeBlock->compileOptimized(callFrame, scopeChain, bytecodeIndex);
#if ENABLE(JIT_VERBOSE_OSR)
if (error)
dataLog("WARNING: optimized compilation failed.\n");
diff --git a/Source/JavaScriptCore/llint/LLIntExceptions.cpp b/Source/JavaScriptCore/llint/LLIntExceptions.cpp
index 20b0db3d9..a915c42e3 100644
--- a/Source/JavaScriptCore/llint/LLIntExceptions.cpp
+++ b/Source/JavaScriptCore/llint/LLIntExceptions.cpp
@@ -37,6 +37,14 @@
namespace JSC { namespace LLInt {
+static void fixupPCforExceptionIfNeeded(ExecState* exec)
+{
+ CodeBlock* codeBlock = exec->codeBlock();
+ ASSERT(!!codeBlock);
+ Instruction* pc = exec->currentVPC();
+ exec->setCurrentVPC(codeBlock->adjustPCIfAtCallSite(pc));
+}
+
void interpreterThrowInCaller(ExecState* exec, ReturnAddressPtr pc)
{
JSGlobalData* globalData = &exec->globalData();
@@ -44,6 +52,7 @@ void interpreterThrowInCaller(ExecState* exec, ReturnAddressPtr pc)
#if LLINT_SLOW_PATH_TRACING
dataLog("Throwing exception %s.\n", globalData->exception.description());
#endif
+ fixupPCforExceptionIfNeeded(exec);
genericThrow(
globalData, exec, globalData->exception,
exec->codeBlock()->bytecodeOffset(exec, pc));
@@ -61,6 +70,7 @@ Instruction* returnToThrow(ExecState* exec, Instruction* pc)
#if LLINT_SLOW_PATH_TRACING
dataLog("Throwing exception %s (returnToThrow).\n", globalData->exception.description());
#endif
+ fixupPCforExceptionIfNeeded(exec);
genericThrow(globalData, exec, globalData->exception, pc - exec->codeBlock()->instructions().begin());
return globalData->llintData.exceptionInstructions();
@@ -73,6 +83,7 @@ void* callToThrow(ExecState* exec, Instruction* pc)
#if LLINT_SLOW_PATH_TRACING
dataLog("Throwing exception %s (callToThrow).\n", globalData->exception.description());
#endif
+ fixupPCforExceptionIfNeeded(exec);
genericThrow(globalData, exec, globalData->exception, pc - exec->codeBlock()->instructions().begin());
return bitwise_cast<void*>(&llint_throw_during_call_trampoline);
diff --git a/Source/JavaScriptCore/llint/LLIntOffsetsExtractor.cpp b/Source/JavaScriptCore/llint/LLIntOffsetsExtractor.cpp
index f863cb218..cbb4258d0 100644
--- a/Source/JavaScriptCore/llint/LLIntOffsetsExtractor.cpp
+++ b/Source/JavaScriptCore/llint/LLIntOffsetsExtractor.cpp
@@ -25,6 +25,7 @@
#include "config.h"
+#include "ArrayProfile.h"
#include "CodeBlock.h"
#include "Executable.h"
#include "Heap.h"
diff --git a/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm b/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm
index b8115dd6b..5f280ce1b 100644
--- a/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm
+++ b/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm
@@ -1255,14 +1255,19 @@ _llint_op_put_by_id_transition_normal_out_of_line:
_llint_op_get_by_val:
traceExecution()
- loadp CodeBlock[cfr], t1
loadi 8[PC], t2
loadi 12[PC], t3
- loadp CodeBlock::m_globalData[t1], t1
loadConstantOrVariablePayload(t2, CellTag, t0, .opGetByValSlow)
- loadp JSGlobalData::jsArrayClassInfo[t1], t2
loadConstantOrVariablePayload(t3, Int32Tag, t1, .opGetByValSlow)
- bpneq [t0], t2, .opGetByValSlow
+ loadp JSCell::m_structure[t0], t3
+ loadp 16[PC], t2
+ if VALUE_PROFILER
+ storep t3, ArrayProfile::m_lastSeenStructure[t2]
+ end
+ loadp CodeBlock[cfr], t2
+ loadp CodeBlock::m_globalData[t2], t2
+ loadp JSGlobalData::jsArrayClassInfo[t2], t2
+ bpneq Structure::m_classInfo[t3], t2, .opGetByValSlow
loadp JSArray::m_storage[t0], t3
biaeq t1, JSArray::m_vectorLength[t0], .opGetByValSlow
loadi 4[PC], t0
@@ -1271,16 +1276,18 @@ _llint_op_get_by_val:
bieq t2, EmptyValueTag, .opGetByValSlow
storei t2, TagOffset[cfr, t0, 8]
storei t1, PayloadOffset[cfr, t0, 8]
- loadi 16[PC], t0
+ loadi 20[PC], t0
valueProfile(t2, t1, t0)
- dispatch(5)
+ dispatch(6)
.opGetByValSlow:
callSlowPath(_llint_slow_path_get_by_val)
- dispatch(5)
+ dispatch(6)
_llint_op_get_argument_by_val:
+ # FIXME: At some point we should array profile this. Right now it isn't necessary
+ # since the DFG will never turn a get_argument_by_val into a GetByVal.
traceExecution()
loadi 8[PC], t0
loadi 12[PC], t1
@@ -1293,15 +1300,15 @@ _llint_op_get_argument_by_val:
loadi 4[PC], t3
loadi ThisArgumentOffset + TagOffset[cfr, t2, 8], t0
loadi ThisArgumentOffset + PayloadOffset[cfr, t2, 8], t1
- loadi 16[PC], t2
+ loadi 20[PC], t2
storei t0, TagOffset[cfr, t3, 8]
storei t1, PayloadOffset[cfr, t3, 8]
valueProfile(t0, t1, t2)
- dispatch(5)
+ dispatch(6)
.opGetArgumentByValSlow:
callSlowPath(_llint_slow_path_get_argument_by_val)
- dispatch(5)
+ dispatch(6)
_llint_op_get_by_pname:
@@ -1338,10 +1345,15 @@ _llint_op_put_by_val:
loadConstantOrVariablePayload(t0, CellTag, t1, .opPutByValSlow)
loadi 8[PC], t0
loadConstantOrVariablePayload(t0, Int32Tag, t2, .opPutByValSlow)
+ loadp JSCell::m_structure[t1], t3
+ loadp 16[PC], t0
+ if VALUE_PROFILER
+ storep t3, ArrayProfile::m_lastSeenStructure[t0]
+ end
loadp CodeBlock[cfr], t0
loadp CodeBlock::m_globalData[t0], t0
loadp JSGlobalData::jsArrayClassInfo[t0], t0
- bpneq [t1], t0, .opPutByValSlow
+ bpneq Structure::m_classInfo[t3], t0, .opPutByValSlow
biaeq t2, JSArray::m_vectorLength[t1], .opPutByValSlow
loadp JSArray::m_storage[t1], t0
bieq ArrayStorage::m_vector + TagOffset[t0, t2, 8], EmptyValueTag, .opPutByValEmpty
@@ -1351,7 +1363,7 @@ _llint_op_put_by_val:
writeBarrier(t1, t3)
storei t1, ArrayStorage::m_vector + TagOffset[t0, t2, 8]
storei t3, ArrayStorage::m_vector + PayloadOffset[t0, t2, 8]
- dispatch(4)
+ dispatch(5)
.opPutByValEmpty:
addi 1, ArrayStorage::m_numValuesInVector[t0]
@@ -1362,7 +1374,7 @@ _llint_op_put_by_val:
.opPutByValSlow:
callSlowPath(_llint_slow_path_put_by_val)
- dispatch(4)
+ dispatch(5)
_llint_op_loop:
diff --git a/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm b/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm
index 6e752a6d0..f1a7e2998 100644
--- a/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm
+++ b/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm
@@ -1099,31 +1099,38 @@ _llint_op_put_by_id_transition_normal_out_of_line:
_llint_op_get_by_val:
traceExecution()
- loadp CodeBlock[cfr], t1
loadis 16[PB, PC, 8], t2
loadis 24[PB, PC, 8], t3
- loadp CodeBlock::m_globalData[t1], t1
loadConstantOrVariableCell(t2, t0, .opGetByValSlow)
- loadp JSGlobalData::jsArrayClassInfo[t1], t2
loadConstantOrVariableInt32(t3, t1, .opGetByValSlow)
sxi2p t1, t1
- bpneq [t0], t2, .opGetByValSlow
+ loadp JSCell::m_structure[t0], t3
+ loadp 32[PB, PC, 8], t2
+ if VALUE_PROFILER
+ storep t3, ArrayProfile::m_lastSeenStructure[t2]
+ end
+ loadp CodeBlock[cfr], t2
+ loadp CodeBlock::m_globalData[t2], t2
+ loadp JSGlobalData::jsArrayClassInfo[t2], t2
+ bpneq Structure::m_classInfo[t3], t2, .opGetByValSlow
loadp JSArray::m_storage[t0], t3
biaeq t1, JSArray::m_vectorLength[t0], .opGetByValSlow
loadis 8[PB, PC, 8], t0
loadp ArrayStorage::m_vector[t3, t1, 8], t2
btpz t2, .opGetByValSlow
storep t2, [cfr, t0, 8]
- loadp 32[PB, PC, 8], t0
+ loadp 40[PB, PC, 8], t0
valueProfile(t2, t0)
- dispatch(5)
+ dispatch(6)
.opGetByValSlow:
callSlowPath(_llint_slow_path_get_by_val)
- dispatch(5)
+ dispatch(6)
_llint_op_get_argument_by_val:
+ # FIXME: At some point we should array profile this. Right now it isn't necessary
+ # since the DFG will never turn a get_argument_by_val into a GetByVal.
traceExecution()
loadis 16[PB, PC, 8], t0
loadis 24[PB, PC, 8], t1
@@ -1139,11 +1146,11 @@ _llint_op_get_argument_by_val:
loadp ThisArgumentOffset[cfr, t2, 8], t0
storep t0, [cfr, t3, 8]
valueProfile(t0, t1)
- dispatch(5)
+ dispatch(6)
.opGetArgumentByValSlow:
callSlowPath(_llint_slow_path_get_argument_by_val)
- dispatch(5)
+ dispatch(6)
_llint_op_get_by_pname:
@@ -1182,10 +1189,15 @@ _llint_op_put_by_val:
loadis 16[PB, PC, 8], t0
loadConstantOrVariableInt32(t0, t2, .opPutByValSlow)
sxi2p t2, t2
+ loadp JSCell::m_structure[t1], t3
+ loadp 32[PB, PC, 8], t0
+ if VALUE_PROFILER
+ storep t3, ArrayProfile::m_lastSeenStructure[t0]
+ end
loadp CodeBlock[cfr], t0
loadp CodeBlock::m_globalData[t0], t0
loadp JSGlobalData::jsArrayClassInfo[t0], t0
- bpneq [t1], t0, .opPutByValSlow
+ bpneq Structure::m_classInfo[t3], t0, .opPutByValSlow
biaeq t2, JSArray::m_vectorLength[t1], .opPutByValSlow
loadp JSArray::m_storage[t1], t0
btpz ArrayStorage::m_vector[t0, t2, 8], .opPutByValEmpty
@@ -1194,7 +1206,7 @@ _llint_op_put_by_val:
loadConstantOrVariable(t3, t1)
writeBarrier(t1)
storep t1, ArrayStorage::m_vector[t0, t2, 8]
- dispatch(4)
+ dispatch(5)
.opPutByValEmpty:
addi 1, ArrayStorage::m_numValuesInVector[t0]
@@ -1205,7 +1217,7 @@ _llint_op_put_by_val:
.opPutByValSlow:
callSlowPath(_llint_slow_path_put_by_val)
- dispatch(4)
+ dispatch(5)
_llint_op_loop:
diff --git a/Source/JavaScriptCore/runtime/Executable.cpp b/Source/JavaScriptCore/runtime/Executable.cpp
index 73b4b6c4f..50bb5ffae 100644
--- a/Source/JavaScriptCore/runtime/Executable.cpp
+++ b/Source/JavaScriptCore/runtime/Executable.cpp
@@ -160,13 +160,13 @@ void FunctionExecutable::destroy(JSCell* cell)
static_cast<FunctionExecutable*>(cell)->FunctionExecutable::~FunctionExecutable();
}
-JSObject* EvalExecutable::compileOptimized(ExecState* exec, ScopeChainNode* scopeChainNode)
+JSObject* EvalExecutable::compileOptimized(ExecState* exec, ScopeChainNode* scopeChainNode, unsigned bytecodeIndex)
{
ASSERT(exec->globalData().dynamicGlobalObject);
ASSERT(!!m_evalCodeBlock);
JSObject* error = 0;
if (m_evalCodeBlock->getJITType() != JITCode::topTierJIT())
- error = compileInternal(exec, scopeChainNode, JITCode::nextTierJIT(m_evalCodeBlock->getJITType()));
+ error = compileInternal(exec, scopeChainNode, JITCode::nextTierJIT(m_evalCodeBlock->getJITType()), bytecodeIndex);
ASSERT(!!m_evalCodeBlock);
return error;
}
@@ -174,7 +174,7 @@ JSObject* EvalExecutable::compileOptimized(ExecState* exec, ScopeChainNode* scop
#if ENABLE(JIT)
bool EvalExecutable::jitCompile(ExecState* exec)
{
- return jitCompileIfAppropriate(exec, m_evalCodeBlock, m_jitCodeForCall, JITCode::bottomTierJIT(), JITCompilationCanFail);
+ return jitCompileIfAppropriate(exec, m_evalCodeBlock, m_jitCodeForCall, JITCode::bottomTierJIT(), UINT_MAX, JITCompilationCanFail);
}
#endif
@@ -193,12 +193,13 @@ inline const char* samplingDescription(JITCode::JITType jitType)
}
}
-JSObject* EvalExecutable::compileInternal(ExecState* exec, ScopeChainNode* scopeChainNode, JITCode::JITType jitType)
+JSObject* EvalExecutable::compileInternal(ExecState* exec, ScopeChainNode* scopeChainNode, JITCode::JITType jitType, unsigned bytecodeIndex)
{
SamplingRegion samplingRegion(samplingDescription(jitType));
#if !ENABLE(JIT)
UNUSED_PARAM(jitType);
+ UNUSED_PARAM(bytecodeIndex);
#endif
JSObject* exception = 0;
JSGlobalData* globalData = &exec->globalData();
@@ -235,7 +236,7 @@ JSObject* EvalExecutable::compileInternal(ExecState* exec, ScopeChainNode* scope
}
#if ENABLE(JIT)
- if (!prepareForExecution(exec, m_evalCodeBlock, m_jitCodeForCall, jitType))
+ if (!prepareForExecution(exec, m_evalCodeBlock, m_jitCodeForCall, jitType, bytecodeIndex))
return 0;
#endif
@@ -301,13 +302,13 @@ JSObject* ProgramExecutable::checkSyntax(ExecState* exec)
return exception;
}
-JSObject* ProgramExecutable::compileOptimized(ExecState* exec, ScopeChainNode* scopeChainNode)
+JSObject* ProgramExecutable::compileOptimized(ExecState* exec, ScopeChainNode* scopeChainNode, unsigned bytecodeIndex)
{
ASSERT(exec->globalData().dynamicGlobalObject);
ASSERT(!!m_programCodeBlock);
JSObject* error = 0;
if (m_programCodeBlock->getJITType() != JITCode::topTierJIT())
- error = compileInternal(exec, scopeChainNode, JITCode::nextTierJIT(m_programCodeBlock->getJITType()));
+ error = compileInternal(exec, scopeChainNode, JITCode::nextTierJIT(m_programCodeBlock->getJITType()), bytecodeIndex);
ASSERT(!!m_programCodeBlock);
return error;
}
@@ -315,16 +316,17 @@ JSObject* ProgramExecutable::compileOptimized(ExecState* exec, ScopeChainNode* s
#if ENABLE(JIT)
bool ProgramExecutable::jitCompile(ExecState* exec)
{
- return jitCompileIfAppropriate(exec, m_programCodeBlock, m_jitCodeForCall, JITCode::bottomTierJIT(), JITCompilationCanFail);
+ return jitCompileIfAppropriate(exec, m_programCodeBlock, m_jitCodeForCall, JITCode::bottomTierJIT(), UINT_MAX, JITCompilationCanFail);
}
#endif
-JSObject* ProgramExecutable::compileInternal(ExecState* exec, ScopeChainNode* scopeChainNode, JITCode::JITType jitType)
+JSObject* ProgramExecutable::compileInternal(ExecState* exec, ScopeChainNode* scopeChainNode, JITCode::JITType jitType, unsigned bytecodeIndex)
{
SamplingRegion samplingRegion(samplingDescription(jitType));
#if !ENABLE(JIT)
UNUSED_PARAM(jitType);
+ UNUSED_PARAM(bytecodeIndex);
#endif
JSObject* exception = 0;
JSGlobalData* globalData = &exec->globalData();
@@ -359,7 +361,7 @@ JSObject* ProgramExecutable::compileInternal(ExecState* exec, ScopeChainNode* sc
}
#if ENABLE(JIT)
- if (!prepareForExecution(exec, m_programCodeBlock, m_jitCodeForCall, jitType))
+ if (!prepareForExecution(exec, m_programCodeBlock, m_jitCodeForCall, jitType, bytecodeIndex))
return 0;
#endif
@@ -431,24 +433,24 @@ FunctionCodeBlock* FunctionExecutable::baselineCodeBlockFor(CodeSpecializationKi
return result;
}
-JSObject* FunctionExecutable::compileOptimizedForCall(ExecState* exec, ScopeChainNode* scopeChainNode)
+JSObject* FunctionExecutable::compileOptimizedForCall(ExecState* exec, ScopeChainNode* scopeChainNode, unsigned bytecodeIndex)
{
ASSERT(exec->globalData().dynamicGlobalObject);
ASSERT(!!m_codeBlockForCall);
JSObject* error = 0;
if (m_codeBlockForCall->getJITType() != JITCode::topTierJIT())
- error = compileForCallInternal(exec, scopeChainNode, JITCode::nextTierJIT(m_codeBlockForCall->getJITType()));
+ error = compileForCallInternal(exec, scopeChainNode, JITCode::nextTierJIT(m_codeBlockForCall->getJITType()), bytecodeIndex);
ASSERT(!!m_codeBlockForCall);
return error;
}
-JSObject* FunctionExecutable::compileOptimizedForConstruct(ExecState* exec, ScopeChainNode* scopeChainNode)
+JSObject* FunctionExecutable::compileOptimizedForConstruct(ExecState* exec, ScopeChainNode* scopeChainNode, unsigned bytecodeIndex)
{
ASSERT(exec->globalData().dynamicGlobalObject);
ASSERT(!!m_codeBlockForConstruct);
JSObject* error = 0;
if (m_codeBlockForConstruct->getJITType() != JITCode::topTierJIT())
- error = compileForConstructInternal(exec, scopeChainNode, JITCode::nextTierJIT(m_codeBlockForConstruct->getJITType()));
+ error = compileForConstructInternal(exec, scopeChainNode, JITCode::nextTierJIT(m_codeBlockForConstruct->getJITType()), bytecodeIndex);
ASSERT(!!m_codeBlockForConstruct);
return error;
}
@@ -456,12 +458,12 @@ JSObject* FunctionExecutable::compileOptimizedForConstruct(ExecState* exec, Scop
#if ENABLE(JIT)
bool FunctionExecutable::jitCompileForCall(ExecState* exec)
{
- return jitCompileFunctionIfAppropriate(exec, m_codeBlockForCall, m_jitCodeForCall, m_jitCodeForCallWithArityCheck, m_symbolTable, JITCode::bottomTierJIT(), JITCompilationCanFail);
+ return jitCompileFunctionIfAppropriate(exec, m_codeBlockForCall, m_jitCodeForCall, m_jitCodeForCallWithArityCheck, m_symbolTable, JITCode::bottomTierJIT(), UINT_MAX, JITCompilationCanFail);
}
bool FunctionExecutable::jitCompileForConstruct(ExecState* exec)
{
- return jitCompileFunctionIfAppropriate(exec, m_codeBlockForConstruct, m_jitCodeForConstruct, m_jitCodeForConstructWithArityCheck, m_symbolTable, JITCode::bottomTierJIT(), JITCompilationCanFail);
+ return jitCompileFunctionIfAppropriate(exec, m_codeBlockForConstruct, m_jitCodeForConstruct, m_jitCodeForConstructWithArityCheck, m_symbolTable, JITCode::bottomTierJIT(), UINT_MAX, JITCompilationCanFail);
}
#endif
@@ -502,7 +504,7 @@ PassOwnPtr<FunctionCodeBlock> FunctionExecutable::produceCodeBlockFor(ScopeChain
return result.release();
}
-JSObject* FunctionExecutable::compileForCallInternal(ExecState* exec, ScopeChainNode* scopeChainNode, JITCode::JITType jitType)
+JSObject* FunctionExecutable::compileForCallInternal(ExecState* exec, ScopeChainNode* scopeChainNode, JITCode::JITType jitType, unsigned bytecodeIndex)
{
SamplingRegion samplingRegion(samplingDescription(jitType));
@@ -510,6 +512,7 @@ JSObject* FunctionExecutable::compileForCallInternal(ExecState* exec, ScopeChain
UNUSED_PARAM(exec);
UNUSED_PARAM(jitType);
UNUSED_PARAM(exec);
+ UNUSED_PARAM(bytecodeIndex);
#endif
ASSERT((jitType == JITCode::bottomTierJIT()) == !m_codeBlockForCall);
JSObject* exception;
@@ -526,7 +529,7 @@ JSObject* FunctionExecutable::compileForCallInternal(ExecState* exec, ScopeChain
m_symbolTable = m_codeBlockForCall->sharedSymbolTable();
#if ENABLE(JIT)
- if (!prepareFunctionForExecution(exec, m_codeBlockForCall, m_jitCodeForCall, m_jitCodeForCallWithArityCheck, m_symbolTable, jitType, CodeForCall))
+ if (!prepareFunctionForExecution(exec, m_codeBlockForCall, m_jitCodeForCall, m_jitCodeForCallWithArityCheck, m_symbolTable, jitType, bytecodeIndex, CodeForCall))
return 0;
#endif
@@ -544,13 +547,14 @@ JSObject* FunctionExecutable::compileForCallInternal(ExecState* exec, ScopeChain
return 0;
}
-JSObject* FunctionExecutable::compileForConstructInternal(ExecState* exec, ScopeChainNode* scopeChainNode, JITCode::JITType jitType)
+JSObject* FunctionExecutable::compileForConstructInternal(ExecState* exec, ScopeChainNode* scopeChainNode, JITCode::JITType jitType, unsigned bytecodeIndex)
{
SamplingRegion samplingRegion(samplingDescription(jitType));
#if !ENABLE(JIT)
UNUSED_PARAM(jitType);
UNUSED_PARAM(exec);
+ UNUSED_PARAM(bytecodeIndex);
#endif
ASSERT((jitType == JITCode::bottomTierJIT()) == !m_codeBlockForConstruct);
@@ -568,7 +572,7 @@ JSObject* FunctionExecutable::compileForConstructInternal(ExecState* exec, Scope
m_symbolTable = m_codeBlockForConstruct->sharedSymbolTable();
#if ENABLE(JIT)
- if (!prepareFunctionForExecution(exec, m_codeBlockForConstruct, m_jitCodeForConstruct, m_jitCodeForConstructWithArityCheck, m_symbolTable, jitType, CodeForConstruct))
+ if (!prepareFunctionForExecution(exec, m_codeBlockForConstruct, m_jitCodeForConstruct, m_jitCodeForConstructWithArityCheck, m_symbolTable, jitType, bytecodeIndex, CodeForConstruct))
return 0;
#endif
diff --git a/Source/JavaScriptCore/runtime/Executable.h b/Source/JavaScriptCore/runtime/Executable.h
index 2f6c6a253..2e5ba28ca 100644
--- a/Source/JavaScriptCore/runtime/Executable.h
+++ b/Source/JavaScriptCore/runtime/Executable.h
@@ -377,7 +377,7 @@ namespace JSC {
return error;
}
- JSObject* compileOptimized(ExecState*, ScopeChainNode*);
+ JSObject* compileOptimized(ExecState*, ScopeChainNode*, unsigned bytecodeIndex);
#if ENABLE(JIT)
void jettisonOptimizedCode(JSGlobalData&);
@@ -418,7 +418,7 @@ namespace JSC {
static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
EvalExecutable(ExecState*, const SourceCode&, bool);
- JSObject* compileInternal(ExecState*, ScopeChainNode*, JITCode::JITType);
+ JSObject* compileInternal(ExecState*, ScopeChainNode*, JITCode::JITType, unsigned bytecodeIndex = UINT_MAX);
static void visitChildren(JSCell*, SlotVisitor&);
OwnPtr<EvalCodeBlock> m_evalCodeBlock;
@@ -448,7 +448,7 @@ namespace JSC {
return error;
}
- JSObject* compileOptimized(ExecState*, ScopeChainNode*);
+ JSObject* compileOptimized(ExecState*, ScopeChainNode*, unsigned bytecodeIndex);
#if ENABLE(JIT)
void jettisonOptimizedCode(JSGlobalData&);
@@ -485,7 +485,7 @@ namespace JSC {
static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
ProgramExecutable(ExecState*, const SourceCode&);
- JSObject* compileInternal(ExecState*, ScopeChainNode*, JITCode::JITType);
+ JSObject* compileInternal(ExecState*, ScopeChainNode*, JITCode::JITType, unsigned bytecodeIndex = UINT_MAX);
static void visitChildren(JSCell*, SlotVisitor&);
OwnPtr<ProgramCodeBlock> m_programCodeBlock;
@@ -543,7 +543,7 @@ namespace JSC {
return error;
}
- JSObject* compileOptimizedForCall(ExecState*, ScopeChainNode*);
+ JSObject* compileOptimizedForCall(ExecState*, ScopeChainNode*, unsigned bytecodeIndex);
#if ENABLE(JIT)
void jettisonOptimizedCodeForCall(JSGlobalData&);
@@ -571,7 +571,7 @@ namespace JSC {
return error;
}
- JSObject* compileOptimizedForConstruct(ExecState*, ScopeChainNode*);
+ JSObject* compileOptimizedForConstruct(ExecState*, ScopeChainNode*, unsigned bytecodeIndex);
#if ENABLE(JIT)
void jettisonOptimizedCodeForConstruct(JSGlobalData&);
@@ -601,16 +601,16 @@ namespace JSC {
return compileForConstruct(exec, scopeChainNode);
}
- JSObject* compileOptimizedFor(ExecState* exec, ScopeChainNode* scopeChainNode, CodeSpecializationKind kind)
+ JSObject* compileOptimizedFor(ExecState* exec, ScopeChainNode* scopeChainNode, unsigned bytecodeIndex, CodeSpecializationKind kind)
{
ASSERT(exec->callee());
ASSERT(exec->callee()->inherits(&JSFunction::s_info));
ASSERT(jsCast<JSFunction*>(exec->callee())->jsExecutable() == this);
if (kind == CodeForCall)
- return compileOptimizedForCall(exec, scopeChainNode);
+ return compileOptimizedForCall(exec, scopeChainNode, bytecodeIndex);
ASSERT(kind == CodeForConstruct);
- return compileOptimizedForConstruct(exec, scopeChainNode);
+ return compileOptimizedForConstruct(exec, scopeChainNode, bytecodeIndex);
}
#if ENABLE(JIT)
@@ -691,8 +691,8 @@ namespace JSC {
FunctionExecutable(JSGlobalData&, const Identifier& name, const Identifier& inferredName, const SourceCode&, bool forceUsesArguments, FunctionParameters*, bool);
FunctionExecutable(ExecState*, const Identifier& name, const Identifier& inferredName, const SourceCode&, bool forceUsesArguments, FunctionParameters*, bool);
- JSObject* compileForCallInternal(ExecState*, ScopeChainNode*, JITCode::JITType);
- JSObject* compileForConstructInternal(ExecState*, ScopeChainNode*, JITCode::JITType);
+ JSObject* compileForCallInternal(ExecState*, ScopeChainNode*, JITCode::JITType, unsigned bytecodeIndex = UINT_MAX);
+ JSObject* compileForConstructInternal(ExecState*, ScopeChainNode*, JITCode::JITType, unsigned bytecodeIndex = UINT_MAX);
OwnPtr<FunctionCodeBlock>& codeBlockFor(CodeSpecializationKind kind)
{
diff --git a/Source/JavaScriptCore/runtime/ExecutionHarness.h b/Source/JavaScriptCore/runtime/ExecutionHarness.h
index 4cc37f3b7..3a876402e 100644
--- a/Source/JavaScriptCore/runtime/ExecutionHarness.h
+++ b/Source/JavaScriptCore/runtime/ExecutionHarness.h
@@ -36,7 +36,7 @@
namespace JSC {
template<typename CodeBlockType>
-inline bool prepareForExecution(ExecState* exec, OwnPtr<CodeBlockType>& codeBlock, JITCode& jitCode, JITCode::JITType jitType)
+inline bool prepareForExecution(ExecState* exec, OwnPtr<CodeBlockType>& codeBlock, JITCode& jitCode, JITCode::JITType jitType, unsigned bytecodeIndex)
{
#if ENABLE(LLINT)
if (JITCode::isBaselineCode(jitType)) {
@@ -46,10 +46,10 @@ inline bool prepareForExecution(ExecState* exec, OwnPtr<CodeBlockType>& codeBloc
return true;
}
#endif // ENABLE(LLINT)
- return jitCompileIfAppropriate(exec, codeBlock, jitCode, jitType, JITCode::isBaselineCode(jitType) ? JITCompilationMustSucceed : JITCompilationCanFail);
+ return jitCompileIfAppropriate(exec, codeBlock, jitCode, jitType, bytecodeIndex, JITCode::isBaselineCode(jitType) ? JITCompilationMustSucceed : JITCompilationCanFail);
}
-inline bool prepareFunctionForExecution(ExecState* exec, OwnPtr<FunctionCodeBlock>& codeBlock, JITCode& jitCode, MacroAssemblerCodePtr& jitCodeWithArityCheck, SharedSymbolTable*& symbolTable, JITCode::JITType jitType, CodeSpecializationKind kind)
+inline bool prepareFunctionForExecution(ExecState* exec, OwnPtr<FunctionCodeBlock>& codeBlock, JITCode& jitCode, MacroAssemblerCodePtr& jitCodeWithArityCheck, SharedSymbolTable*& symbolTable, JITCode::JITType jitType, unsigned bytecodeIndex, CodeSpecializationKind kind)
{
#if ENABLE(LLINT)
if (JITCode::isBaselineCode(jitType)) {
@@ -61,7 +61,7 @@ inline bool prepareFunctionForExecution(ExecState* exec, OwnPtr<FunctionCodeBloc
#else
UNUSED_PARAM(kind);
#endif // ENABLE(LLINT)
- return jitCompileFunctionIfAppropriate(exec, codeBlock, jitCode, jitCodeWithArityCheck, symbolTable, jitType, JITCode::isBaselineCode(jitType) ? JITCompilationMustSucceed : JITCompilationCanFail);
+ return jitCompileFunctionIfAppropriate(exec, codeBlock, jitCode, jitCodeWithArityCheck, symbolTable, jitType, bytecodeIndex, JITCode::isBaselineCode(jitType) ? JITCompilationMustSucceed : JITCompilationCanFail);
}
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/Structure.h b/Source/JavaScriptCore/runtime/Structure.h
index ee0b573d9..0b9c92210 100644
--- a/Source/JavaScriptCore/runtime/Structure.h
+++ b/Source/JavaScriptCore/runtime/Structure.h
@@ -322,6 +322,11 @@ namespace JSC {
{
return OBJECT_OFFSETOF(Structure, m_typeInfo) + TypeInfo::typeOffset();
}
+
+ static ptrdiff_t classInfoOffset()
+ {
+ return OBJECT_OFFSETOF(Structure, m_classInfo);
+ }
static Structure* createStructure(JSGlobalData&);
diff --git a/Source/JavaScriptCore/shell/PlatformEfl.cmake b/Source/JavaScriptCore/shell/PlatformEfl.cmake
index c35af2d51..53755727b 100644
--- a/Source/JavaScriptCore/shell/PlatformEfl.cmake
+++ b/Source/JavaScriptCore/shell/PlatformEfl.cmake
@@ -1,5 +1,5 @@
LIST(APPEND JSC_LIBRARIES
- ${Glib_LIBRARIES}
+ ${GLIB_LIBRARIES}
${ECORE_LIBRARIES}
${CMAKE_DL_LIBS}
)