ValueRecovery should be moved out of the DFG JIT
authorfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 3 Nov 2011 06:55:29 +0000 (06:55 +0000)
committerfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 3 Nov 2011 06:55:29 +0000 (06:55 +0000)
https://bugs.webkit.org/show_bug.cgi?id=71439

Reviewed by Oliver Hunt.

* JavaScriptCore.xcodeproj/project.pbxproj:
* bytecode/DataFormat.h: Added.
(JSC::dataFormatToString):
(JSC::needDataFormatConversion):
(JSC::isJSFormat):
(JSC::isJSInteger):
(JSC::isJSDouble):
(JSC::isJSCell):
(JSC::isJSBoolean):
* bytecode/ValueRecovery.h: Added.
(JSC::ValueRecovery::ValueRecovery):
(JSC::ValueRecovery::alreadyInRegisterFile):
(JSC::ValueRecovery::alreadyInRegisterFileAsUnboxedInt32):
(JSC::ValueRecovery::alreadyInRegisterFileAsUnboxedCell):
(JSC::ValueRecovery::alreadyInRegisterFileAsUnboxedBoolean):
(JSC::ValueRecovery::inGPR):
(JSC::ValueRecovery::inPair):
(JSC::ValueRecovery::inFPR):
(JSC::ValueRecovery::displacedInRegisterFile):
(JSC::ValueRecovery::constant):
(JSC::ValueRecovery::technique):
(JSC::ValueRecovery::isInRegisters):
(JSC::ValueRecovery::gpr):
(JSC::ValueRecovery::tagGPR):
(JSC::ValueRecovery::payloadGPR):
(JSC::ValueRecovery::fpr):
(JSC::ValueRecovery::virtualRegister):
(JSC::ValueRecovery::dump):
* bytecode/VirtualRegister.h: Added.
* dfg/DFGGenerationInfo.h:
(JSC::DFG::GenerationInfo::isJSFormat):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::ValueSource::dump):
* dfg/DFGSpeculativeJIT.h:
* dfg/DFGVariableAccessData.h:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@99144 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/bytecode/DataFormat.h [new file with mode: 0644]
Source/JavaScriptCore/bytecode/ValueRecovery.h [new file with mode: 0644]
Source/JavaScriptCore/bytecode/VirtualRegister.h [new file with mode: 0644]
Source/JavaScriptCore/dfg/DFGGenerationInfo.h
Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
Source/JavaScriptCore/dfg/DFGVariableAccessData.h

index 329bae2bcbaba4b0d41f54b3a4d9f1b461260a6e..d6dd1e5fcf73f937b30ff8bf1fd08c61a96e880c 100644 (file)
@@ -1,3 +1,46 @@
+2011-11-02  Filip Pizlo  <fpizlo@apple.com>
+
+        ValueRecovery should be moved out of the DFG JIT
+        https://bugs.webkit.org/show_bug.cgi?id=71439
+
+        Reviewed by Oliver Hunt.
+
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * bytecode/DataFormat.h: Added.
+        (JSC::dataFormatToString):
+        (JSC::needDataFormatConversion):
+        (JSC::isJSFormat):
+        (JSC::isJSInteger):
+        (JSC::isJSDouble):
+        (JSC::isJSCell):
+        (JSC::isJSBoolean):
+        * bytecode/ValueRecovery.h: Added.
+        (JSC::ValueRecovery::ValueRecovery):
+        (JSC::ValueRecovery::alreadyInRegisterFile):
+        (JSC::ValueRecovery::alreadyInRegisterFileAsUnboxedInt32):
+        (JSC::ValueRecovery::alreadyInRegisterFileAsUnboxedCell):
+        (JSC::ValueRecovery::alreadyInRegisterFileAsUnboxedBoolean):
+        (JSC::ValueRecovery::inGPR):
+        (JSC::ValueRecovery::inPair):
+        (JSC::ValueRecovery::inFPR):
+        (JSC::ValueRecovery::displacedInRegisterFile):
+        (JSC::ValueRecovery::constant):
+        (JSC::ValueRecovery::technique):
+        (JSC::ValueRecovery::isInRegisters):
+        (JSC::ValueRecovery::gpr):
+        (JSC::ValueRecovery::tagGPR):
+        (JSC::ValueRecovery::payloadGPR):
+        (JSC::ValueRecovery::fpr):
+        (JSC::ValueRecovery::virtualRegister):
+        (JSC::ValueRecovery::dump):
+        * bytecode/VirtualRegister.h: Added.
+        * dfg/DFGGenerationInfo.h:
+        (JSC::DFG::GenerationInfo::isJSFormat):
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::ValueSource::dump):
+        * dfg/DFGSpeculativeJIT.h:
+        * dfg/DFGVariableAccessData.h:
+
 2011-11-02  Sam Weinig  <sam@webkit.org>
 
         Object.getOwnPropertyDescriptor() does not retrieve the getter/setter from a property on the window that has been overridden with a getter/setter
