1/* 2 * Copyright (C) 2012, 2013 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#ifndef DFGArrayifySlowPathGenerator_h 27#define DFGArrayifySlowPathGenerator_h 28 29#if ENABLE(DFG_JIT) 30 31#include "DFGArrayMode.h" 32#include "DFGCommon.h" 33#include "DFGOSRExitJumpPlaceholder.h" 34#include "DFGOperations.h" 35#include "DFGSlowPathGenerator.h" 36#include "DFGSpeculativeJIT.h" 37#include <wtf/Vector.h> 38 39namespace JSC { namespace DFG { 40 41class ArrayifySlowPathGenerator : public JumpingSlowPathGenerator<MacroAssembler::JumpList> { 42public: 43 ArrayifySlowPathGenerator( 44 const MacroAssembler::JumpList& from, SpeculativeJIT* jit, Node* node, GPRReg baseGPR, 45 GPRReg propertyGPR, GPRReg tempGPR, GPRReg structureGPR) 46 : JumpingSlowPathGenerator<MacroAssembler::JumpList>(from, jit) 47 , m_op(node->op()) 48 , m_arrayMode(node->arrayMode()) 49 , m_structure(node->op() == ArrayifyToStructure ? node->structure() : 0) 50 , m_baseGPR(baseGPR) 51 , m_propertyGPR(propertyGPR) 52 , m_tempGPR(tempGPR) 53 , m_structureGPR(structureGPR) 54 { 55 ASSERT(m_op == Arrayify || m_op == ArrayifyToStructure); 56 57 jit->silentSpillAllRegistersImpl(false, m_plans, InvalidGPRReg); 58 59 if (m_propertyGPR != InvalidGPRReg) { 60 switch (m_arrayMode.type()) { 61 case Array::Int32: 62 case Array::Double: 63 case Array::Contiguous: 64 m_badPropertyJump = jit->speculationCheck(Uncountable, JSValueRegs(), 0); 65 break; 66 default: 67 break; 68 } 69 } 70 m_badIndexingTypeJump = jit->speculationCheck(BadIndexingType, JSValueSource::unboxedCell(m_baseGPR), 0); 71 } 72 73protected: 74 virtual void generateInternal(SpeculativeJIT* jit) override 75 { 76 linkFrom(jit); 77 78 ASSERT(m_op == Arrayify || m_op == ArrayifyToStructure); 79 80 if (m_propertyGPR != InvalidGPRReg) { 81 switch (m_arrayMode.type()) { 82 case Array::Int32: 83 case Array::Double: 84 case Array::Contiguous: 85 m_badPropertyJump.fill(jit, jit->m_jit.branch32( 86 MacroAssembler::AboveOrEqual, m_propertyGPR, 87 MacroAssembler::TrustedImm32(MIN_SPARSE_ARRAY_INDEX))); 88 break; 89 default: 90 break; 91 } 92 } 93 94 for (unsigned i = 0; i < m_plans.size(); ++i) 95 jit->silentSpill(m_plans[i]); 96 switch (m_arrayMode.type()) { 97 case Array::Int32: 98 jit->callOperation(operationEnsureInt32, m_tempGPR, m_baseGPR); 99 break; 100 case Array::Double: 101 jit->callOperation(operationEnsureDouble, m_tempGPR, m_baseGPR); 102 break; 103 case Array::Contiguous: 104 if (m_arrayMode.conversion() == Array::RageConvert) 105 jit->callOperation(operationRageEnsureContiguous, m_tempGPR, m_baseGPR); 106 else 107 jit->callOperation(operationEnsureContiguous, m_tempGPR, m_baseGPR); 108 break; 109 case Array::ArrayStorage: 110 case Array::SlowPutArrayStorage: 111 jit->callOperation(operationEnsureArrayStorage, m_tempGPR, m_baseGPR); 112 break; 113 default: 114 CRASH(); 115 break; 116 } 117 for (unsigned i = m_plans.size(); i--;) 118 jit->silentFill(m_plans[i], GPRInfo::regT0); 119 120 if (m_op == ArrayifyToStructure) { 121 ASSERT(m_structure); 122 m_badIndexingTypeJump.fill( 123 jit, jit->m_jit.branchWeakStructure(MacroAssembler::NotEqual, MacroAssembler::Address(m_baseGPR, JSCell::structureIDOffset()), m_structure)); 124 } else { 125 // Finally, check that we have the kind of array storage that we wanted to get. 126 // Note that this is a backwards speculation check, which will result in the 127 // bytecode operation corresponding to this arrayification being reexecuted. 128 // That's fine, since arrayification is not user-visible. 129 jit->m_jit.load8( 130 MacroAssembler::Address(m_baseGPR, JSCell::indexingTypeOffset()), m_structureGPR); 131 m_badIndexingTypeJump.fill( 132 jit, jit->jumpSlowForUnwantedArrayMode(m_structureGPR, m_arrayMode)); 133 } 134 135 jumpTo(jit); 136 } 137 138private: 139 NodeType m_op; 140 ArrayMode m_arrayMode; 141 Structure* m_structure; 142 GPRReg m_baseGPR; 143 GPRReg m_propertyGPR; 144 GPRReg m_tempGPR; 145 GPRReg m_structureGPR; 146 OSRExitJumpPlaceholder m_badPropertyJump; 147 OSRExitJumpPlaceholder m_badIndexingTypeJump; 148 Vector<SilentRegisterSavePlan, 2> m_plans; 149}; 150 151} } // namespace JSC::DFG 152 153#endif // ENABLE(DFG_JIT) 154 155#endif // DFGArrayifySlowPathGenerator_h 156 157