/* * Copyright (C) 2013 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 FTLExitValue_h #define FTLExitValue_h #include #if ENABLE(FTL_JIT) #include "FTLExitArgument.h" #include "JSCJSValue.h" #include namespace JSC { namespace FTL { // This is like ValueRecovery, but respects the way that the FTL does OSR // exit: the live non-constant non-flushed values are passed as arguments // to a noreturn tail call. ExitValue is hence mostly responsible for // telling us the mapping between operands in bytecode and the arguments to // the call. enum ExitValueKind { InvalidExitValue, ExitValueDead, ExitValueArgument, ExitValueConstant, ExitValueInJSStack, ExitValueInJSStackAsInt32, ExitValueInJSStackAsDouble }; class ExitValue { public: ExitValue() : m_kind(InvalidExitValue) { } bool operator!() const { return m_kind == InvalidExitValue; } static ExitValue dead() { ExitValue result; result.m_kind = ExitValueDead; return result; } static ExitValue inJSStack() { ExitValue result; result.m_kind = ExitValueInJSStack; return result; } static ExitValue inJSStackAsInt32() { ExitValue result; result.m_kind = ExitValueInJSStackAsInt32; return result; } static ExitValue inJSStackAsDouble() { ExitValue result; result.m_kind = ExitValueInJSStackAsDouble; return result; } static ExitValue constant(JSValue value) { ExitValue result; result.m_kind = ExitValueConstant; result.u.constant = JSValue::encode(value); return result; } static ExitValue exitArgument(const ExitArgument& argument) { ExitValue result; result.m_kind = ExitValueArgument; result.u.argument = argument.representation(); return result; } ExitValueKind kind() const { return m_kind; } bool isDead() const { return kind() == ExitValueDead; } bool isInJSStackSomehow() const { switch (kind()) { case ExitValueInJSStack: case ExitValueInJSStackAsInt32: case ExitValueInJSStackAsDouble: return true; default: return false; } } bool isConstant() const { return kind() == ExitValueConstant; } bool isArgument() const { return kind() == ExitValueArgument; } ExitArgument exitArgument() const { ASSERT(isArgument()); return ExitArgument(u.argument); } JSValue constant() const { ASSERT(isConstant()); return JSValue::decode(u.constant); } void dump(PrintStream&) const; void dumpInContext(PrintStream&, DumpContext*) const; private: ExitValueKind m_kind; union { ExitArgumentRepresentation argument; EncodedJSValue constant; } u; }; } } // namespace JSC::FTL #endif // ENABLE(FTL_JIT) #endif // FTLExitValue_h