Commit c6bb4a9f authored by fpizlo@apple.com's avatar fpizlo@apple.com

Get rid of the AlreadyInJSStack recoveries since they are totally redundant...

Get rid of the AlreadyInJSStack recoveries since they are totally redundant with the DisplacedInJSStack recoveries
https://bugs.webkit.org/show_bug.cgi?id=122065

Reviewed by Mark Hahnenberg.
        
This mostly just kills a bunch of code.
        
But incidentaly while killing that code, I uncovered a bug in our FTL OSR entrypoint
creation phase. The phase inserts a sequence of SetLocal(ExtractOSREntryLocal) nodes.
If we hoist some type check into the local, then we might inject a conversion node
between the ExtractOSREntryLocal and the SetLocal - for example we might put in a
Int32ToDouble node. But currently the FixupPhase will make all conversion nodes placed
on an edge of a SetLocal use forward exit. This then confuses the OSR exit machinery.
When OSR exit sees a forward exit, it tries to "roll forward" execution from the exiting
node to the first node that has a different CodeOrigin. This only works if the nodes
after the forward exit are MovHints or other tnings that the OSR exit compiler can
forward-execute. But here, it will see a bunch of SetLocal and ExtractOSREntryLocal
nodes for the same bytecode index. Two possible solutions exist. We could teach the
forward-execution logic how to deal with multiple SetLocals and ExtractOSREntryLocals.
This would be a lot of complexity; right now it just needs to deal with exactly one
SetLocal-like operation. The alternative is to make sure that the conversion node that
we inject ends up exiting *backward* rather than forward.
        
But making the conversion nodes exit backward is somewhat tricky. Before this patch,
conversion nodes always exit forward for SetLocals and backwards otherwise. It turns out
that the solution is to rationalize how we choose the speculation direciton for a
conversion node. The conversion node's speculation direction should be the same as the
speculation direction of the node for which it is doing a conversion. Since SetLocal's
already exit forward by default, this policy preserves our previous behavior. But it
also allows the OSR entrypoint creation phase to make its SetLocals exit backward
instead.
        
Of course, if the SetLocal(ExtractOSREntryLocal) sequences exit backward, then we need
to make sure that the OSR exit machine knows that the local variables are indeed live.
Consider that if we have:
        
    a: ExtractOSREntryLocal(loc1)
    b: SetLocal(@a, loc1)
    c: ExtractOSRentryLocal(loc2)
    d: SetLocal(@c, loc2)
        
Without additional magic, the exit at @b will think that loc2 is dead and the OSR exit
compiler will clobber loc2 with Undefined. So we need to make sure that we actually
emit code like:
        
    a: ExtractOSREntryLocal(loc1)
    b: ExtractOSREntryLocal(loc2)
    c: SetLocal(@a, loc1)
    d: SetLocal(@b, loc2)
    e: SetLocal(@a, loc1)
    f: SetLocal(@b, loc2)

