|  | /* | 
|  | * Copyright (C) 2014, 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. | 
|  | */ | 
|  |  | 
|  | #include "config.h" | 
|  | #include "DFGVariableAccessData.h" | 
|  |  | 
|  | #if ENABLE(DFG_JIT) | 
|  |  | 
|  | namespace JSC { namespace DFG { | 
|  |  | 
|  | VariableAccessData::VariableAccessData() | 
|  | : m_local(static_cast<VirtualRegister>(std::numeric_limits<int>::min())) | 
|  | , m_prediction(SpecNone) | 
|  | , m_argumentAwarePrediction(SpecNone) | 
|  | , m_flags(0) | 
|  | , m_shouldNeverUnbox(false) | 
|  | , m_structureCheckHoistingFailed(false) | 
|  | , m_checkArrayHoistingFailed(false) | 
|  | , m_isProfitableToUnbox(false) | 
|  | , m_isLoadedFrom(false) | 
|  | , m_doubleFormatState(EmptyDoubleFormatState) | 
|  | { | 
|  | clearVotes(); | 
|  | } | 
|  |  | 
|  | VariableAccessData::VariableAccessData(VirtualRegister local) | 
|  | : m_local(local) | 
|  | , m_prediction(SpecNone) | 
|  | , m_argumentAwarePrediction(SpecNone) | 
|  | , m_flags(0) | 
|  | , m_shouldNeverUnbox(false) | 
|  | , m_structureCheckHoistingFailed(false) | 
|  | , m_checkArrayHoistingFailed(false) | 
|  | , m_isProfitableToUnbox(false) | 
|  | , m_isLoadedFrom(false) | 
|  | , m_doubleFormatState(EmptyDoubleFormatState) | 
|  | { | 
|  | clearVotes(); | 
|  | } | 
|  |  | 
|  | bool VariableAccessData::mergeShouldNeverUnbox(bool shouldNeverUnbox) | 
|  | { | 
|  | bool newShouldNeverUnbox = m_shouldNeverUnbox | shouldNeverUnbox; | 
|  | if (newShouldNeverUnbox == m_shouldNeverUnbox) | 
|  | return false; | 
|  | m_shouldNeverUnbox = newShouldNeverUnbox; | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool VariableAccessData::predict(SpeculatedType prediction) | 
|  | { | 
|  | VariableAccessData* self = find(); | 
|  | bool result = mergeSpeculation(self->m_prediction, prediction); | 
|  | if (result) | 
|  | mergeSpeculation(m_argumentAwarePrediction, m_prediction); | 
|  | return result; | 
|  | } | 
|  |  | 
|  | bool VariableAccessData::mergeArgumentAwarePrediction(SpeculatedType prediction) | 
|  | { | 
|  | return mergeSpeculation(find()->m_argumentAwarePrediction, prediction); | 
|  | } | 
|  |  | 
|  | bool VariableAccessData::shouldUseDoubleFormatAccordingToVote() | 
|  | { | 
|  | // We don't support this facility for arguments, yet. | 
|  | // FIXME: make this work for arguments. | 
|  | if (local().isArgument()) | 
|  | return false; | 
|  |  | 
|  | // If the variable is not a number prediction, then this doesn't | 
|  | // make any sense. | 
|  | if (!isFullNumberSpeculation(prediction())) { | 
|  | // FIXME: we may end up forcing a local in inlined argument position to be a double even | 
|  | // if it is sometimes not even numeric, since this never signals the fact that it doesn't | 
|  | // want doubles. https://bugs.webkit.org/show_bug.cgi?id=109511 | 
|  | return false; | 
|  | } | 
|  |  | 
|  | // If the variable is predicted to hold only doubles, then it's a | 
|  | // no-brainer: it should be formatted as a double. | 
|  | if (isDoubleSpeculation(prediction())) | 
|  | return true; | 
|  |  | 
|  | // If the variable is known to be used as an integer, then be safe - | 
|  | // don't force it to be a double. | 
|  | if (flags() & NodeBytecodeUsesAsInt) | 
|  | return false; | 
|  |  | 
|  | // If the variable has been voted to become a double, then make it a | 
|  | // double. | 
|  | if (voteRatio() >= Options::doubleVoteRatioForDoubleFormat()) | 
|  | return true; | 
|  |  | 
|  | return false; | 
|  | } | 
|  |  | 
|  | bool VariableAccessData::tallyVotesForShouldUseDoubleFormat() | 
|  | { | 
|  | ASSERT(isRoot()); | 
|  |  | 
|  | if (local().isArgument() || shouldNeverUnbox() | 
|  | || (flags() & NodeBytecodeUsesAsArrayIndex)) | 
|  | return DFG::mergeDoubleFormatState(m_doubleFormatState, NotUsingDoubleFormat); | 
|  |  | 
|  | if (m_doubleFormatState == CantUseDoubleFormat) | 
|  | return false; | 
|  |  | 
|  | bool newValueOfShouldUseDoubleFormat = shouldUseDoubleFormatAccordingToVote(); | 
|  | if (!newValueOfShouldUseDoubleFormat) { | 
|  | // We monotonically convert to double. Hence, if the fixpoint leads us to conclude that we should | 
|  | // switch back to int, we instead ignore this and stick with double. | 
|  | return false; | 
|  | } | 
|  |  | 
|  | if (m_doubleFormatState == UsingDoubleFormat) | 
|  | return false; | 
|  |  | 
|  | return DFG::mergeDoubleFormatState(m_doubleFormatState, UsingDoubleFormat); | 
|  | } | 
|  |  | 
|  | bool VariableAccessData::mergeDoubleFormatState(DoubleFormatState doubleFormatState) | 
|  | { | 
|  | return DFG::mergeDoubleFormatState(find()->m_doubleFormatState, doubleFormatState); | 
|  | } | 
|  |  | 
|  | bool VariableAccessData::makePredictionForDoubleFormat() | 
|  | { | 
|  | ASSERT(isRoot()); | 
|  |  | 
|  | if (m_doubleFormatState != UsingDoubleFormat) | 
|  | return false; | 
|  |  | 
|  | SpeculatedType type = m_prediction; | 
|  | if (type & ~SpecBytecodeNumber) | 
|  | type |= SpecDoublePureNaN; | 
|  | if (type & (SpecInt32Only | SpecInt52Any)) | 
|  | type |= SpecAnyIntAsDouble; | 
|  | return checkAndSet(m_prediction, type); | 
|  | } | 
|  |  | 
|  | bool VariableAccessData::couldRepresentInt52() | 
|  | { | 
|  | if (shouldNeverUnbox()) | 
|  | return false; | 
|  |  | 
|  | return couldRepresentInt52Impl(); | 
|  | } | 
|  |  | 
|  | bool VariableAccessData::couldRepresentInt52Impl() | 
|  | { | 
|  | // The hardware has to support it. | 
|  | if (!enableInt52()) | 
|  | return false; | 
|  |  | 
|  | // We punt for machine arguments. | 
|  | if (m_local.isArgument()) | 
|  | return false; | 
|  |  | 
|  | // The argument-aware prediction -- which merges all of an (inlined or machine) | 
|  | // argument's variable access datas' predictions -- must possibly be Int52Any. | 
|  | return isInt32OrInt52Speculation(argumentAwarePrediction()); | 
|  | } | 
|  |  | 
|  | FlushFormat VariableAccessData::flushFormat() | 
|  | { | 
|  | ASSERT(find() == this); | 
|  |  | 
|  | if (!shouldUnboxIfPossible()) | 
|  | return FlushedJSValue; | 
|  |  | 
|  | if (shouldUseDoubleFormat()) | 
|  | return FlushedDouble; | 
|  |  | 
|  | SpeculatedType prediction = argumentAwarePrediction(); | 
|  |  | 
|  | // This guard is here to protect the call to couldRepresentInt52(), which will return | 
|  | // true for !prediction. | 
|  | if (!prediction) | 
|  | return FlushedJSValue; | 
|  |  | 
|  | if (isInt32Speculation(prediction)) | 
|  | return FlushedInt32; | 
|  |  | 
|  | if (couldRepresentInt52Impl()) | 
|  | return FlushedInt52; | 
|  |  | 
|  | if (isCellSpeculation(prediction)) | 
|  | return FlushedCell; | 
|  |  | 
|  | if (isBooleanSpeculation(prediction)) | 
|  | return FlushedBoolean; | 
|  |  | 
|  | return FlushedJSValue; | 
|  | } | 
|  |  | 
|  | } } // namespace JSC::DFG | 
|  |  | 
|  | #endif // ENABLE(DFG_JIT) | 
|  |  |