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.h329
1 files changed, 184 insertions, 145 deletions
diff --git a/Source/JavaScriptCore/bytecode/ValueRecovery.h b/Source/JavaScriptCore/bytecode/ValueRecovery.h
index 77d5a1030..5f6ee9c72 100644
--- a/Source/JavaScriptCore/bytecode/ValueRecovery.h
+++ b/Source/JavaScriptCore/bytecode/ValueRecovery.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Apple Inc. All rights reserved.
+ * 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
@@ -26,43 +26,49 @@
#ifndef ValueRecovery_h
#define ValueRecovery_h
+#include "DFGMinifiedID.h"
#include "DataFormat.h"
+#if ENABLE(JIT)
+#include "GPRInfo.h"
+#include "FPRInfo.h"
+#include "Reg.h"
+#endif
#include "JSCJSValue.h"
#include "MacroAssembler.h"
#include "VirtualRegister.h"
-#include <stdio.h>
-#include <wtf/Platform.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 already in the stack at the right location.
- AlreadyInJSStack,
- // It's already in the stack but unboxed.
- AlreadyInJSStackAsUnboxedInt32,
- AlreadyInJSStackAsUnboxedCell,
- AlreadyInJSStackAsUnboxedBoolean,
- AlreadyInJSStackAsUnboxedDouble,
// It's in a register.
InGPR,
UnboxedInt32InGPR,
+ UnboxedInt52InGPR,
+ UnboxedStrictInt52InGPR,
UnboxedBooleanInGPR,
+ UnboxedCellInGPR,
#if USE(JSVALUE32_64)
InPair,
#endif
InFPR,
- UInt32InGPR,
+ UnboxedDoubleInFPR,
// 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.
- ArgumentsThatWereNotCreated,
+ // 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.
@@ -78,67 +84,43 @@ 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 alreadyInJSStackAsUnboxedCell()
- {
- ValueRecovery result;
- result.m_technique = AlreadyInJSStackAsUnboxedCell;
- return result;
- }
-
- static ValueRecovery alreadyInJSStackAsUnboxedBoolean()
- {
- ValueRecovery result;
- result.m_technique = AlreadyInJSStackAsUnboxedBoolean;
- return result;
- }
-
- static ValueRecovery alreadyInJSStackAsUnboxedDouble()
+
+#if ENABLE(JIT)
+ static ValueRecovery inRegister(Reg reg, DataFormat dataFormat)
{
- ValueRecovery result;
- result.m_technique = AlreadyInJSStackAsUnboxedDouble;
- return result;
+ if (reg.isGPR())
+ return inGPR(reg.gpr(), dataFormat);
+
+ ASSERT(reg.isFPR());
+ return inFPR(reg.fpr(), dataFormat);
}
+#endif
+
+ explicit operator bool() const { return isSet(); }
static ValueRecovery inGPR(MacroAssembler::RegisterID gpr, DataFormat dataFormat)
{
ASSERT(dataFormat != DataFormatNone);
#if USE(JSVALUE32_64)
- ASSERT(dataFormat == DataFormatInteger || dataFormat == DataFormatCell || dataFormat == DataFormatBoolean);
+ ASSERT(dataFormat == DataFormatInt32 || dataFormat == DataFormatCell || dataFormat == DataFormatBoolean);
#endif
ValueRecovery result;
- if (dataFormat == DataFormatInteger)
+ 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;
}
- 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)
{
@@ -150,10 +132,14 @@ public:
}
#endif
- static ValueRecovery inFPR(MacroAssembler::FPRegisterID fpr)
+ static ValueRecovery inFPR(MacroAssembler::FPRegisterID fpr, DataFormat dataFormat)
{
+ ASSERT(dataFormat == DataFormatDouble || dataFormat & DataFormatJS);
ValueRecovery result;
- result.m_technique = InFPR;
+ if (dataFormat == DataFormatDouble)
+ result.m_technique = UnboxedDoubleInFPR;
+ else
+ result.m_technique = InFPR;
result.m_source.fpr = fpr;
return result;
}
@@ -162,10 +148,18 @@ public:
{
ValueRecovery result;
switch (dataFormat) {
- case DataFormatInteger:
+ 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;
@@ -183,7 +177,7 @@ public:
result.m_technique = DisplacedInJSStack;
break;
}
- result.m_source.virtualReg = virtualReg;
+ result.m_source.virtualReg = virtualReg.offset();
return result;
}
@@ -195,50 +189,110 @@ public:
return result;
}
- static ValueRecovery argumentsThatWereNotCreated()
+ static ValueRecovery directArgumentsThatWereNotCreated(DFG::MinifiedID id)
{
ValueRecovery result;
- result.m_technique = ArgumentsThatWereNotCreated;
+ 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
+
+ bool isInGPR() const
{
switch (m_technique) {
case InGPR:
case UnboxedInt32InGPR:
case UnboxedBooleanInGPR:
-#if USE(JSVALUE32_64)
- case InPair:
-#endif
+ case UnboxedCellInGPR:
+ case UnboxedInt52InGPR:
+ case UnboxedStrictInt52InGPR:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ bool isInFPR() const
+ {
+ switch (m_technique) {
case InFPR:
+ case UnboxedDoubleInFPR:
return true;
default:
return false;
}
}
-
- bool isAlreadyInJSStack() const
+
+ bool isInRegisters() const
+ {
+ return isInJSValueRegs() || isInGPR() || isInFPR();
+ }
+
+ bool isInJSStack() const
{
- switch (technique()) {
- case AlreadyInJSStack:
- case AlreadyInJSStackAsUnboxedInt32:
- case AlreadyInJSStackAsUnboxedCell:
- case AlreadyInJSStackAsUnboxedBoolean:
- case AlreadyInJSStackAsUnboxedDouble:
+ switch (m_technique) {
+ case DisplacedInJSStack:
+ case Int32DisplacedInJSStack:
+ case Int52DisplacedInJSStack:
+ case StrictInt52DisplacedInJSStack:
+ case DoubleDisplacedInJSStack:
+ case CellDisplacedInJSStack:
+ case BooleanDisplacedInJSStack:
return true;
default:
return false;
}
}
+
+ DataFormat dataFormat() const
+ {
+ switch (m_technique) {
+ case InGPR:
+ case InFPR:
+ case DisplacedInJSStack:
+ case Constant:
+#if USE(JSVALUE32_64)
+ case InPair:
+#endif
+ return DataFormatJS;
+ case UnboxedInt32InGPR:
+ case Int32DisplacedInJSStack:
+ return DataFormatInt32;
+ case UnboxedInt52InGPR:
+ case Int52DisplacedInJSStack:
+ return DataFormatInt52;
+ case UnboxedStrictInt52InGPR:
+ case StrictInt52DisplacedInJSStack:
+ return DataFormatStrictInt52;
+ case UnboxedBooleanInGPR:
+ case BooleanDisplacedInJSStack:
+ return DataFormatBoolean;
+ case UnboxedCellInGPR:
+ case CellDisplacedInJSStack:
+ return DataFormatCell;
+ case UnboxedDoubleInFPR:
+ case DoubleDisplacedInJSStack:
+ return DataFormatDouble;
+ default:
+ return DataFormatNone;
+ }
+ }
MacroAssembler::RegisterID gpr() const
{
- ASSERT(m_technique == InGPR || m_technique == UnboxedInt32InGPR || m_technique == UnboxedBooleanInGPR || m_technique == UInt32InGPR);
+ ASSERT(isInGPR());
return m_source.gpr;
}
@@ -254,94 +308,78 @@ public:
ASSERT(m_technique == InPair);
return m_source.pair.payloadGPR;
}
-#endif
+
+ bool isInJSValueRegs() const
+ {
+ return m_technique == InPair;
+ }
+
+#if ENABLE(JIT)
+ JSValueRegs jsValueRegs() const
+ {
+ ASSERT(isInJSValueRegs());
+ return JSValueRegs(tagGPR(), payloadGPR());
+ }
+#endif // ENABLE(JIT)
+#else
+ bool isInJSValueRegs() const
+ {
+ return isInGPR();
+ }
+#endif // USE(JSVALUE32_64)
MacroAssembler::FPRegisterID fpr() const
{
- ASSERT(m_technique == InFPR);
+ ASSERT(isInFPR());
return m_source.fpr;
}
VirtualRegister virtualRegister() const
{
- ASSERT(m_technique == DisplacedInJSStack || m_technique == Int32DisplacedInJSStack || m_technique == DoubleDisplacedInJSStack || m_technique == CellDisplacedInJSStack || m_technique == BooleanDisplacedInJSStack);
- return m_source.virtualReg;
- }
-
- JSValue constant() const
- {
- ASSERT(m_technique == Constant);
- return JSValue::decode(m_source.constant);
+ ASSERT(isInJSStack());
+ return VirtualRegister(m_source.virtualReg);
}
- void dump(PrintStream& out) const
+ ValueRecovery withLocalsOffset(int offset) const
{
- switch (technique()) {
- case AlreadyInJSStack:
- out.printf("-");
- break;
- case AlreadyInJSStackAsUnboxedInt32:
- out.printf("(int32)");
- break;
- case AlreadyInJSStackAsUnboxedCell:
- out.printf("(cell)");
- break;
- case AlreadyInJSStackAsUnboxedBoolean:
- out.printf("(bool)");
- break;
- case AlreadyInJSStackAsUnboxedDouble:
- out.printf("(double)");
- break;
- case InGPR:
- out.printf("%%r%d", gpr());
- break;
- case UnboxedInt32InGPR:
- out.printf("int32(%%r%d)", gpr());
- break;
- case UnboxedBooleanInGPR:
- out.printf("bool(%%r%d)", gpr());
- break;
- case UInt32InGPR:
- out.printf("uint32(%%r%d)", gpr());
- break;
- case InFPR:
- out.printf("%%fr%d", fpr());
- break;
-#if USE(JSVALUE32_64)
- case InPair:
- out.printf("pair(%%r%d, %%r%d)", tagGPR(), payloadGPR());
- break;
-#endif
+ switch (m_technique) {
case DisplacedInJSStack:
- out.printf("*%d", virtualRegister());
- break;
case Int32DisplacedInJSStack:
- out.printf("*int32(%d)", virtualRegister());
- break;
case DoubleDisplacedInJSStack:
- out.printf("*double(%d)", virtualRegister());
- break;
case CellDisplacedInJSStack:
- out.printf("*cell(%d)", virtualRegister());
- break;
case BooleanDisplacedInJSStack:
- out.printf("*bool(%d)", virtualRegister());
- break;
- case ArgumentsThatWereNotCreated:
- out.printf("arguments");
- break;
- case Constant:
- out.print("[", constant(), "]");
- break;
- case DontKnow:
- out.printf("!");
- break;
+ case Int52DisplacedInJSStack:
+ case StrictInt52DisplacedInJSStack: {
+ ValueRecovery result;
+ result.m_technique = m_technique;
+ result.m_source.virtualReg = m_source.virtualReg + offset;
+ return result;
+ }
+
default:
- out.printf("?%d", technique());
- break;
+ return *this;
}
}
+ JSValue constant() const
+ {
+ ASSERT(isConstant());
+ 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 {
@@ -353,8 +391,9 @@ private:
MacroAssembler::RegisterID payloadGPR;
} pair;
#endif
- VirtualRegister virtualReg;
+ int virtualReg;
EncodedJSValue constant;
+ uintptr_t nodeID;
} m_source;
};