| /* |
| * 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 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 || 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 |