* CMakeLists.txt:
* GNUmakefile.list.am:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
* JavaScriptCore.xcodeproj/project.pbxproj:
* Target.pri:
* bytecode/CodeOrigin.h:
* bytecode/ValueRecovery.cpp: Added.
(JSC::ValueRecovery::recover):
(JSC::ValueRecovery::dumpInContext):
(JSC::ValueRecovery::dump):
* bytecode/ValueRecovery.h:
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupSetLocalsInBlock):
(JSC::DFG::FixupPhase::fixEdge):
* dfg/DFGJITCode.cpp:
(JSC::DFG::JITCode::reconstruct):
* dfg/DFGNode.h:
(JSC::DFG::Node::speculationDirection):
(JSC::DFG::Node::setSpeculationDirection):
* dfg/DFGOSREntrypointCreationPhase.cpp:
(JSC::DFG::OSREntrypointCreationPhase::run):
* dfg/DFGOSRExitCompiler32_64.cpp:
(JSC::DFG::OSRExitCompiler::compileExit):
* dfg/DFGOSRExitCompiler64.cpp:
(JSC::DFG::OSRExitCompiler::compileExit):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileInlineStart):
(JSC::DFG::SpeculativeJIT::computeValueRecoveryFor):
* dfg/DFGSpeculativeJIT.h:
(JSC::DFG::SpeculativeJIT::computeValueRecoveryFor):
* dfg/DFGValueSource.h:
(JSC::DFG::ValueSource::valueRecovery):
* dfg/DFGVariableEventStream.cpp:
(JSC::DFG::VariableEventStream::reconstruct):
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::LowerDFGToLLVM::speculate):
(JSC::FTL::LowerDFGToLLVM::speculateMachineInt):
* interpreter/Register.h:
(JSC::Register::unboxedStrictInt52):
* runtime/Arguments.cpp:
(JSC::Arguments::tearOff):
* runtime/Arguments.h:



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@156677 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 1367e453
......@@ -72,6 +72,7 @@ set(JavaScriptCore_SOURCES
bytecode/StructureStubClearingWatchpoint.cpp
bytecode/StructureStubInfo.cpp
bytecode/UnlinkedCodeBlock.cpp
bytecode/ValueRecovery.cpp
bytecode/Watchpoint.cpp
bytecompiler/BytecodeGenerator.cpp
......
2013-09-30 Filip Pizlo <fpizlo@apple.com>
Get rid of the AlreadyInJSStack recoveries since they are totally redundant with the DisplacedInJSStack recoveries
https://bugs.webkit.org/show_bug.cgi?id=122065
Reviewed by Mark Hahnenberg.
This mostly just kills a bunch of code.
But incidentaly while killing that code, I uncovered a bug in our FTL OSR entrypoint
creation phase. The phase inserts a sequence of SetLocal(ExtractOSREntryLocal) nodes.
If we hoist some type check into the local, then we might inject a conversion node
between the ExtractOSREntryLocal and the SetLocal - for example we might put in a
Int32ToDouble node. But currently the FixupPhase will make all conversion nodes placed
on an edge of a SetLocal use forward exit. This then confuses the OSR exit machinery.
When OSR exit sees a forward exit, it tries to "roll forward" execution from the exiting
node to the first node that has a different CodeOrigin. This only works if the nodes
after the forward exit are MovHints or other tnings that the OSR exit compiler can
forward-execute. But here, it will see a bunch of SetLocal and ExtractOSREntryLocal
nodes for the same bytecode index. Two possible solutions exist. We could teach the
forward-execution logic how to deal with multiple SetLocals and ExtractOSREntryLocals.
This would be a lot of complexity; right now it just needs to deal with exactly one
SetLocal-like operation. The alternative is to make sure that the conversion node that
we inject ends up exiting *backward* rather than forward.
But making the conversion nodes exit backward is somewhat tricky. Before this patch,
conversion nodes always exit forward for SetLocals and backwards otherwise. It turns out
that the solution is to rationalize how we choose the speculation direciton for a
conversion node. The conversion node's speculation direction should be the same as the
speculation direction of the node for which it is doing a conversion. Since SetLocal's
already exit forward by default, this policy preserves our previous behavior. But it
also allows the OSR entrypoint creation phase to make its SetLocals exit backward
instead.
Of course, if the SetLocal(ExtractOSREntryLocal) sequences exit backward, then we need
to make sure that the OSR exit machine knows that the local variables are indeed live.
Consider that if we have:
a: ExtractOSREntryLocal(loc1)
b: SetLocal(@a, loc1)
c: ExtractOSRentryLocal(loc2)
d: SetLocal(@c, loc2)
Without additional magic, the exit at @b will think that loc2 is dead and the OSR exit
compiler will clobber loc2 with Undefined. So we need to make sure that we actually
emit code like:
a: ExtractOSREntryLocal(loc1)
b: ExtractOSREntryLocal(loc2)
c: SetLocal(@a, loc1)
d: SetLocal(@b, loc2)
e: SetLocal(@a, loc1)
f: SetLocal(@b, loc2)
* CMakeLists.txt:
* GNUmakefile.list.am:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
* JavaScriptCore.xcodeproj/project.pbxproj:
* Target.pri:
* bytecode/CodeOrigin.h:
* bytecode/ValueRecovery.cpp: Added.
(JSC::ValueRecovery::recover):
(JSC::ValueRecovery::dumpInContext):
(JSC::ValueRecovery::dump):
* bytecode/ValueRecovery.h:
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupSetLocalsInBlock):
(JSC::DFG::FixupPhase::fixEdge):
* dfg/DFGJITCode.cpp:
(JSC::DFG::JITCode::reconstruct):
* dfg/DFGNode.h:
(JSC::DFG::Node::speculationDirection):
(JSC::DFG::Node::setSpeculationDirection):
* dfg/DFGOSREntrypointCreationPhase.cpp:
(JSC::DFG::OSREntrypointCreationPhase::run):
* dfg/DFGOSRExitCompiler32_64.cpp:
(JSC::DFG::OSRExitCompiler::compileExit):
* dfg/DFGOSRExitCompiler64.cpp:
(JSC::DFG::OSRExitCompiler::compileExit):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileInlineStart):
(JSC::DFG::SpeculativeJIT::computeValueRecoveryFor):
* dfg/DFGSpeculativeJIT.h:
(JSC::DFG::SpeculativeJIT::computeValueRecoveryFor):
* dfg/DFGValueSource.h:
(JSC::DFG::ValueSource::valueRecovery):
* dfg/DFGVariableEventStream.cpp:
(JSC::DFG::VariableEventStream::reconstruct):
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::LowerDFGToLLVM::speculate):
(JSC::FTL::LowerDFGToLLVM::speculateMachineInt):
* interpreter/Register.h:
(JSC::Register::unboxedStrictInt52):
* runtime/Arguments.cpp:
(JSC::Arguments::tearOff):
* runtime/Arguments.h:
2013-09-30 Alex Christensen <alex.christensen@flexsim.com>
Win64 compile fix after r1256490.
......@@ -167,6 +167,7 @@ javascriptcore_sources += \
Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp \
Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h \
Source/JavaScriptCore/bytecode/ValueProfile.h \
Source/JavaScriptCore/bytecode/ValueRecovery.cpp \
Source/JavaScriptCore/bytecode/ValueRecovery.h \
Source/JavaScriptCore/bytecode/VirtualRegister.h \
Source/JavaScriptCore/bytecode/Watchpoint.cpp \
......
......@@ -320,6 +320,7 @@
<ClCompile Include="..\bytecode\StructureStubClearingWatchpoint.cpp" />
<ClCompile Include="..\bytecode\StructureStubInfo.cpp" />
<ClCompile Include="..\bytecode\UnlinkedCodeBlock.cpp" />
<ClCompile Include="..\bytecode\ValueRecovery.cpp" />
<ClCompile Include="..\bytecode\Watchpoint.cpp" />
<ClCompile Include="..\bytecompiler\BytecodeGenerator.cpp" />
<ClCompile Include="..\bytecompiler\NodesCodegen.cpp" />
......
......@@ -118,8 +118,6 @@
0F24E54217EA9F5900ABB217 /* CCallHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F24E53D17EA9F5900ABB217 /* CCallHelpers.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F24E54317EA9F5900ABB217 /* FPRInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F24E53E17EA9F5900ABB217 /* FPRInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F24E54417EA9F5900ABB217 /* GPRInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F24E53F17EA9F5900ABB217 /* GPRInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F24E55517F0B71C00ABB217 /* InlineCallFrameSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F24E55317F0B71C00ABB217 /* InlineCallFrameSet.cpp */; };
0F24E55617F0B71C00ABB217 /* InlineCallFrameSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F24E55417F0B71C00ABB217 /* InlineCallFrameSet.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F24E54C17EE274900ABB217 /* JITOperations.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F24E54517EE274900ABB217 /* JITOperations.cpp */; };
0F24E54D17EE274900ABB217 /* JITOperations.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F24E54617EE274900ABB217 /* JITOperations.h */; };
0F24E54E17EE274900ABB217 /* JITOperationWrappers.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F24E54717EE274900ABB217 /* JITOperationWrappers.h */; };
......@@ -127,6 +125,9 @@
0F24E55017EE274900ABB217 /* Repatch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F24E54917EE274900ABB217 /* Repatch.cpp */; };
0F24E55117EE274900ABB217 /* Repatch.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F24E54A17EE274900ABB217 /* Repatch.h */; };
0F24E55217EE274900ABB217 /* ScratchRegisterAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F24E54B17EE274900ABB217 /* ScratchRegisterAllocator.h */; };
0F24E55517F0B71C00ABB217 /* InlineCallFrameSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F24E55317F0B71C00ABB217 /* InlineCallFrameSet.cpp */; };
0F24E55617F0B71C00ABB217 /* InlineCallFrameSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F24E55417F0B71C00ABB217 /* InlineCallFrameSet.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F24E55817F74EDB00ABB217 /* ValueRecovery.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F24E55717F74EDB00ABB217 /* ValueRecovery.cpp */; };
0F256C361627B0AD007F2783 /* DFGCallArrayAllocatorSlowPathGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F256C341627B0AA007F2783 /* DFGCallArrayAllocatorSlowPathGenerator.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F2B66AC17B6B53F00A7AE3F /* GCIncomingRefCounted.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2B66A817B6B53D00A7AE3F /* GCIncomingRefCounted.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F2B66AD17B6B54500A7AE3F /* GCIncomingRefCountedInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2B66A917B6B53D00A7AE3F /* GCIncomingRefCountedInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
......@@ -1322,8 +1323,6 @@
0F24E53D17EA9F5900ABB217 /* CCallHelpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCallHelpers.h; sourceTree = "<group>"; };
0F24E53E17EA9F5900ABB217 /* FPRInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FPRInfo.h; sourceTree = "<group>"; };
0F24E53F17EA9F5900ABB217 /* GPRInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPRInfo.h; sourceTree = "<group>"; };
0F24E55317F0B71C00ABB217 /* InlineCallFrameSet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InlineCallFrameSet.cpp; sourceTree = "<group>"; };
0F24E55417F0B71C00ABB217 /* InlineCallFrameSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InlineCallFrameSet.h; sourceTree = "<group>"; };
0F24E54517EE274900ABB217 /* JITOperations.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITOperations.cpp; sourceTree = "<group>"; };
0F24E54617EE274900ABB217 /* JITOperations.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITOperations.h; sourceTree = "<group>"; };
0F24E54717EE274900ABB217 /* JITOperationWrappers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITOperationWrappers.h; sourceTree = "<group>"; };
......@@ -1331,6 +1330,9 @@
0F24E54917EE274900ABB217 /* Repatch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Repatch.cpp; sourceTree = "<group>"; };
0F24E54A17EE274900ABB217 /* Repatch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Repatch.h; sourceTree = "<group>"; };
0F24E54B17EE274900ABB217 /* ScratchRegisterAllocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScratchRegisterAllocator.h; sourceTree = "<group>"; };
0F24E55317F0B71C00ABB217 /* InlineCallFrameSet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InlineCallFrameSet.cpp; sourceTree = "<group>"; };
0F24E55417F0B71C00ABB217 /* InlineCallFrameSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InlineCallFrameSet.h; sourceTree = "<group>"; };
0F24E55717F74EDB00ABB217 /* ValueRecovery.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ValueRecovery.cpp; sourceTree = "<group>"; };
0F256C341627B0AA007F2783 /* DFGCallArrayAllocatorSlowPathGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGCallArrayAllocatorSlowPathGenerator.h; path = dfg/DFGCallArrayAllocatorSlowPathGenerator.h; sourceTree = "<group>"; };
0F2B66A817B6B53D00A7AE3F /* GCIncomingRefCounted.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GCIncomingRefCounted.h; sourceTree = "<group>"; };
0F2B66A917B6B53D00A7AE3F /* GCIncomingRefCountedInlines.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GCIncomingRefCountedInlines.h; sourceTree = "<group>"; };
......@@ -3764,8 +3766,6 @@
969A078F0ED1D3AE00F1F681 /* bytecode */ = {
isa = PBXGroup;
children = (
0F24E55317F0B71C00ABB217 /* InlineCallFrameSet.cpp */,
0F24E55417F0B71C00ABB217 /* InlineCallFrameSet.h */,
0F8335B41639C1E3001443B5 /* ArrayAllocationProfile.cpp */,
0F8335B51639C1E3001443B5 /* ArrayAllocationProfile.h */,
0F63945115D07051006A597C /* ArrayProfile.cpp */,
......@@ -3800,6 +3800,8 @@
0F93329514CA7DC10085F3C6 /* GetByIdStatus.cpp */,
0F93329614CA7DC10085F3C6 /* GetByIdStatus.h */,
0F0B83A814BCF55E00885B4F /* HandlerInfo.h */,
0F24E55317F0B71C00ABB217 /* InlineCallFrameSet.cpp */,
0F24E55417F0B71C00ABB217 /* InlineCallFrameSet.h */,
969A07930ED1D3AE00F1F681 /* Instruction.h */,
BCFD8C900EEB2EE700283848 /* JumpTable.cpp */,
BCFD8C910EEB2EE700283848 /* JumpTable.h */,
......@@ -3838,6 +3840,7 @@
A79E781E15EECBA80047C855 /* UnlinkedCodeBlock.cpp */,
A79E781F15EECBA80047C855 /* UnlinkedCodeBlock.h */,
0F963B3613FC6FDE0002D9B2 /* ValueProfile.h */,
0F24E55717F74EDB00ABB217 /* ValueRecovery.cpp */,
0F426A451460CBAB00131F8F /* ValueRecovery.h */,
0F426A461460CBAB00131F8F /* VirtualRegister.h */,
0F919D2215853CDE004A4E7D /* Watchpoint.cpp */,
......@@ -5276,6 +5279,7 @@
14E84FA014EE1ACC00D6D5D4 /* WeakSet.cpp in Sources */,
0F6E5C191724AF3D005C574F /* WebKitLLVMLibraryAnchor.cpp in Sources */,
0FC8150B14043C0E00CFA603 /* WriteBarrierSupport.cpp in Sources */,
0F24E55817F74EDB00ABB217 /* ValueRecovery.cpp in Sources */,
A7E5AB3A1799E4B200D2833D /* X86Disassembler.cpp in Sources */,
863C6D9C1521111A00585E4E /* YarrCanonicalizeUCS2.cpp in Sources */,
86704B8412DBA33700A9FE7B /* YarrInterpreter.cpp in Sources */,
......
......@@ -80,6 +80,7 @@ SOURCES += \
bytecode/StructureStubClearingWatchpoint.cpp \
bytecode/StructureStubInfo.cpp \
bytecode/UnlinkedCodeBlock.cpp \
bytecode/ValueRecovery.cpp \
bytecode/Watchpoint.cpp \
bytecompiler/BytecodeGenerator.cpp \
bytecompiler/NodesCodegen.cpp \
......
/*
* Copyright (C) 2011, 2013 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 "ValueRecovery.h"
#include "CodeBlock.h"
#include "Operations.h"
namespace JSC {
JSValue ValueRecovery::recover(ExecState* exec) const
{
switch (technique()) {
case DisplacedInJSStack:
return exec->r(virtualRegister().offset()).jsValue();
case Int32DisplacedInJSStack:
return jsNumber(exec->r(virtualRegister().offset()).unboxedInt32());
case Int52DisplacedInJSStack:
return jsNumber(exec->r(virtualRegister().offset()).unboxedInt52());
case StrictInt52DisplacedInJSStack:
return jsNumber(exec->r(virtualRegister().offset()).unboxedStrictInt52());
case DoubleDisplacedInJSStack:
return jsNumber(exec->r(virtualRegister().offset()).unboxedDouble());
case CellDisplacedInJSStack:
return exec->r(virtualRegister().offset()).unboxedCell();
case BooleanDisplacedInJSStack:
#if USE(JSVALUE64)
return exec->r(virtualRegister().offset()).jsValue();
#else
return jsBoolean(exec->r(virtualRegister().offset()).unboxedBoolean());
#endif
case Constant:
return constant();
default:
RELEASE_ASSERT_NOT_REACHED();
return JSValue();
}
}
void ValueRecovery::dumpInContext(PrintStream& out, DumpContext* context) const
{
switch (technique()) {
case InGPR:
out.print(gpr());
return;
case UnboxedInt32InGPR:
out.print("int32(", gpr(), ")");
return;
case UnboxedInt52InGPR:
out.print("int52(", gpr(), ")");
return;
case UnboxedStrictInt52InGPR:
out.print("strictInt52(", gpr(), ")");
return;
case UnboxedBooleanInGPR:
out.print("bool(", gpr(), ")");
return;
case UnboxedCellInGPR:
out.print("cell(", gpr(), ")");
return;
case UInt32InGPR:
out.print("uint32(", gpr(), ")");
return;
case InFPR:
out.print(fpr());
return;
#if USE(JSVALUE32_64)
case InPair:
out.print("pair(", tagGPR(), ", ", payloadGPR(), ")");
return;
#endif
case DisplacedInJSStack:
out.printf("*%d", virtualRegister().offset());
return;
case Int32DisplacedInJSStack:
out.printf("*int32(%d)", virtualRegister().offset());
return;
case Int52DisplacedInJSStack:
out.printf("*int52(%d)", virtualRegister().offset());
return;
case StrictInt52DisplacedInJSStack:
out.printf("*strictInt52(%d)", virtualRegister().offset());
return;
case DoubleDisplacedInJSStack:
out.printf("*double(%d)", virtualRegister().offset());
return;
case CellDisplacedInJSStack:
out.printf("*cell(%d)", virtualRegister().offset());
return;
case BooleanDisplacedInJSStack:
out.printf("*bool(%d)", virtualRegister().offset());
return;
case ArgumentsThatWereNotCreated:
out.printf("arguments");
return;
case Constant:
out.print("[", inContext(constant(), context), "]");
return;
case DontKnow:
out.printf("!");
return;
}
RELEASE_ASSERT_NOT_REACHED();
}
void ValueRecovery::dump(PrintStream& out) const
{
dumpInContext(out, 0);
}
} // namespace JSC
/*
* Copyright (C) 2011 Apple Inc. All rights reserved.
* Copyright (C) 2011, 2013 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
......@@ -42,14 +42,6 @@ struct DumpContext;
// Describes how to recover a given bytecode virtual register at a given
// code point.
enum ValueRecoveryTechnique {
// It's already in the stack at the right location.
AlreadyInJSStack,
// It's already in the stack but unboxed.
AlreadyInJSStackAsUnboxedInt32,
AlreadyInJSStackAsUnboxedInt52,
AlreadyInJSStackAsUnboxedCell,
AlreadyInJSStackAsUnboxedBoolean,
AlreadyInJSStackAsUnboxedDouble,
// It's in a register.
InGPR,
UnboxedInt32InGPR,
......@@ -89,48 +81,6 @@ public:
bool isSet() const { return m_technique != DontKnow; }
bool operator!() const { return !isSet(); }
static ValueRecovery alreadyInJSStack()
{
ValueRecovery result;
result.m_technique = AlreadyInJSStack;
return result;
}
static ValueRecovery alreadyInJSStackAsUnboxedInt32()
{
ValueRecovery result;
result.m_technique = AlreadyInJSStackAsUnboxedInt32;
return result;
}
static ValueRecovery alreadyInJSStackAsUnboxedInt52()
{
ValueRecovery result;
result.m_technique = AlreadyInJSStackAsUnboxedInt52;
return result;
}
static ValueRecovery alreadyInJSStackAsUnboxedCell()
{
ValueRecovery result;
result.m_technique = AlreadyInJSStackAsUnboxedCell;
return result;
}
static ValueRecovery alreadyInJSStackAsUnboxedBoolean()
{
ValueRecovery result;
result.m_technique = AlreadyInJSStackAsUnboxedBoolean;
return result;
}
static ValueRecovery alreadyInJSStackAsUnboxedDouble()
{
ValueRecovery result;
result.m_technique = AlreadyInJSStackAsUnboxedDouble;
return result;
}
static ValueRecovery inGPR(MacroAssembler::RegisterID gpr, DataFormat dataFormat)
{
ASSERT(dataFormat != DataFormatNone);
......@@ -256,21 +206,6 @@ public:
}
}
bool isAlreadyInJSStack() const
{
switch (technique()) {
case AlreadyInJSStack:
case AlreadyInJSStackAsUnboxedInt32:
case AlreadyInJSStackAsUnboxedInt52:
case AlreadyInJSStackAsUnboxedCell:
case AlreadyInJSStackAsUnboxedBoolean:
case AlreadyInJSStackAsUnboxedDouble:
return true;
default:
return false;
}
}
MacroAssembler::RegisterID gpr() const
{
ASSERT(m_technique == InGPR || m_technique == UnboxedInt32InGPR || m_technique == UnboxedBooleanInGPR || m_technique == UInt32InGPR || m_technique == UnboxedInt52InGPR || m_technique == UnboxedStrictInt52InGPR || m_technique == UnboxedCellInGPR);
......@@ -309,95 +244,11 @@ public:
return JSValue::decode(m_source.constant);
}
void dumpInContext(PrintStream& out, DumpContext* context) const
{
switch (technique()) {
case AlreadyInJSStack:
out.printf("-");
return;
case AlreadyInJSStackAsUnboxedInt32:
out.printf("(int32)");
return;
case AlreadyInJSStackAsUnboxedInt52:
out.printf("(int52)");
return;
case AlreadyInJSStackAsUnboxedCell:
out.printf("(cell)");
return;
case AlreadyInJSStackAsUnboxedBoolean:
out.printf("(bool)");
return;
case AlreadyInJSStackAsUnboxedDouble:
out.printf("(double)");
return;
case InGPR:
out.print(gpr());
return;
case UnboxedInt32InGPR:
out.print("int32(", gpr(), ")");
return;
case UnboxedInt52InGPR:
out.print("int52(", gpr(), ")");
return;
case UnboxedStrictInt52InGPR:
out.print("strictInt52(", gpr(), ")");
return;
case UnboxedBooleanInGPR:
out.print("bool(", gpr(), ")");
return;
case UnboxedCellInGPR:
out.print("cell(", gpr(), ")");
return;
case UInt32InGPR:
out.print("uint32(", gpr(), ")");
return;
case InFPR:
out.print(fpr());
return;
#if USE(JSVALUE32_64)
case InPair:
out.print("pair(", tagGPR(), ", ", payloadGPR(), ")");
return;
#endif
case DisplacedInJSStack:
out.printf("*%d", virtualRegister().offset());
return;
case Int32DisplacedInJSStack:
out.printf("*int32(%d)", virtualRegister().offset());
return;
case Int52DisplacedInJSStack:
out.printf("*int52(%d)", virtualRegister().offset());
return;
case StrictInt52DisplacedInJSStack:
out.printf("*strictInt52(%d)", virtualRegister().offset());
return;
case DoubleDisplacedInJSStack:
out.printf("*double(%d)", virtualRegister().offset());
return;
case CellDisplacedInJSStack:
out.printf("*cell(%d)", virtualRegister().offset());
return;
case BooleanDisplacedInJSStack:
out.printf("*bool(%d)", virtualRegister().offset());
return;
case ArgumentsThatWereNotCreated:
out.printf("arguments");
return;
case Constant:
out.print("[", inContext(constant(), context), "]");
return;
case DontKnow:
out.printf("!");
return;
}
RELEASE_ASSERT_NOT_REACHED();
}
void dump(PrintStream& out) const
{
dumpInContext(out, 0);
}
JSValue recover(ExecState*) const;
void dumpInContext(PrintStream& out, DumpContext* context) const;
void dump(PrintStream& out) const;
private:
ValueRecoveryTechnique m_technique;
union {
......
......@@ -1219,7 +1219,7 @@ private:
case FlushedJSValue:
break;
case FlushedDouble:
fixEdge<NumberUse>(node->child1(), ForwardSpeculation);
fixEdge<NumberUse>(node->child1());
break;
case FlushedInt32:
fixEdge<Int32Use>(node->child1());
......@@ -1407,11 +1407,11 @@ private:
// edge, you either call fixEdge() or perform the equivalent functionality
// yourself. Obviously, you should have a really good reason if you do the latter.
template<UseKind useKind>
void fixEdge(Edge& edge, SpeculationDirection direction = BackwardSpeculation)
void fixEdge(Edge& edge)
{
if (isDouble(useKind)) {
if (edge->shouldSpeculateInt32ForArithmetic()) {
injectInt32ToDoubleNode(edge, useKind, direction);
injectInt32ToDoubleNode(edge, useKind, m_currentNode->speculationDirection());
return;
}
......@@ -1424,6 +1424,7 @@ private:
Node* result = m_insertionSet.insertNode(
m_indexInBlock, SpecInt52AsDouble, Int52ToDouble,
m_currentNode->codeOrigin, Edge(edge.node(), NumberUse));
result->setSpeculationDirection(m_currentNode->speculationDirection());
edge = Edge(result, useKind);
return;
}
......@@ -1477,6 +1478,7 @@ private:
Node* result = m_insertionSet.insertNode(
m_indexInBlock, SpecInt52, Int52ToValue,
m_currentNode->codeOrigin, Edge(edge.node(), UntypedUse));
result->setSpeculationDirection(m_currentNode->speculationDirection());
edge = Edge(result, useKind);
return;
}
......
......@@ -92,31 +92,7 @@ void JITCode::reconstruct(
continue;
}
ValueRecovery recovery = recoveries[i];
JSValue value;
switch (recovery.technique()) {
case AlreadyInJSStack:
case AlreadyInJSStackAsUnboxedCell:
case AlreadyInJSStackAsUnboxedBoolean:
value = exec->r(operand).jsValue();
break;
case AlreadyInJSStackAsUnboxedInt32:
value = jsNumber(exec->r(operand).unboxedInt32());
break;
case AlreadyInJSStackAsUnboxedInt52:
value = jsNumber(exec->r(operand).unboxedInt52());
break;
case AlreadyInJSStackAsUnboxedDouble:
value = jsDoubleNumber(exec->r(operand).unboxedDouble());
break;
case Constant:
value = recovery.constant();
break;
default:
RELEASE_ASSERT_NOT_REACHED();
break;
}
result[i] = value;
result[i] = recoveries[i].recover(exec);
}
}
......
......@@ -274,6 +274,26 @@ struct Node {
return filterFlags(~flags);
}
SpeculationDirection speculationDirection()
{
if (flags() & NodeExitsForward)
return ForwardSpeculation;
return BackwardSpeculation;
}
void setSpeculationDirection(SpeculationDirection direction)
{
switch (direction) {
case ForwardSpeculation:
mergeFlags(NodeExitsForward);
return;
case BackwardSpeculation:
clearFlags(NodeExitsForward);
return;
}
RELEASE_ASSERT_NOT_REACHED();