index 1ca53a5b2616cf2067db7ef7932907da6c817fd0..d8a7c00d8f8742d47675287210945d662d686bd3 100644 (file)
@@ -50,6 +50,9 @@
                0BF28A2911A33DC300638F84 /* SizeLimits.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0BF28A2811A33DC300638F84 /* SizeLimits.cpp */; };
                0F16D726142C39C000CF784A /* BitVector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F16D724142C39A200CF784A /* BitVector.cpp */; };
                0F242DA713F3B1E8007ADD4C /* WeakReferenceHarvester.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F242DA513F3B1BB007ADD4C /* WeakReferenceHarvester.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               0F426A481460CBB300131F8F /* ValueRecovery.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F426A451460CBAB00131F8F /* ValueRecovery.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               0F426A491460CBB700131F8F /* VirtualRegister.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F426A461460CBAB00131F8F /* VirtualRegister.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               0F426A4B1460CD6E00131F8F /* DataFormat.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F426A4A1460CD6B00131F8F /* DataFormat.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F620174143FCD330068B77C /* DFGVariableAccessData.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F620172143FCD2F0068B77C /* DFGVariableAccessData.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F620175143FCD370068B77C /* DFGOperands.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F620171143FCD2F0068B77C /* DFGOperands.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F620176143FCD3B0068B77C /* DFGBasicBlock.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F620170143FCD2F0068B77C /* DFGBasicBlock.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0BF28A2811A33DC300638F84 /* SizeLimits.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SizeLimits.cpp; sourceTree = "<group>"; };
                0F16D724142C39A200CF784A /* BitVector.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BitVector.cpp; sourceTree = "<group>"; };
                0F242DA513F3B1BB007ADD4C /* WeakReferenceHarvester.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WeakReferenceHarvester.h; sourceTree = "<group>"; };
+               0F426A451460CBAB00131F8F /* ValueRecovery.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ValueRecovery.h; sourceTree = "<group>"; };
+               0F426A461460CBAB00131F8F /* VirtualRegister.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VirtualRegister.h; sourceTree = "<group>"; };
+               0F426A4A1460CD6B00131F8F /* DataFormat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DataFormat.h; sourceTree = "<group>"; };
                0F62016D143FCD2F0068B77C /* DFGAbstractState.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGAbstractState.cpp; path = dfg/DFGAbstractState.cpp; sourceTree = "<group>"; };
                0F62016E143FCD2F0068B77C /* DFGAbstractState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGAbstractState.h; path = dfg/DFGAbstractState.h; sourceTree = "<group>"; };
                0F62016F143FCD2F0068B77C /* DFGAbstractValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGAbstractValue.h; path = dfg/DFGAbstractValue.h; sourceTree = "<group>"; };
                969A078F0ED1D3AE00F1F681 /* bytecode */ = {
                        isa = PBXGroup;
                        children = (
+                               0F426A4A1460CD6B00131F8F /* DataFormat.h */,
+                               0F426A451460CBAB00131F8F /* ValueRecovery.h */,
+                               0F426A461460CBAB00131F8F /* VirtualRegister.h */,
                                0FBD7E671447998F00481315 /* CodeOrigin.h */,
                                0FD82E8E14207A5100179C94 /* ValueProfile.cpp */,
                                0FD82E84141F3FDA00179C94 /* PredictedType.cpp */,
                                0F620178143FCD440068B77C /* DFGAbstractState.h in Headers */,
                                0FBD7E691447999600481315 /* CodeOrigin.h in Headers */,
                                65303D641447B9E100D3F904 /* ParserTokens.h in Headers */,
+                               0F426A481460CBB300131F8F /* ValueRecovery.h in Headers */,
+                               0F426A491460CBB700131F8F /* VirtualRegister.h in Headers */,
+                               0F426A4B1460CD6E00131F8F /* DataFormat.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
diff --git a/Source/JavaScriptCore/bytecode/DataFormat.h b/Source/JavaScriptCore/bytecode/DataFormat.h
new file mode 100644 (file)
index 0000000..b78a6e8
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2011 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 DataFormat_h
+#define DataFormat_h
+
+#include <wtf/Assertions.h>
+
+namespace JSC {
+
+// === DataFormat ===
+//
+// This enum tracks the current representation in which a value is being held.
+// Values may be unboxed primitives (int32, double, or cell), or boxed as a JSValue.
+// For boxed values, we may know the type of boxing that has taken place.
+// (May also need bool, array, object, string types!)
+enum DataFormat {
+    DataFormatNone = 0,
+    DataFormatInteger = 1,
+    DataFormatDouble = 2,
+    DataFormatBoolean = 3,
+    DataFormatCell = 4,
+    DataFormatStorage = 5,
+    DataFormatJS = 8,
+    DataFormatJSInteger = DataFormatJS | DataFormatInteger,
+    DataFormatJSDouble = DataFormatJS | DataFormatDouble,
+    DataFormatJSCell = DataFormatJS | DataFormatCell,
+    DataFormatJSBoolean = DataFormatJS | DataFormatBoolean
+};
+
+#ifndef NDEBUG
+inline const char* dataFormatToString(DataFormat dataFormat)
+{
+    switch (dataFormat) {
+    case DataFormatNone:
+        return "None";
+    case DataFormatInteger:
+        return "Integer";
+    case DataFormatDouble:
+        return "Double";
+    case DataFormatCell:
+        return "Cell";
+    case DataFormatBoolean:
+        return "Boolean";
+    case DataFormatStorage:
+        return "Storage";
+    case DataFormatJS:
+        return "JS";
+    case DataFormatJSInteger:
+        return "JSInteger";
+    case DataFormatJSDouble:
+        return "JSDouble";
+    case DataFormatJSCell:
+        return "JSCell";
+    case DataFormatJSBoolean:
+        return "JSBoolean";
+    default:
+        return "Unknown";
+    }
+}
+#endif
+
+#if USE(JSVALUE64)
+inline bool needDataFormatConversion(DataFormat from, DataFormat to)
+{
+    ASSERT(from != DataFormatNone);
+    ASSERT(to != DataFormatNone);
+    switch (from) {
+    case DataFormatInteger:
+    case DataFormatDouble:
+        return to != from;
+    case DataFormatCell:
+    case DataFormatJS:
+    case DataFormatJSInteger:
+    case DataFormatJSDouble:
+    case DataFormatJSCell:
+    case DataFormatJSBoolean:
+        switch (to) {
+        case DataFormatInteger:
+        case DataFormatDouble:
+            return true;
+        case DataFormatCell:
+        case DataFormatJS:
+        case DataFormatJSInteger:
+        case DataFormatJSDouble:
+        case DataFormatJSCell:
+        case DataFormatJSBoolean:
+            return false;
+        default:
+            // This captures DataFormatBoolean, which is currently unused.
+            ASSERT_NOT_REACHED();
+        }
+    case DataFormatStorage:
+        ASSERT(to == DataFormatStorage);
+        return false;
+    default:
+        // This captures DataFormatBoolean, which is currently unused.
+        ASSERT_NOT_REACHED();
+    }
+    return true;
+}
+
+#elif USE(JSVALUE32_64)
+inline bool needDataFormatConversion(DataFormat from, DataFormat to)
+{
+    ASSERT(from != DataFormatNone);
+    ASSERT(to != DataFormatNone);
+    switch (from) {
+    case DataFormatInteger:
+    case DataFormatCell:
+    case DataFormatBoolean:
+        return ((to & DataFormatJS) || to == DataFormatDouble);
+    case DataFormatDouble:
+    case DataFormatJSDouble:
+        return (to != DataFormatDouble && to != DataFormatJSDouble);
+    case DataFormatJS:
+    case DataFormatJSInteger:
+    case DataFormatJSCell:
+    case DataFormatJSBoolean:
+        return (!(to & DataFormatJS) || to == DataFormatJSDouble);
+    case DataFormatStorage:
+        ASSERT(to == DataFormatStorage);
+        return false;
+    default:
+        ASSERT_NOT_REACHED();
+    }
+    return true;
+}
+#endif
+
+inline bool isJSFormat(DataFormat format, DataFormat expectedFormat)
+{
+    ASSERT(expectedFormat & DataFormatJS);
+    return (format | DataFormatJS) == expectedFormat;
+}
+
+inline bool isJSInteger(DataFormat format)
+{
+    return isJSFormat(format, DataFormatJSInteger);
+}
+
+inline bool isJSDouble(DataFormat format)
+{
+    return isJSFormat(format, DataFormatJSDouble);
+}
+
+inline bool isJSCell(DataFormat format)
+{
+    return isJSFormat(format, DataFormatJSCell);
+}
+
+inline bool isJSBoolean(DataFormat format)
+{
+    return isJSFormat(format, DataFormatJSBoolean);
+}
+
+}
+
+#endif // DataFormat_h
diff --git a/Source/JavaScriptCore/bytecode/ValueRecovery.h b/Source/JavaScriptCore/bytecode/ValueRecovery.h
new file mode 100644 (file)
index 0000000..13c8a38
--- /dev/null
@@ -0,0 +1,294 @@
+/*
+ * Copyright (C) 2011 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 ValueRecovery_h
+#define ValueRecovery_h
+
+#include "DataFormat.h"
+#include "JSValue.h"
+#include "MacroAssembler.h"
+#include "VirtualRegister.h"
+#include <wtf/Platform.h>
+
+namespace JSC {
+
+// Describes how to recover a given bytecode virtual register at a given
+// code point.
+enum ValueRecoveryTechnique {
+    // It's already in the register file at the right location.
+    AlreadyInRegisterFile,
+    // It's already in the register file but unboxed.
+    AlreadyInRegisterFileAsUnboxedInt32,
+    AlreadyInRegisterFileAsUnboxedCell,
+    AlreadyInRegisterFileAsUnboxedBoolean,
+    // It's in a register.
+    InGPR,
+    UnboxedInt32InGPR,
+    UnboxedBooleanInGPR,
+#if USE(JSVALUE32_64)
+    InPair,
+#endif
+    InFPR,
+    // It's in the register file, but at a different location.
+    DisplacedInRegisterFile,
+    // It's in the register file, at a different location, and it's unboxed.
+    Int32DisplacedInRegisterFile,
+    DoubleDisplacedInRegisterFile,
+    // It's a constant.
+    Constant,
+    // Don't know how to recover it.
+    DontKnow
+};
+
+class ValueRecovery {
+public:
+    ValueRecovery()
+        : m_technique(DontKnow)
+    {
+    }
+    
+    static ValueRecovery alreadyInRegisterFile()
+    {
+        ValueRecovery result;
+        result.m_technique = AlreadyInRegisterFile;
+        return result;
+    }
+    
+    static ValueRecovery alreadyInRegisterFileAsUnboxedInt32()
+    {
+        ValueRecovery result;
+        result.m_technique = AlreadyInRegisterFileAsUnboxedInt32;
+        return result;
+    }
+    
+    static ValueRecovery alreadyInRegisterFileAsUnboxedCell()
+    {
+        ValueRecovery result;
+        result.m_technique = AlreadyInRegisterFileAsUnboxedCell;
+        return result;
+    }
+    
+    static ValueRecovery alreadyInRegisterFileAsUnboxedBoolean()
+    {
+        ValueRecovery result;
+        result.m_technique = AlreadyInRegisterFileAsUnboxedBoolean;
+        return result;
+    }
+    
+    static ValueRecovery inGPR(MacroAssembler::RegisterID gpr, DataFormat dataFormat)
+    {
+        ASSERT(dataFormat != DataFormatNone);
+#if USE(JSVALUE32_64)
+        ASSERT(dataFormat == DataFormatInteger || dataFormat == DataFormatCell || dataFormat == DataFormatBoolean);
+#endif
+        ValueRecovery result;
+        if (dataFormat == DataFormatInteger)
+            result.m_technique = UnboxedInt32InGPR;
+        else if (dataFormat == DataFormatBoolean)
+            result.m_technique = UnboxedBooleanInGPR;
+        else
+            result.m_technique = InGPR;
+        result.m_source.gpr = gpr;
+        return result;
+    }
+    
+#if USE(JSVALUE32_64)
+    static ValueRecovery inPair(MacroAssembler::RegisterID tagGPR, MacroAssembler::RegisterID payloadGPR)
+    {
+        ValueRecovery result;
+        result.m_technique = InPair;
+        result.m_source.pair.tagGPR = tagGPR;
+        result.m_source.pair.payloadGPR = payloadGPR;
+        return result;
+    }
+#endif
+
+    static ValueRecovery inFPR(MacroAssembler::FPRegisterID fpr)
+    {
+        ValueRecovery result;
+        result.m_technique = InFPR;
+        result.m_source.fpr = fpr;
+        return result;
+    }
+    
+    static ValueRecovery displacedInRegisterFile(VirtualRegister virtualReg, DataFormat dataFormat)
+    {
+        ValueRecovery result;
+        switch (dataFormat) {
+        case DataFormatInteger:
+            result.m_technique = Int32DisplacedInRegisterFile;
+            break;
+            
+        case DataFormatDouble:
+            result.m_technique = DoubleDisplacedInRegisterFile;
+            break;
+
+        default:
+            ASSERT(dataFormat != DataFormatNone && dataFormat != DataFormatStorage);
+            result.m_technique = DisplacedInRegisterFile;
+            break;
+        }
+        result.m_source.virtualReg = virtualReg;
+        return result;
+    }
+    
+    static ValueRecovery constant(JSValue value)
+    {
+        ValueRecovery result;
+        result.m_technique = Constant;
+        result.m_source.constant = JSValue::encode(value);
+        return result;
+    }
+    
+    ValueRecoveryTechnique technique() const { return m_technique; }
+    
+    bool isInRegisters() const
+    {
+        switch (m_technique) {
+        case InGPR:
+        case UnboxedInt32InGPR:
+        case UnboxedBooleanInGPR:
+#if USE(JSVALUE32_64)
+        case InPair:
+#endif
+        case InFPR:
+            return true;
+        default:
+            return false;
+        }
+    }
+    
+    MacroAssembler::RegisterID gpr() const
+    {
+        ASSERT(m_technique == InGPR || m_technique == UnboxedInt32InGPR || m_technique == UnboxedBooleanInGPR);
+        return m_source.gpr;
+    }
+    
+#if USE(JSVALUE32_64)
+    MacroAssembler::RegisterID tagGPR() const
+    {
+        ASSERT(m_technique == InPair);
+        return m_source.pair.tagGPR;
+    }
+    
+    MacroAssembler::RegisterID payloadGPR() const
+    {
+        ASSERT(m_technique == InPair);
+        return m_source.pair.payloadGPR;
+    }
+#endif
+    
+    MacroAssembler::FPRegisterID fpr() const
+    {
+        ASSERT(m_technique == InFPR);
+        return m_source.fpr;
+    }
+    
+    VirtualRegister virtualRegister() const
+    {
+        ASSERT(m_technique == DisplacedInRegisterFile || m_technique == Int32DisplacedInRegisterFile || m_technique == DoubleDisplacedInRegisterFile);
+        return m_source.virtualReg;
+    }
+    
+    JSValue constant() const
+    {
+        ASSERT(m_technique == Constant);
+        return JSValue::decode(m_source.constant);
+    }
+    
+#ifndef NDEBUG
+    void dump(FILE* out) const
+    {
+        switch (technique()) {
+        case AlreadyInRegisterFile:
+            fprintf(out, "-");
+            break;
+        case AlreadyInRegisterFileAsUnboxedInt32:
+            fprintf(out, "(int32)");
+            break;
+        case AlreadyInRegisterFileAsUnboxedCell:
+            fprintf(out, "(cell)");
+            break;
+        case AlreadyInRegisterFileAsUnboxedBoolean:
+            fprintf(out, "(bool)");
+            break;
+        case InGPR:
+            fprintf(out, "%%r%d", gpr());
+            break;
+        case UnboxedInt32InGPR:
+            fprintf(out, "int32(%%r%d)", gpr());
+            break;
+        case UnboxedBooleanInGPR:
+            fprintf(out, "bool(%%r%d)", gpr());
+            break;
+        case InFPR:
+            fprintf(out, "%%r%d", fpr());
+            break;
+#if USE(JSVALUE32_64)
+        case InPair:
+            fprintf(out, "pair(%%r%d, %%r%d)", tagGPR(), payloadGPR());
+            break;
+#endif
+        case DisplacedInRegisterFile:
+            fprintf(out, "*%d", virtualRegister());
+            break;
+        case Int32DisplacedInRegisterFile:
+            fprintf(out, "*int32(%d)", virtualRegister());
+            break;
+        case DoubleDisplacedInRegisterFile:
+            fprintf(out, "*double(%d)", virtualRegister());
+            break;
+        case Constant:
+            fprintf(out, "[%s]", constant().description());
+            break;
+        case DontKnow:
+            fprintf(out, "!");
+            break;
+        default:
+            fprintf(out, "?%d", technique());
+            break;
+        }
+    }
+#endif
+    
+private:
+    ValueRecoveryTechnique m_technique;
+    union {
+        MacroAssembler::RegisterID gpr;
+        MacroAssembler::FPRegisterID fpr;
+#if USE(JSVALUE32_64)
+        struct {
+            MacroAssembler::RegisterID tagGPR;
+            MacroAssembler::RegisterID payloadGPR;
+        } pair;
+#endif
+        VirtualRegister virtualReg;
+        EncodedJSValue constant;
+    } m_source;
+};
+
+} // namespace JSC
+
+#endif // ValueRecovery_h
diff --git a/Source/JavaScriptCore/bytecode/VirtualRegister.h b/Source/JavaScriptCore/bytecode/VirtualRegister.h
new file mode 100644 (file)
index 0000000..b95f8b8
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2011 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 VirtualRegister_h
+#define VirtualRegister_h
+
+#include <wtf/Platform.h>
+
+namespace JSC {
+
+// Type for a virtual register number (spill location).
+// Using an enum to make this type-checked at compile time, to avert programmer errors.
+enum VirtualRegister { InvalidVirtualRegister = -1 };
+COMPILE_ASSERT(sizeof(VirtualRegister) == sizeof(int), VirtualRegister_is_32bit);
+
+} // namespace JSC
+
+#endif // VirtualRegister_h
index 460b1bbfcbdea8b85ffa451e7217b7458e2bd5bd..3469610b00e3ca9af70ea2dea341bb4784e93386 100644 (file)
 
 #if ENABLE(DFG_JIT)
 
+#include "DataFormat.h"
 #include <dfg/DFGJITCompiler.h>
 
 namespace JSC { namespace DFG {
 
-// === DataFormat ===
-//
-// This enum tracks the current representation in which a value is being held.
-// Values may be unboxed primitives (int32, double, or cell), or boxed as a JSValue.
-// For boxed values, we may know the type of boxing that has taken place.
-// (May also need bool, array, object, string types!)
-enum DataFormat {
-    DataFormatNone = 0,
-    DataFormatInteger = 1,
-    DataFormatDouble = 2,
-    DataFormatBoolean = 3,
-    DataFormatCell = 4,
-    DataFormatStorage = 5,
-    DataFormatJS = 8,
-    DataFormatJSInteger = DataFormatJS | DataFormatInteger,
-    DataFormatJSDouble = DataFormatJS | DataFormatDouble,
-    DataFormatJSCell = DataFormatJS | DataFormatCell,
-    DataFormatJSBoolean = DataFormatJS | DataFormatBoolean
-};
-
-#ifndef NDEBUG
-inline const char* dataFormatToString(DataFormat dataFormat)
-{
-    switch (dataFormat) {
-    case DataFormatNone:
-        return "None";
-    case DataFormatInteger:
-        return "Integer";
-    case DataFormatDouble:
-        return "Double";
-    case DataFormatCell:
-        return "Cell";
-    case DataFormatBoolean:
-        return "Boolean";
-    case DataFormatStorage:
-        return "Storage";
-    case DataFormatJS:
-        return "JS";
-    case DataFormatJSInteger:
-        return "JSInteger";
-    case DataFormatJSDouble:
-        return "JSDouble";
-    case DataFormatJSCell:
-        return "JSCell";
-    case DataFormatJSBoolean:
-        return "JSBoolean";
-    default:
-        return "Unknown";
-    }
-}
-#endif
-
-#if USE(JSVALUE64)
-inline bool needDataFormatConversion(DataFormat from, DataFormat to)
-{
-    ASSERT(from != DataFormatNone);
-    ASSERT(to != DataFormatNone);
-    switch (from) {
-    case DataFormatInteger:
-    case DataFormatDouble:
-        return to != from;
-    case DataFormatCell:
-    case DataFormatJS:
-    case DataFormatJSInteger:
-    case DataFormatJSDouble:
-    case DataFormatJSCell:
-    case DataFormatJSBoolean:
-        switch (to) {
-        case DataFormatInteger:
-        case DataFormatDouble:
-            return true;
-        case DataFormatCell:
-        case DataFormatJS:
-        case DataFormatJSInteger:
-        case DataFormatJSDouble:
-        case DataFormatJSCell:
-        case DataFormatJSBoolean:
-            return false;
-        default:
-            // This captures DataFormatBoolean, which is currently unused.
-            ASSERT_NOT_REACHED();
-        }
-    case DataFormatStorage:
-        ASSERT(to == DataFormatStorage);
-        return false;
-    default:
-        // This captures DataFormatBoolean, which is currently unused.
-        ASSERT_NOT_REACHED();
-    }
-    return true;
-}
-
-#elif USE(JSVALUE32_64)
-inline bool needDataFormatConversion(DataFormat from, DataFormat to)
-{
-    ASSERT(from != DataFormatNone);
-    ASSERT(to != DataFormatNone);
-    switch (from) {
-    case DataFormatInteger:
-    case DataFormatCell:
-    case DataFormatBoolean:
-        return ((to & DataFormatJS) || to == DataFormatDouble);
-    case DataFormatDouble:
-    case DataFormatJSDouble:
-        return (to != DataFormatDouble && to != DataFormatJSDouble);
-    case DataFormatJS:
-    case DataFormatJSInteger:
-    case DataFormatJSCell:
-    case DataFormatJSBoolean:
-        return (!(to & DataFormatJS) || to == DataFormatJSDouble);
-    case DataFormatStorage:
-        ASSERT(to == DataFormatStorage);
-        return false;
-    default:
-        ASSERT_NOT_REACHED();
-    }
-    return true;
-}
-#endif
-
-inline bool isJSFormat(DataFormat format, DataFormat expectedFormat)
-{
-    ASSERT(expectedFormat & DataFormatJS);
-    return (format | DataFormatJS) == expectedFormat;
-}
-
-inline bool isJSInteger(DataFormat format)
-{
-    return isJSFormat(format, DataFormatJSInteger);
-}
-
-inline bool isJSDouble(DataFormat format)
-{
-    return isJSFormat(format, DataFormatJSDouble);
-}
-
-inline bool isJSCell(DataFormat format)
-{
-    return isJSFormat(format, DataFormatJSCell);
-}
-
-inline bool isJSBoolean(DataFormat format)
-{
-    return isJSFormat(format, DataFormatJSBoolean);
-}
-
 // === GenerationInfo ===
 //
 // This class is used to track the current status of a live values during code generation.
@@ -306,7 +161,7 @@ public:
     
     bool isJSFormat(DataFormat expectedFormat)
     {
-        return DFG::isJSFormat(registerFormat(), expectedFormat) || DFG::isJSFormat(spillFormat(), expectedFormat);
+        return JSC::isJSFormat(registerFormat(), expectedFormat) || JSC::isJSFormat(spillFormat(), expectedFormat);
     }
     
     bool isJSInteger()
index c501beda224ebbd1e35dc8c4c186edb5dee5a384..d58aa455eaf79279c18c6c30b0ab214a60ff4a42 100644 (file)
@@ -60,59 +60,6 @@ void ValueSource::dump(FILE* out) const
         break;
     }
 }
-
-void ValueRecovery::dump(FILE* out) const
-{
-    switch (technique()) {
-    case AlreadyInRegisterFile:
-        fprintf(out, "-");
-        break;
-    case AlreadyInRegisterFileAsUnboxedInt32:
-        fprintf(out, "(int32)");
-        break;
-    case AlreadyInRegisterFileAsUnboxedCell:
-        fprintf(out, "(cell)");
-        break;
-    case AlreadyInRegisterFileAsUnboxedBoolean:
-        fprintf(out, "(bool)");
-        break;
-    case InGPR:
-        fprintf(out, "%%%s", GPRInfo::debugName(gpr()));
-        break;
-    case UnboxedInt32InGPR:
-        fprintf(out, "int32(%%%s)", GPRInfo::debugName(gpr()));
-        break;
-    case UnboxedBooleanInGPR:
-        fprintf(out, "bool(%%%s)", GPRInfo::debugName(gpr()));
-        break;
-    case InFPR:
-        fprintf(out, "%%%s", FPRInfo::debugName(fpr()));
-        break;
-#if USE(JSVALUE32_64)
-    case InPair:
-        fprintf(out, "pair(%%%s, %%%s)", GPRInfo::debugName(tagGPR()), GPRInfo::debugName(payloadGPR()));
-        break;
-#endif
-    case DisplacedInRegisterFile:
-        fprintf(out, "*%d", virtualRegister());
-        break;
-    case Int32DisplacedInRegisterFile:
-        fprintf(out, "*int32(%d)", virtualRegister());
-        break;
-    case DoubleDisplacedInRegisterFile:
-        fprintf(out, "*double(%d)", virtualRegister());
-        break;
-    case Constant:
-        fprintf(out, "[%s]", constant().description());
-        break;
-    case DontKnow:
-        fprintf(out, "!");
-        break;
-    default:
-        fprintf(out, "?%d", technique());
-        break;
-    }
-}
 #endif
 
 OSRExit::OSRExit(JSValueSource jsValueSource, ValueProfile* valueProfile, MacroAssembler::Jump check, SpeculativeJIT* jit, unsigned recoveryIndex)
index 7107913c84b0f41083b732c362641c31eace7446..efcba1c9544f9c8f133e3e7103c49db8da1d249c 100644 (file)
@@ -28,6 +28,7 @@
 
 #if ENABLE(DFG_JIT)
 
+#include "ValueRecovery.h"
 #include <dfg/DFGAbstractState.h>
 #include <dfg/DFGJITCodeGenerator.h>
 
@@ -145,194 +146,6 @@ private:
     NodeIndex m_nodeIndex;
 };
     
-// Describes how to recover a given bytecode virtual register at a given
-// code point.
-enum ValueRecoveryTechnique {
-    // It's already in the register file at the right location.
-    AlreadyInRegisterFile,
-    // It's already in the register file but unboxed.
-    AlreadyInRegisterFileAsUnboxedInt32,
-    AlreadyInRegisterFileAsUnboxedCell,
-    AlreadyInRegisterFileAsUnboxedBoolean,
-    // It's in a register.
-    InGPR,
-    UnboxedInt32InGPR,
-    UnboxedBooleanInGPR,
-#if USE(JSVALUE32_64)
-    InPair,
-#endif
-    InFPR,
-    // It's in the register file, but at a different location.
-    DisplacedInRegisterFile,
-    // It's in the register file, at a different location, and it's unboxed.
-    Int32DisplacedInRegisterFile,
-    DoubleDisplacedInRegisterFile,
-    // It's a constant.
-    Constant,
-    // Don't know how to recover it.
-    DontKnow
-};
-
-class ValueRecovery {
-public:
-    ValueRecovery()
-        : m_technique(DontKnow)
-    {
-    }
-    
-    static ValueRecovery alreadyInRegisterFile()
-    {
-        ValueRecovery result;
-        result.m_technique = AlreadyInRegisterFile;
-        return result;
-    }
-    
-    static ValueRecovery alreadyInRegisterFileAsUnboxedInt32()
-    {
-        ValueRecovery result;
-        result.m_technique = AlreadyInRegisterFileAsUnboxedInt32;
-        return result;
-    }
-    
-    static ValueRecovery alreadyInRegisterFileAsUnboxedCell()
-    {
-        ValueRecovery result;
-        result.m_technique = AlreadyInRegisterFileAsUnboxedCell;
-        return result;
-    }
-    
-    static ValueRecovery alreadyInRegisterFileAsUnboxedBoolean()
-    {
-        ValueRecovery result;
-        result.m_technique = AlreadyInRegisterFileAsUnboxedBoolean;
-        return result;
-    }
-    
-    static ValueRecovery inGPR(GPRReg gpr, DataFormat dataFormat)
-    {
-        ASSERT(dataFormat != DataFormatNone);
-#if USE(JSVALUE32_64)
-        ASSERT(dataFormat == DataFormatInteger || dataFormat == DataFormatCell || dataFormat == DataFormatBoolean);
-#endif
-        ValueRecovery result;
-        if (dataFormat == DataFormatInteger)
-            result.m_technique = UnboxedInt32InGPR;
-        else if (dataFormat == DataFormatBoolean)
-            result.m_technique = UnboxedBooleanInGPR;
-        else
-            result.m_technique = InGPR;
-        result.m_source.gpr = gpr;
-        return result;
-    }
-    
-#if USE(JSVALUE32_64)
-    static ValueRecovery inPair(GPRReg tagGPR, GPRReg payloadGPR)
-    {
-        ValueRecovery result;
-        result.m_technique = InPair;
-        result.m_source.pair.tagGPR = tagGPR;
-        result.m_source.pair.payloadGPR = payloadGPR;
-        return result;
-    }
-#endif
-
-    static ValueRecovery inFPR(FPRReg fpr)
-    {
-        ValueRecovery result;
-        result.m_technique = InFPR;
-        result.m_source.fpr = fpr;
-        return result;
-    }
-    
-    static ValueRecovery displacedInRegisterFile(VirtualRegister virtualReg, DataFormat dataFormat)
-    {
-        ValueRecovery result;
-        switch (dataFormat) {
-        case DataFormatInteger:
-            result.m_technique = Int32DisplacedInRegisterFile;
-            break;
-            
-        case DataFormatDouble:
-            result.m_technique = DoubleDisplacedInRegisterFile;
-            break;
-
-        default:
-            ASSERT(dataFormat != DataFormatNone && dataFormat != DataFormatStorage);
-            result.m_technique = DisplacedInRegisterFile;
-            break;
-        }
-        result.m_source.virtualReg = virtualReg;
-        return result;
-    }
-    
-    static ValueRecovery constant(JSValue value)
-    {
-        ValueRecovery result;
-        result.m_technique = Constant;
-        result.m_source.constant = JSValue::encode(value);
-        return result;
-    }
-    
-    ValueRecoveryTechnique technique() const { return m_technique; }
-    
-    GPRReg gpr() const
-    {
-        ASSERT(m_technique == InGPR || m_technique == UnboxedInt32InGPR || m_technique == UnboxedBooleanInGPR);
-        return m_source.gpr;
-    }
-    
-#if USE(JSVALUE32_64)
-    GPRReg tagGPR() const
-    {
-        ASSERT(m_technique == InPair);
-        return m_source.pair.tagGPR;
-    }
-    
-    GPRReg payloadGPR() const
-    {
-        ASSERT(m_technique == InPair);
-        return m_source.pair.payloadGPR;
-    }
-#endif
-    
-    FPRReg fpr() const
-    {
-        ASSERT(m_technique == InFPR);
-        return m_source.fpr;
-    }
-    
-    VirtualRegister virtualRegister() const
-    {
-        ASSERT(m_technique == DisplacedInRegisterFile || m_technique == Int32DisplacedInRegisterFile || m_technique == DoubleDisplacedInRegisterFile);
-        return m_source.virtualReg;
-    }
-    
-    JSValue constant() const
-    {
-        ASSERT(m_technique == Constant);
-        return JSValue::decode(m_source.constant);
-    }
-    
-#ifndef NDEBUG
-    void dump(FILE* out) const;
-#endif
-    
-private:
-    ValueRecoveryTechnique m_technique;
-    union {
-        GPRReg gpr;
-        FPRReg fpr;
-#if USE(JSVALUE32_64)
-        struct {
-            GPRReg tagGPR;
-            GPRReg payloadGPR;
-        } pair;
-#endif
-        VirtualRegister virtualReg;
-        EncodedJSValue constant;
-    } m_source;
-};
-
 // === OSRExit ===
 //
 // This structure describes how to exit the speculative path by
index ce93fdd3f4808a4b34a6ba4de41190b19b1690a6..2a76a2cc56dfd30735bfe75b8a28d303265f3fda 100644 (file)
 #ifndef DFGVariableAccessData_h
 #define DFGVariableAccessData_h
 
+#include "PredictedType.h"
+#include "VirtualRegister.h"
 #include <wtf/Platform.h>
-
-#if ENABLE(DFG_JIT)
-
 #include <wtf/UnionFind.h>
 
 namespace JSC { namespace DFG {
 
-// Type for a virtual register number (spill location).
-// Using an enum to make this type-checked at compile time, to avert programmer errors.
-enum VirtualRegister { InvalidVirtualRegister = -1 };
-COMPILE_ASSERT(sizeof(VirtualRegister) == sizeof(int), VirtualRegister_is_32bit);
-
 class VariableAccessData: public UnionFind<VariableAccessData> {
 public:
     VariableAccessData()
@@ -86,6 +80,4 @@ private:
 
 } } // namespace JSC::DFG
 
-#endif // ENABLE(DFG_JIT)
-
 #endif // DFGVariableAccessData_h