Commit 97e94ddd authored by fpizlo@apple.com's avatar 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):



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@138399 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 5f4aface
......@@ -95,6 +95,7 @@ set(JavaScriptCore_SOURCES
dfg/DFGOSRExitCompiler.cpp
dfg/DFGOSRExitCompiler32_64.cpp
dfg/DFGOSRExitCompiler64.cpp
dfg/DFGOSRExitJumpPlaceholder.cpp
dfg/DFGOperations.cpp
dfg/DFGPhase.cpp
dfg/DFGPredictionPropagationPhase.cpp
......
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.
......
......@@ -172,6 +172,7 @@ javascriptcore_sources += \
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 @@ javascriptcore_sources += \
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 \
......
......@@ -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;
};
......
......@@ -132,6 +132,7 @@ SOURCES += \
dfg/DFGOSRExitCompiler.cpp \
dfg/DFGOSRExitCompiler64.cpp \
dfg/DFGOSRExitCompiler32_64.cpp \
dfg/DFGOSRExitJumpPlaceholder.cpp \
dfg/DFGPhase.cpp \
dfg/DFGPredictionPropagationPhase.cpp \
dfg/DFGRepatch.cpp \
......
/*
* 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
/*
* 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)
/*
* 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
......@@ -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 @@ void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource
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 @@ void SpeculativeJIT::arrayify(Node& node, GPRReg baseReg, GPRReg propertyReg)
}
// 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 @@ void SpeculativeJIT::arrayify(Node& node, GPRReg baseReg, GPRReg propertyReg)
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;
}
}
// 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;
slowPath.append(jumpSlowForUnwantedArrayMode(tempGPR, node.arrayMode()));
}
silentFillAllRegisters(tempGPR);
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()));
}
addSlowPathGenerator(adoptPtr(new ArrayifySlowPathGenerator(
slowPath, this, node, baseReg, propertyReg, tempGPR, structureGPR)));
done.link(&m_jit);
noResult(m_compileIndex);
}
......
......@@ -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 @@ public:
// 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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment