]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - bytecode/ValueRecovery.h
JavaScriptCore-1097.3.tar.gz
[apple/javascriptcore.git] / bytecode / ValueRecovery.h
diff --git a/bytecode/ValueRecovery.h b/bytecode/ValueRecovery.h
new file mode 100644 (file)
index 0000000..007c6d3
--- /dev/null
@@ -0,0 +1,348 @@
+/*
+ * 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 <stdio.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,
+    AlreadyInRegisterFileAsUnboxedDouble,
+    // It's in a register.
+    InGPR,
+    UnboxedInt32InGPR,
+    UnboxedBooleanInGPR,
+#if USE(JSVALUE32_64)
+    InPair,
+#endif
+    InFPR,
+    UInt32InGPR,
+    // 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,
+    CellDisplacedInRegisterFile,
+    BooleanDisplacedInRegisterFile,
+    // 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 alreadyInRegisterFileAsUnboxedDouble()
+    {
+        ValueRecovery result;
+        result.m_technique = AlreadyInRegisterFileAsUnboxedDouble;
+        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;
+    }
+    
+    static ValueRecovery uint32InGPR(MacroAssembler::RegisterID gpr)
+    {
+        ValueRecovery result;
+        result.m_technique = UInt32InGPR;
+        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;
+
+        case DataFormatCell:
+            result.m_technique = CellDisplacedInRegisterFile;
+            break;
+            
+        case DataFormatBoolean:
+            result.m_technique = BooleanDisplacedInRegisterFile;
+            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 isConstant() const { return m_technique == Constant; }
+    
+    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;
+        }
+    }
+    
+    bool isAlreadyInRegisterFile() const
+    {
+        switch (technique()) {
+        case AlreadyInRegisterFile:
+        case AlreadyInRegisterFileAsUnboxedInt32:
+        case AlreadyInRegisterFileAsUnboxedCell:
+        case AlreadyInRegisterFileAsUnboxedBoolean:
+        case AlreadyInRegisterFileAsUnboxedDouble:
+            return true;
+        default:
+            return false;
+        }
+    }
+    
+    MacroAssembler::RegisterID gpr() const
+    {
+        ASSERT(m_technique == InGPR || m_technique == UnboxedInt32InGPR || m_technique == UnboxedBooleanInGPR || m_technique == UInt32InGPR);
+        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 || m_technique == CellDisplacedInRegisterFile || m_technique == BooleanDisplacedInRegisterFile);
+        return m_source.virtualReg;
+    }
+    
+    JSValue constant() const
+    {
+        ASSERT(m_technique == Constant);
+        return JSValue::decode(m_source.constant);
+    }
+    
+    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 AlreadyInRegisterFileAsUnboxedDouble:
+            fprintf(out, "(double)");
+            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 UInt32InGPR:
+            fprintf(out, "uint32(%%r%d)", gpr());
+            break;
+        case InFPR:
+            fprintf(out, "%%fr%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 CellDisplacedInRegisterFile:
+            fprintf(out, "*cell(%d)", virtualRegister());
+            break;
+        case BooleanDisplacedInRegisterFile:
+            fprintf(out, "*bool(%d)", virtualRegister());
+            break;
+        case Constant:
+            fprintf(out, "[%s]", constant().description());
+            break;
+        case DontKnow:
+            fprintf(out, "!");
+            break;
+        default:
+            fprintf(out, "?%d", technique());
+            break;
+        }
+    }
+    
+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