DFG Arrayify slow path should be out-of-line
https://bugs.webkit.org/show_bug.cgi?id=105400
Reviewed by Gavin Barraclough.
The interesting bit of this change is allowing out-of-line slow path generators
to emit speculation checks. This is accomplished by having a version of
speculationCheck() that returns a jump placeholder instead of taking a jump (or
jump list) as an argument. You can then fill in that jump placeholder at a
later time, so long as you do it before OSR exit linking. Slow path generators
run before linking, so that just naturally ends up working.
This isn't really a big win, but we know that out-of-lining slow paths is
generally a good thing to do, so it's fair to assume that this is a move in the
right direction.
* CMakeLists.txt:
* GNUmakefile.list.am:
* JavaScriptCore.xcodeproj/project.pbxproj:
* Target.pri:
* dfg/DFGArrayifySlowPathGenerator.h: Added.
(DFG):
(ArrayifySlowPathGenerator):
(JSC::DFG::ArrayifySlowPathGenerator::ArrayifySlowPathGenerator):
(JSC::DFG::ArrayifySlowPathGenerator::generateInternal):
* dfg/DFGOSRExitJumpPlaceholder.cpp: Added.
(DFG):
(JSC::DFG::OSRExitJumpPlaceholder::fill):
* dfg/DFGOSRExitJumpPlaceholder.h: Added.
(DFG):
(OSRExitJumpPlaceholder):
(JSC::DFG::OSRExitJumpPlaceholder::OSRExitJumpPlaceholder):
(JSC::DFG::OSRExitJumpPlaceholder::operator!):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::speculationCheck):
(DFG):
(JSC::DFG::SpeculativeJIT::arrayify):
* dfg/DFGSpeculativeJIT.h:
(SpeculativeJIT):
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@138399 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/CMakeLists.txt b/Source/JavaScriptCore/CMakeLists.txt
index 8a12d17..f89d5ab 100644
--- a/Source/JavaScriptCore/CMakeLists.txt
+++ b/Source/JavaScriptCore/CMakeLists.txt
@@ -95,6 +95,7 @@
dfg/DFGOSRExitCompiler.cpp
dfg/DFGOSRExitCompiler32_64.cpp
dfg/DFGOSRExitCompiler64.cpp
+ dfg/DFGOSRExitJumpPlaceholder.cpp
dfg/DFGOperations.cpp
dfg/DFGPhase.cpp
dfg/DFGPredictionPropagationPhase.cpp
diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog
index 0fa5383..fbde4ee 100644
--- a/Source/JavaScriptCore/ChangeLog
+++ b/Source/JavaScriptCore/ChangeLog
@@ -1,3 +1,45 @@
+2012-12-21 Filip Pizlo <fpizlo@apple.com>
+
+ DFG Arrayify slow path should be out-of-line
+ https://bugs.webkit.org/show_bug.cgi?id=105400
+
+ Reviewed by Gavin Barraclough.
+
+ The interesting bit of this change is allowing out-of-line slow path generators
+ to emit speculation checks. This is accomplished by having a version of
+ speculationCheck() that returns a jump placeholder instead of taking a jump (or
+ jump list) as an argument. You can then fill in that jump placeholder at a
+ later time, so long as you do it before OSR exit linking. Slow path generators
+ run before linking, so that just naturally ends up working.
+
+ This isn't really a big win, but we know that out-of-lining slow paths is
+ generally a good thing to do, so it's fair to assume that this is a move in the
+ right direction.
+
+ * CMakeLists.txt:
+ * GNUmakefile.list.am:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * Target.pri:
+ * dfg/DFGArrayifySlowPathGenerator.h: Added.
+ (DFG):
+ (ArrayifySlowPathGenerator):
+ (JSC::DFG::ArrayifySlowPathGenerator::ArrayifySlowPathGenerator):
+ (JSC::DFG::ArrayifySlowPathGenerator::generateInternal):
+ * dfg/DFGOSRExitJumpPlaceholder.cpp: Added.
+ (DFG):
+ (JSC::DFG::OSRExitJumpPlaceholder::fill):
+ * dfg/DFGOSRExitJumpPlaceholder.h: Added.
+ (DFG):
+ (OSRExitJumpPlaceholder):
+ (JSC::DFG::OSRExitJumpPlaceholder::OSRExitJumpPlaceholder):
+ (JSC::DFG::OSRExitJumpPlaceholder::operator!):
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::speculationCheck):
+ (DFG):
+ (JSC::DFG::SpeculativeJIT::arrayify):
+ * dfg/DFGSpeculativeJIT.h:
+ (SpeculativeJIT):
+
2012-12-20 Oliver Hunt <oliver@apple.com>
Finally found the problem. Using the wrong JSContextGroup.
diff --git a/Source/JavaScriptCore/GNUmakefile.list.am b/Source/JavaScriptCore/GNUmakefile.list.am
index 14c419b..437b2ae 100644
--- a/Source/JavaScriptCore/GNUmakefile.list.am
+++ b/Source/JavaScriptCore/GNUmakefile.list.am
@@ -172,6 +172,7 @@
Source/JavaScriptCore/dfg/DFGArgumentsSimplificationPhase.h \
Source/JavaScriptCore/dfg/DFGArrayMode.cpp \
Source/JavaScriptCore/dfg/DFGArrayMode.h \
+ Source/JavaScriptCore/dfg/DFGArrayifySlowPathGenerator.h \
Source/JavaScriptCore/dfg/DFGAssemblyHelpers.cpp \
Source/JavaScriptCore/dfg/DFGAssemblyHelpers.h \
Source/JavaScriptCore/dfg/DFGBasicBlock.h \
@@ -229,6 +230,8 @@
Source/JavaScriptCore/dfg/DFGOSRExit.h \
Source/JavaScriptCore/dfg/DFGOSRExit.cpp \
Source/JavaScriptCore/dfg/DFGOSRExitCompilationInfo.h \
+ Source/JavaScriptCore/dfg/DFGOSRExitJumpPlaceholder.cpp \
+ Source/JavaScriptCore/dfg/DFGOSRExitJumpPlaceholder.h \
Source/JavaScriptCore/dfg/DFGPhase.cpp \
Source/JavaScriptCore/dfg/DFGPhase.h \
Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp \
diff --git a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj b/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
index c37e9a3..4c90cbd 100644
--- a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
+++ b/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
@@ -58,6 +58,7 @@
/* End PBXAggregateTarget section */
/* Begin PBXBuildFile section */
+ 0F05C3B41683CF9200BAF45B /* DFGArrayifySlowPathGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F05C3B21683CF8F00BAF45B /* DFGArrayifySlowPathGenerator.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F0776BF14FF002B00102332 /* JITCompilationEffort.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0776BD14FF002800102332 /* JITCompilationEffort.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F0B839A14BCF45D00885B4F /* LLIntEntrypoints.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F0B839514BCF45A00885B4F /* LLIntEntrypoints.cpp */; };
0F0B839B14BCF46000885B4F /* LLIntEntrypoints.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0B839614BCF45A00885B4F /* LLIntEntrypoints.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -258,6 +259,8 @@
0FE228EE1436AB2C00196C48 /* Options.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FE228EA1436AB2300196C48 /* Options.cpp */; };
0FEB3ECD16237F4D00AB67AD /* TypedArrayDescriptor.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FEB3ECB16237F4700AB67AD /* TypedArrayDescriptor.h */; settings = {ATTRIBUTES = (Private, ); }; };
0FEB3ECF16237F6C00AB67AD /* MacroAssembler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FEB3ECE16237F6700AB67AD /* MacroAssembler.cpp */; };
+ 0FEFC9AA1681A3B300567F53 /* DFGOSRExitJumpPlaceholder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FEFC9A71681A3B000567F53 /* DFGOSRExitJumpPlaceholder.cpp */; };
+ 0FEFC9AB1681A3B600567F53 /* DFGOSRExitJumpPlaceholder.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FEFC9A81681A3B000567F53 /* DFGOSRExitJumpPlaceholder.h */; settings = {ATTRIBUTES = (Private, ); }; };
0FF42731158EBD54004CB9FF /* Disassembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FF4272F158EBD44004CB9FF /* Disassembler.h */; settings = {ATTRIBUTES = (Private, ); }; };
0FF42732158EBD58004CB9FF /* UDis86Disassembler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FF42730158EBD44004CB9FF /* UDis86Disassembler.cpp */; };
0FF42740158EBE8B004CB9FF /* udis86_decode.c in Sources */ = {isa = PBXBuildFile; fileRef = 0FF42734158EBD94004CB9FF /* udis86_decode.c */; };
@@ -891,6 +894,7 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
+ 0F05C3B21683CF8F00BAF45B /* DFGArrayifySlowPathGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGArrayifySlowPathGenerator.h; path = dfg/DFGArrayifySlowPathGenerator.h; sourceTree = "<group>"; };
0F0776BD14FF002800102332 /* JITCompilationEffort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITCompilationEffort.h; sourceTree = "<group>"; };
0F0B839514BCF45A00885B4F /* LLIntEntrypoints.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LLIntEntrypoints.cpp; path = llint/LLIntEntrypoints.cpp; sourceTree = "<group>"; };
0F0B839614BCF45A00885B4F /* LLIntEntrypoints.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLIntEntrypoints.h; path = llint/LLIntEntrypoints.h; sourceTree = "<group>"; };
@@ -1095,6 +1099,8 @@
0FE228EB1436AB2300196C48 /* Options.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Options.h; sourceTree = "<group>"; };
0FEB3ECB16237F4700AB67AD /* TypedArrayDescriptor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TypedArrayDescriptor.h; sourceTree = "<group>"; };
0FEB3ECE16237F6700AB67AD /* MacroAssembler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MacroAssembler.cpp; sourceTree = "<group>"; };
+ 0FEFC9A71681A3B000567F53 /* DFGOSRExitJumpPlaceholder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGOSRExitJumpPlaceholder.cpp; path = dfg/DFGOSRExitJumpPlaceholder.cpp; sourceTree = "<group>"; };
+ 0FEFC9A81681A3B000567F53 /* DFGOSRExitJumpPlaceholder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGOSRExitJumpPlaceholder.h; path = dfg/DFGOSRExitJumpPlaceholder.h; sourceTree = "<group>"; };
0FF4272F158EBD44004CB9FF /* Disassembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Disassembler.h; path = disassembler/Disassembler.h; sourceTree = "<group>"; };
0FF42730158EBD44004CB9FF /* UDis86Disassembler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UDis86Disassembler.cpp; path = disassembler/UDis86Disassembler.cpp; sourceTree = "<group>"; };
0FF42734158EBD94004CB9FF /* udis86_decode.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = udis86_decode.c; path = disassembler/udis86/udis86_decode.c; sourceTree = "<group>"; };
@@ -2460,7 +2466,6 @@
86EC9DB31328DF44002B2AD7 /* dfg */ = {
isa = PBXGroup;
children = (
- 65987F2C167FE84B003C2F8D /* DFGOSRExitCompilationInfo.h */,
0F62016D143FCD2F0068B77C /* DFGAbstractState.cpp */,
0F62016E143FCD2F0068B77C /* DFGAbstractState.h */,
0F62016F143FCD2F0068B77C /* DFGAbstractValue.h */,
@@ -2468,6 +2473,7 @@
0F1E3A431534CBAD000F9456 /* DFGArgumentPosition.h */,
0F16015A156198BF00C2587C /* DFGArgumentsSimplificationPhase.cpp */,
0F16015B156198BF00C2587C /* DFGArgumentsSimplificationPhase.h */,
+ 0F05C3B21683CF8F00BAF45B /* DFGArrayifySlowPathGenerator.h */,
0F63948115E48114006A597C /* DFGArrayMode.cpp */,
0F63948215E48114006A597C /* DFGArrayMode.h */,
0FC0976B1468AB4A00CF2442 /* DFGAssemblyHelpers.cpp */,
@@ -2521,10 +2527,13 @@
0FD82E53141DAEDE00179C94 /* DFGOSREntry.h */,
0FC0978E146A6F6300CF2442 /* DFGOSRExit.cpp */,
0FC097681468A6EF00CF2442 /* DFGOSRExit.h */,
+ 65987F2C167FE84B003C2F8D /* DFGOSRExitCompilationInfo.h */,
0FC0978F146A6F6300CF2442 /* DFGOSRExitCompiler.cpp */,
0FC0976F14693AEF00CF2442 /* DFGOSRExitCompiler.h */,
0FC09775146943AD00CF2442 /* DFGOSRExitCompiler32_64.cpp */,
0FC0977014693AEF00CF2442 /* DFGOSRExitCompiler64.cpp */,
+ 0FEFC9A71681A3B000567F53 /* DFGOSRExitJumpPlaceholder.cpp */,
+ 0FEFC9A81681A3B000567F53 /* DFGOSRExitJumpPlaceholder.h */,
0FFFC94F14EF909500C72532 /* DFGPhase.cpp */,
0FFFC95014EF909500C72532 /* DFGPhase.h */,
0FFFC95114EF909500C72532 /* DFGPredictionPropagationPhase.cpp */,
@@ -3183,6 +3192,8 @@
0F13912A16771C36009CCB07 /* ProfilerBytecodeSequence.h in Headers */,
0F13912C16771C3D009CCB07 /* ProfilerProfiledBytecodes.h in Headers */,
A7C0C4AC168103020017011D /* JSScriptRefPrivate.h in Headers */,
+ 0FEFC9AB1681A3B600567F53 /* DFGOSRExitJumpPlaceholder.h in Headers */,
+ 0F05C3B41683CF9200BAF45B /* DFGArrayifySlowPathGenerator.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -3801,6 +3812,7 @@
0F13912916771C33009CCB07 /* ProfilerBytecodeSequence.cpp in Sources */,
0F13912B16771C3A009CCB07 /* ProfilerProfiledBytecodes.cpp in Sources */,
A7C0C4AD1681067E0017011D /* JSScriptRef.cpp in Sources */,
+ 0FEFC9AA1681A3B300567F53 /* DFGOSRExitJumpPlaceholder.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
diff --git a/Source/JavaScriptCore/Target.pri b/Source/JavaScriptCore/Target.pri
index 788d909..666aa56 100644
--- a/Source/JavaScriptCore/Target.pri
+++ b/Source/JavaScriptCore/Target.pri
@@ -132,6 +132,7 @@
dfg/DFGOSRExitCompiler.cpp \
dfg/DFGOSRExitCompiler64.cpp \
dfg/DFGOSRExitCompiler32_64.cpp \
+ dfg/DFGOSRExitJumpPlaceholder.cpp \
dfg/DFGPhase.cpp \
dfg/DFGPredictionPropagationPhase.cpp \
dfg/DFGRepatch.cpp \
diff --git a/Source/JavaScriptCore/dfg/DFGArrayifySlowPathGenerator.h b/Source/JavaScriptCore/dfg/DFGArrayifySlowPathGenerator.h
new file mode 100644
index 0000000..cd40836
--- /dev/null
+++ b/Source/JavaScriptCore/dfg/DFGArrayifySlowPathGenerator.h
@@ -0,0 +1,167 @@
+/*
+ * 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 DFGArrayifySlowPathGenerator_h
+#define DFGArrayifySlowPathGenerator_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(DFG_JIT)
+
+#include "DFGArrayMode.h"
+#include "DFGCommon.h"
+#include "DFGOSRExitJumpPlaceholder.h"
+#include "DFGOperations.h"
+#include "DFGSlowPathGenerator.h"
+#include "DFGSpeculativeJIT.h"
+#include <wtf/Vector.h>
+
+namespace JSC { namespace DFG {
+
+class ArrayifySlowPathGenerator : public JumpingSlowPathGenerator<MacroAssembler::JumpList> {
+public:
+ ArrayifySlowPathGenerator(
+ const MacroAssembler::JumpList& from, SpeculativeJIT* jit, Node& node, GPRReg baseGPR,
+ GPRReg propertyGPR, GPRReg tempGPR, GPRReg structureGPR)
+ : JumpingSlowPathGenerator<MacroAssembler::JumpList>(from, jit)
+ , m_op(node.op())
+ , m_arrayMode(node.arrayMode())
+ , m_structure(node.op() == ArrayifyToStructure ? node.structure() : 0)
+ , m_baseGPR(baseGPR)
+ , m_propertyGPR(propertyGPR)
+ , m_tempGPR(tempGPR)
+ , m_structureGPR(structureGPR)
+ {
+ ASSERT(m_op == Arrayify || m_op == ArrayifyToStructure);
+
+ jit->silentSpillAllRegistersImpl(false, m_plans, InvalidGPRReg);
+
+ if (m_propertyGPR != InvalidGPRReg) {
+ switch (m_arrayMode.type()) {
+ case Array::Int32:
+ case Array::Double:
+ case Array::Contiguous:
+ m_badPropertyJump = jit->speculationCheck(Uncountable, JSValueRegs(), NoNode);
+ break;
+ default:
+ break;
+ }
+ }
+ m_badIndexingTypeJump = jit->speculationCheck(BadIndexingType, JSValueSource::unboxedCell(m_baseGPR), NoNode);
+ }
+
+protected:
+ void generateInternal(SpeculativeJIT* jit)
+ {
+ linkFrom(jit);
+
+ ASSERT(m_op == Arrayify || m_op == ArrayifyToStructure);
+
+ if (m_propertyGPR != InvalidGPRReg) {
+ switch (m_arrayMode.type()) {
+ case Array::Int32:
+ case Array::Double:
+ case Array::Contiguous:
+ m_badPropertyJump.fill(jit, jit->m_jit.branch32(
+ MacroAssembler::AboveOrEqual, m_propertyGPR,
+ MacroAssembler::TrustedImm32(MIN_SPARSE_ARRAY_INDEX)));
+ break;
+ default:
+ break;
+ }
+ }
+
+ for (unsigned i = 0; i < m_plans.size(); ++i)
+ jit->silentSpill(m_plans[i]);
+ switch (m_arrayMode.type()) {
+ case Array::Int32:
+ jit->callOperation(operationEnsureInt32, m_tempGPR, m_baseGPR);
+ break;
+ case Array::Double:
+ jit->callOperation(operationEnsureDouble, m_tempGPR, m_baseGPR);
+ break;
+ case Array::Contiguous:
+ if (m_arrayMode.conversion() == Array::RageConvert)
+ jit->callOperation(operationRageEnsureContiguous, m_tempGPR, m_baseGPR);
+ else
+ jit->callOperation(operationEnsureContiguous, m_tempGPR, m_baseGPR);
+ break;
+ case Array::ArrayStorage:
+ case Array::SlowPutArrayStorage:
+ jit->callOperation(operationEnsureArrayStorage, m_tempGPR, m_baseGPR);
+ break;
+ default:
+ CRASH();
+ break;
+ }
+ for (unsigned i = m_plans.size(); i--;)
+ jit->silentFill(m_plans[i], GPRInfo::regT0);
+
+ if (m_op == ArrayifyToStructure) {
+ ASSERT(m_structure);
+ m_badIndexingTypeJump.fill(
+ jit, jit->m_jit.branchWeakPtr(
+ MacroAssembler::NotEqual,
+ MacroAssembler::Address(m_baseGPR, JSCell::structureOffset()),
+ m_structure));
+ } else {
+ // Alas, we need to reload the structure because silent spilling does not save
+ // temporaries. Nor would it be useful for it to do so. Either way we're talking
+ // about a load.
+ jit->m_jit.loadPtr(
+ MacroAssembler::Address(m_baseGPR, JSCell::structureOffset()), m_structureGPR);
+
+ // Finally, check that we have the kind of array storage that we wanted to get.
+ // Note that this is a backwards speculation check, which will result in the
+ // bytecode operation corresponding to this arrayification being reexecuted.
+ // That's fine, since arrayification is not user-visible.
+ jit->m_jit.load8(
+ MacroAssembler::Address(m_structureGPR, Structure::indexingTypeOffset()), m_structureGPR);
+ m_badIndexingTypeJump.fill(
+ jit, jit->jumpSlowForUnwantedArrayMode(m_structureGPR, m_arrayMode));
+ }
+
+ jumpTo(jit);
+ }
+
+private:
+ NodeType m_op;
+ ArrayMode m_arrayMode;
+ Structure* m_structure;
+ GPRReg m_baseGPR;
+ GPRReg m_propertyGPR;
+ GPRReg m_tempGPR;
+ GPRReg m_structureGPR;
+ OSRExitJumpPlaceholder m_badPropertyJump;
+ OSRExitJumpPlaceholder m_badIndexingTypeJump;
+ Vector<SilentRegisterSavePlan, 2> m_plans;
+};
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
+#endif // DFGArrayifySlowPathGenerator_h
+
diff --git a/Source/JavaScriptCore/dfg/DFGOSRExitJumpPlaceholder.cpp b/Source/JavaScriptCore/dfg/DFGOSRExitJumpPlaceholder.cpp
new file mode 100644
index 0000000..fec99ec
--- /dev/null
+++ b/Source/JavaScriptCore/dfg/DFGOSRExitJumpPlaceholder.cpp
@@ -0,0 +1,51 @@
+/*
+ * 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 "DFGOSRExitJumpPlaceholder.h"
+
+#if ENABLE(DFG_JIT)
+
+#include "DFGJITCompiler.h"
+#include "DFGSpeculativeJIT.h"
+
+namespace JSC { namespace DFG {
+
+void OSRExitJumpPlaceholder::fill(JITCompiler& jit, const MacroAssembler::JumpList& jumps)
+{
+ if (!*this)
+ return;
+ jit.m_exitCompilationInfo[m_index].m_failureJumps = jumps;
+}
+
+void OSRExitJumpPlaceholder::fill(SpeculativeJIT* jit, const MacroAssembler::JumpList& jumps)
+{
+ fill(jit->m_jit, jumps);
+}
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
diff --git a/Source/JavaScriptCore/dfg/DFGOSRExitJumpPlaceholder.h b/Source/JavaScriptCore/dfg/DFGOSRExitJumpPlaceholder.h
new file mode 100644
index 0000000..4e016a4
--- /dev/null
+++ b/Source/JavaScriptCore/dfg/DFGOSRExitJumpPlaceholder.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 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 DFGOSRExitJumpPlaceholder_h
+#define DFGOSRExitJumpPlaceholder_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(DFG_JIT)
+
+#include "DFGCommon.h"
+#include "MacroAssembler.h"
+
+namespace JSC { namespace DFG {
+
+class JITCompiler;
+class SpeculativeJIT;
+
+class OSRExitJumpPlaceholder {
+public:
+ OSRExitJumpPlaceholder()
+ : m_index(std::numeric_limits<unsigned>::max())
+ {
+ }
+
+private:
+ friend class SpeculativeJIT;
+
+ OSRExitJumpPlaceholder(unsigned index)
+ : m_index(index)
+ {
+ }
+
+public:
+ bool operator!() const { return m_index == std::numeric_limits<unsigned>::max(); }
+
+ void fill(JITCompiler&, const MacroAssembler::JumpList&);
+ void fill(SpeculativeJIT*, const MacroAssembler::JumpList&);
+
+private:
+ unsigned m_index;
+};
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
+#endif // DFGOSRExitJumpPlaceholder_h
+
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
index 8549142..bd3fda2 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
@@ -29,6 +29,7 @@
#if ENABLE(DFG_JIT)
#include "Arguments.h"
+#include "DFGArrayifySlowPathGenerator.h"
#include "DFGCallArrayAllocatorSlowPathGenerator.h"
#include "DFGSlowPathGenerator.h"
#include "LinkBuffer.h"
@@ -119,6 +120,23 @@
speculationCheck(kind, jsValueSource, nodeUse.index(), jumpToFail);
}
+OSRExitJumpPlaceholder SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex)
+{
+ if (!m_compileOkay)
+ return OSRExitJumpPlaceholder();
+ ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes);
+ unsigned index = m_jit.codeBlock()->numberOfOSRExits();
+ m_jit.appendExitInfo();
+ m_jit.codeBlock()->appendOSRExit(OSRExit(kind, jsValueSource, m_jit.graph().methodOfGettingAValueProfileFor(nodeIndex), this, m_stream->size()));
+ return OSRExitJumpPlaceholder(index);
+}
+
+OSRExitJumpPlaceholder SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse)
+{
+ ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes);
+ return speculationCheck(kind, jsValueSource, nodeUse.index());
+}
+
void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex, const MacroAssembler::JumpList& jumpsToFail)
{
if (!m_compileOkay)
@@ -548,11 +566,11 @@
}
// We can skip all that comes next if we already have array storage.
- MacroAssembler::JumpList done;
+ MacroAssembler::JumpList slowPath;
if (node.op() == ArrayifyToStructure) {
- done.append(m_jit.branchWeakPtr(
- JITCompiler::Equal,
+ slowPath.append(m_jit.branchWeakPtr(
+ JITCompiler::NotEqual,
JITCompiler::Address(baseReg, JSCell::structureOffset()),
node.structure()));
} else {
@@ -562,77 +580,12 @@
m_jit.load8(
MacroAssembler::Address(structureGPR, Structure::indexingTypeOffset()), tempGPR);
- done = jumpSlowForUnwantedArrayMode(tempGPR, node.arrayMode(), true);
- }
-
- // If we're allegedly creating contiguous storage and the index is bogus, then
- // just don't.
- if (propertyReg != InvalidGPRReg) {
- switch (node.arrayMode().type()) {
- case Array::Int32:
- case Array::Double:
- case Array::Contiguous:
- speculationCheck(
- Uncountable, JSValueRegs(), NoNode,
- m_jit.branch32(
- MacroAssembler::AboveOrEqual, propertyReg, TrustedImm32(MIN_SPARSE_ARRAY_INDEX)));
- break;
- default:
- break;
- }
+ slowPath.append(jumpSlowForUnwantedArrayMode(tempGPR, node.arrayMode()));
}
- // Now call out to create the array storage.
- silentSpillAllRegisters(tempGPR);
- switch (node.arrayMode().type()) {
- case Array::Int32:
- callOperation(operationEnsureInt32, tempGPR, baseReg);
- break;
- case Array::Double:
- callOperation(operationEnsureDouble, tempGPR, baseReg);
- break;
- case Array::Contiguous:
- if (node.arrayMode().conversion() == Array::RageConvert)
- callOperation(operationRageEnsureContiguous, tempGPR, baseReg);
- else
- callOperation(operationEnsureContiguous, tempGPR, baseReg);
- break;
- case Array::ArrayStorage:
- case Array::SlowPutArrayStorage:
- callOperation(operationEnsureArrayStorage, tempGPR, baseReg);
- break;
- default:
- CRASH();
- break;
- }
- silentFillAllRegisters(tempGPR);
+ addSlowPathGenerator(adoptPtr(new ArrayifySlowPathGenerator(
+ slowPath, this, node, baseReg, propertyReg, tempGPR, structureGPR)));
- if (node.op() == ArrayifyToStructure) {
- speculationCheck(
- BadIndexingType, JSValueSource::unboxedCell(baseReg), NoNode,
- m_jit.branchWeakPtr(
- JITCompiler::NotEqual,
- JITCompiler::Address(baseReg, JSCell::structureOffset()),
- node.structure()));
- } else {
- // Alas, we need to reload the structure because silent spilling does not save
- // temporaries. Nor would it be useful for it to do so. Either way we're talking
- // about a load.
- m_jit.loadPtr(
- MacroAssembler::Address(baseReg, JSCell::structureOffset()), structureGPR);
-
- // Finally, check that we have the kind of array storage that we wanted to get.
- // Note that this is a backwards speculation check, which will result in the
- // bytecode operation corresponding to this arrayification being reexecuted.
- // That's fine, since arrayification is not user-visible.
- m_jit.load8(
- MacroAssembler::Address(structureGPR, Structure::indexingTypeOffset()), structureGPR);
- speculationCheck(
- BadIndexingType, JSValueSource::unboxedCell(baseReg), NoNode,
- jumpSlowForUnwantedArrayMode(structureGPR, node.arrayMode()));
- }
-
- done.link(&m_jit);
noResult(m_compileIndex);
}
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
index b684282..5ea1076 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
@@ -34,6 +34,7 @@
#include "DFGGenerationInfo.h"
#include "DFGJITCompiler.h"
#include "DFGOSRExit.h"
+#include "DFGOSRExitJumpPlaceholder.h"
#include "DFGOperations.h"
#include "DFGSilentRegisterSavePlan.h"
#include "DFGValueSource.h"
@@ -2445,6 +2446,9 @@
// Add a speculation check without additional recovery.
void speculationCheck(ExitKind, JSValueSource, NodeIndex, MacroAssembler::Jump jumpToFail);
void speculationCheck(ExitKind, JSValueSource, Edge, MacroAssembler::Jump jumpToFail);
+ // Add a speculation check without additional recovery, and with a promise to supply a jump later.
+ OSRExitJumpPlaceholder speculationCheck(ExitKind, JSValueSource, NodeIndex);
+ OSRExitJumpPlaceholder speculationCheck(ExitKind, JSValueSource, Edge);
// Add a set of speculation checks without additional recovery.
void speculationCheck(ExitKind, JSValueSource, NodeIndex, const MacroAssembler::JumpList& jumpsToFail);
void speculationCheck(ExitKind, JSValueSource, Edge, const MacroAssembler::JumpList& jumpsToFail);