diff options
Diffstat (limited to 'Source/JavaScriptCore/bytecode/ValueRecovery.h')
-rw-r--r-- | Source/JavaScriptCore/bytecode/ValueRecovery.h | 329 |
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; }; |