summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/bytecode/ValueRecovery.h
diff options
context:
space:
mode:
Diffstat (limited to 'Source/JavaScriptCore/bytecode/ValueRecovery.h')
-rw-r--r--Source/JavaScriptCore/bytecode/ValueRecovery.h303
1 files changed, 303 insertions, 0 deletions
diff --git a/Source/JavaScriptCore/bytecode/ValueRecovery.h b/Source/JavaScriptCore/bytecode/ValueRecovery.h
new file mode 100644
index 000000000..42651e2c7
--- /dev/null
+++ b/Source/JavaScriptCore/bytecode/ValueRecovery.h
@@ -0,0 +1,303 @@
+/*
+ * Copyright (C) 2011, 2013, 2015 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 "DFGMinifiedID.h"
+#include "DataFormat.h"
+#if ENABLE(JIT)
+#include "GPRInfo.h"
+#include "FPRInfo.h"
+#endif
+#include "JSCJSValue.h"
+#include "MacroAssembler.h"
+#include "VirtualRegister.h"
+
+namespace JSC {
+
+struct DumpContext;
+struct InlineCallFrame;
+
+// Describes how to recover a given bytecode virtual register at a given
+// code point.
+enum ValueRecoveryTechnique {
+ // It's in a register.
+ InGPR,
+ UnboxedInt32InGPR,
+ UnboxedInt52InGPR,
+ UnboxedStrictInt52InGPR,
+ UnboxedBooleanInGPR,
+ UnboxedCellInGPR,
+#if USE(JSVALUE32_64)
+ InPair,
+#endif
+ InFPR,
+ // It's in the stack, but at a different location.
+ DisplacedInJSStack,
+ // It's in the stack, at a different location, and it's unboxed.
+ Int32DisplacedInJSStack,
+ Int52DisplacedInJSStack,
+ StrictInt52DisplacedInJSStack,
+ DoubleDisplacedInJSStack,
+ CellDisplacedInJSStack,
+ BooleanDisplacedInJSStack,
+ // It's an Arguments object. This arises because of the simplified arguments simplification done by the DFG.
+ DirectArgumentsThatWereNotCreated,
+ ClonedArgumentsThatWereNotCreated,
+ // It's a constant.
+ Constant,
+ // Don't know how to recover it.
+ DontKnow
+};
+
+class ValueRecovery {
+public:
+ ValueRecovery()
+ : m_technique(DontKnow)
+ {
+ }
+
+ bool isSet() const { return m_technique != DontKnow; }
+ bool operator!() const { return !isSet(); }
+
+ static ValueRecovery inGPR(MacroAssembler::RegisterID gpr, DataFormat dataFormat)
+ {
+ ASSERT(dataFormat != DataFormatNone);
+#if USE(JSVALUE32_64)
+ ASSERT(dataFormat == DataFormatInt32 || dataFormat == DataFormatCell || dataFormat == DataFormatBoolean);
+#endif
+ ValueRecovery result;
+ if (dataFormat == DataFormatInt32)
+ result.m_technique = UnboxedInt32InGPR;
+ else if (dataFormat == DataFormatInt52)
+ result.m_technique = UnboxedInt52InGPR;
+ else if (dataFormat == DataFormatStrictInt52)
+ result.m_technique = UnboxedStrictInt52InGPR;
+ else if (dataFormat == DataFormatBoolean)
+ result.m_technique = UnboxedBooleanInGPR;
+ else if (dataFormat == DataFormatCell)
+ result.m_technique = UnboxedCellInGPR;
+ 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 displacedInJSStack(VirtualRegister virtualReg, DataFormat dataFormat)
+ {
+ ValueRecovery result;
+ switch (dataFormat) {
+ case DataFormatInt32:
+ result.m_technique = Int32DisplacedInJSStack;
+ break;
+
+ case DataFormatInt52:
+ result.m_technique = Int52DisplacedInJSStack;
+ break;
+
+ case DataFormatStrictInt52:
+ result.m_technique = StrictInt52DisplacedInJSStack;
+ break;
+
+ case DataFormatDouble:
+ result.m_technique = DoubleDisplacedInJSStack;
+ break;
+
+ case DataFormatCell:
+ result.m_technique = CellDisplacedInJSStack;
+ break;
+
+ case DataFormatBoolean:
+ result.m_technique = BooleanDisplacedInJSStack;
+ break;
+
+ default:
+ ASSERT(dataFormat != DataFormatNone && dataFormat != DataFormatStorage);
+ result.m_technique = DisplacedInJSStack;
+ break;
+ }
+ result.m_source.virtualReg = virtualReg.offset();
+ return result;
+ }
+
+ static ValueRecovery constant(JSValue value)
+ {
+ ValueRecovery result;
+ result.m_technique = Constant;
+ result.m_source.constant = JSValue::encode(value);
+ return result;
+ }
+
+ static ValueRecovery directArgumentsThatWereNotCreated(DFG::MinifiedID id)
+ {
+ ValueRecovery result;
+ result.m_technique = DirectArgumentsThatWereNotCreated;
+ result.m_source.nodeID = id.bits();
+ return result;
+ }
+
+ static ValueRecovery outOfBandArgumentsThatWereNotCreated(DFG::MinifiedID id)
+ {
+ ValueRecovery result;
+ result.m_technique = ClonedArgumentsThatWereNotCreated;
+ result.m_source.nodeID = id.bits();
+ 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:
+ case UnboxedCellInGPR:
+ case UnboxedInt52InGPR:
+ case UnboxedStrictInt52InGPR:
+#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 || m_technique == UnboxedInt52InGPR || m_technique == UnboxedStrictInt52InGPR || m_technique == UnboxedCellInGPR);
+ 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 == DisplacedInJSStack || m_technique == Int32DisplacedInJSStack || m_technique == DoubleDisplacedInJSStack || m_technique == CellDisplacedInJSStack || m_technique == BooleanDisplacedInJSStack || m_technique == Int52DisplacedInJSStack || m_technique == StrictInt52DisplacedInJSStack);
+ return VirtualRegister(m_source.virtualReg);
+ }
+
+ ValueRecovery withLocalsOffset(int offset) const
+ {
+ switch (m_technique) {
+ case DisplacedInJSStack:
+ case Int32DisplacedInJSStack:
+ case DoubleDisplacedInJSStack:
+ case CellDisplacedInJSStack:
+ case BooleanDisplacedInJSStack:
+ case Int52DisplacedInJSStack:
+ case StrictInt52DisplacedInJSStack: {
+ ValueRecovery result;
+ result.m_technique = m_technique;
+ result.m_source.virtualReg = m_source.virtualReg + offset;
+ return result;
+ }
+
+ default:
+ return *this;
+ }
+ }
+
+ JSValue constant() const
+ {
+ ASSERT(m_technique == Constant);
+ return JSValue::decode(m_source.constant);
+ }
+
+ DFG::MinifiedID nodeID() const
+ {
+ ASSERT(m_technique == DirectArgumentsThatWereNotCreated || m_technique == ClonedArgumentsThatWereNotCreated);
+ return DFG::MinifiedID::fromBits(m_source.nodeID);
+ }
+
+ JSValue recover(ExecState*) const;
+
+#if ENABLE(JIT)
+ void dumpInContext(PrintStream& out, DumpContext* context) const;
+ void dump(PrintStream& out) const;
+#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
+ int virtualReg;
+ EncodedJSValue constant;
+ uintptr_t nodeID;
+ } m_source;
+};
+
+} // namespace JSC
+
+#endif // ValueRecovery_h