| /* |
| * Copyright (C) 2012 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 "DFGArrayMode.h" |
| |
| #if ENABLE(DFG_JIT) |
| |
| #include "DFGAbstractValue.h" |
| |
| namespace JSC { namespace DFG { |
| |
| Array::Mode fromObserved(ArrayModes modes, bool makeSafe) |
| { |
| // FIXME: we may want to add some polymorphic support in the future. That's why this |
| // is a switch statement right now. |
| |
| switch (modes) { |
| case 0: |
| return Array::Undecided; |
| case IsJSArray: |
| return makeSafe ? Array::JSArrayOutOfBounds : Array::JSArray; |
| default: |
| // We know that this is possibly a kind of array for which, though there is no |
| // useful data in the array profile, we may be able to extract useful data from |
| // the value profiles of the inputs. Hence, we leave it as undecided, and let |
| // the predictions propagator decide later. |
| return Array::Undecided; |
| } |
| } |
| |
| Array::Mode refineArrayMode(Array::Mode arrayMode, SpeculatedType base, SpeculatedType index) |
| { |
| if (!base || !index) { |
| // It can be that we had a legitimate arrayMode but no incoming predictions. That'll |
| // happen if we inlined code based on, say, a global variable watchpoint, but later |
| // realized that the callsite could not have possibly executed. It may be worthwhile |
| // to fix that, but for now I'm leaving it as-is. |
| return Array::ForceExit; |
| } |
| |
| if (!isInt32Speculation(index) || !isCellSpeculation(base)) |
| return Array::Generic; |
| |
| // Pass through any array modes that would have been decided by the array profile, since |
| // the predictions of the inputs will not tell us anything useful that we didn't already |
| // get from the array profile. |
| switch (arrayMode) { |
| case Array::ForceExit: |
| case Array::JSArray: |
| case Array::JSArrayOutOfBounds: |
| return arrayMode; |
| default: |
| break; |
| } |
| |
| if (isStringSpeculation(base)) |
| return Array::String; |
| |
| if (isArgumentsSpeculation(base)) |
| return Array::Arguments; |
| |
| if (isInt8ArraySpeculation(base)) |
| return Array::Int8Array; |
| |
| if (isInt16ArraySpeculation(base)) |
| return Array::Int16Array; |
| |
| if (isInt32ArraySpeculation(base)) |
| return Array::Int32Array; |
| |
| if (isUint8ArraySpeculation(base)) |
| return Array::Uint8Array; |
| |
| if (isUint8ClampedArraySpeculation(base)) |
| return Array::Uint8ClampedArray; |
| |
| if (isUint16ArraySpeculation(base)) |
| return Array::Uint16Array; |
| |
| if (isUint32ArraySpeculation(base)) |
| return Array::Uint32Array; |
| |
| if (isFloat32ArraySpeculation(base)) |
| return Array::Float32Array; |
| |
| if (isFloat64ArraySpeculation(base)) |
| return Array::Float64Array; |
| |
| return Array::Generic; |
| } |
| |
| bool modeAlreadyChecked(AbstractValue& value, Array::Mode arrayMode) |
| { |
| switch (arrayMode) { |
| case Array::Generic: |
| return true; |
| |
| case Array::ForceExit: |
| return false; |
| |
| case Array::String: |
| return isStringSpeculation(value.m_type); |
| |
| case Array::JSArray: |
| case Array::JSArrayOutOfBounds: |
| return value.m_currentKnownStructure.hasSingleton() |
| && value.m_currentKnownStructure.singleton()->classInfo() == &JSArray::s_info; |
| |
| case Array::Arguments: |
| return isArgumentsSpeculation(value.m_type); |
| |
| case Array::Int8Array: |
| return isInt8ArraySpeculation(value.m_type); |
| |
| case Array::Int16Array: |
| return isInt16ArraySpeculation(value.m_type); |
| |
| case Array::Int32Array: |
| return isInt32ArraySpeculation(value.m_type); |
| |
| case Array::Uint8Array: |
| return isUint8ArraySpeculation(value.m_type); |
| |
| case Array::Uint8ClampedArray: |
| return isUint8ClampedArraySpeculation(value.m_type); |
| |
| case Array::Uint16Array: |
| return isUint16ArraySpeculation(value.m_type); |
| |
| case Array::Uint32Array: |
| return isUint32ArraySpeculation(value.m_type); |
| |
| case Array::Float32Array: |
| return isFloat32ArraySpeculation(value.m_type); |
| |
| case Array::Float64Array: |
| return isFloat64ArraySpeculation(value.m_type); |
| |
| case Array::Undecided: |
| break; |
| } |
| |
| ASSERT_NOT_REACHED(); |
| return false; |
| } |
| |
| const char* modeToString(Array::Mode mode) |
| { |
| switch (mode) { |
| case Array::Undecided: |
| return "Undecided"; |
| case Array::Generic: |
| return "Generic"; |
| case Array::ForceExit: |
| return "ForceExit"; |
| case Array::String: |
| return "String"; |
| case Array::JSArray: |
| return "JSArray"; |
| case Array::JSArrayOutOfBounds: |
| return "JSArrayOutOfBounds"; |
| case Array::Arguments: |
| return "Arguments"; |
| case Array::Int8Array: |
| return "Int8Array"; |
| case Array::Int16Array: |
| return "Int16Array"; |
| case Array::Int32Array: |
| return "Int32Array"; |
| case Array::Uint8Array: |
| return "Uint8Array"; |
| case Array::Uint8ClampedArray: |
| return "Uint8ClampedArray"; |
| case Array::Uint16Array: |
| return "Uint16Array"; |
| case Array::Uint32Array: |
| return "Uint32Array"; |
| case Array::Float32Array: |
| return "Float32Array"; |
| case Array::Float64Array: |
| return "Float64Array"; |
| default: |
| // Better to return something then it is to crash. Remember, this method |
| // is being called from our main diagnostic tool, the IR dumper. It's like |
| // a stack trace. So if we get here then probably something has already |
| // gone wrong. |
| return "Unknown!"; |
| } |
| } |
| |
| } } // namespace JSC::DFG |
| |
| #endif // ENABLE(DFG_JIT) |
| |