1/* 2 * Copyright (C) 2013, 2014 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 DFGSafeToExecute_h 27#define DFGSafeToExecute_h 28 29#if ENABLE(DFG_JIT) 30 31#include "DFGGraph.h" 32 33namespace JSC { namespace DFG { 34 35template<typename AbstractStateType> 36class SafeToExecuteEdge { 37public: 38 SafeToExecuteEdge(AbstractStateType& state) 39 : m_state(state) 40 , m_result(true) 41 { 42 } 43 44 void operator()(Node*, Edge edge) 45 { 46 switch (edge.useKind()) { 47 case UntypedUse: 48 case Int32Use: 49 case DoubleRepUse: 50 case DoubleRepRealUse: 51 case Int52RepUse: 52 case NumberUse: 53 case BooleanUse: 54 case CellUse: 55 case ObjectUse: 56 case FinalObjectUse: 57 case ObjectOrOtherUse: 58 case StringIdentUse: 59 case StringUse: 60 case StringObjectUse: 61 case StringOrStringObjectUse: 62 case NotStringVarUse: 63 case NotCellUse: 64 case OtherUse: 65 case MiscUse: 66 case MachineIntUse: 67 case DoubleRepMachineIntUse: 68 return; 69 70 case KnownInt32Use: 71 if (m_state.forNode(edge).m_type & ~SpecInt32) 72 m_result = false; 73 return; 74 75 case KnownCellUse: 76 if (m_state.forNode(edge).m_type & ~SpecCell) 77 m_result = false; 78 return; 79 80 case KnownStringUse: 81 if (m_state.forNode(edge).m_type & ~SpecString) 82 m_result = false; 83 return; 84 85 case LastUseKind: 86 RELEASE_ASSERT_NOT_REACHED(); 87 break; 88 } 89 RELEASE_ASSERT_NOT_REACHED(); 90 } 91 92 bool result() const { return m_result; } 93private: 94 AbstractStateType& m_state; 95 bool m_result; 96}; 97 98// Determines if it's safe to execute a node within the given abstract state. This may 99// return false conservatively. If it returns true, then you can hoist the given node 100// up to the given point and expect that it will not crash. This doesn't guarantee that 101// the node will produce the result you wanted other than not crashing. 102template<typename AbstractStateType> 103bool safeToExecute(AbstractStateType& state, Graph& graph, Node* node) 104{ 105 SafeToExecuteEdge<AbstractStateType> safeToExecuteEdge(state); 106 DFG_NODE_DO_TO_CHILDREN(graph, node, safeToExecuteEdge); 107 if (!safeToExecuteEdge.result()) 108 return false; 109 110 switch (node->op()) { 111 case JSConstant: 112 case DoubleConstant: 113 case Int52Constant: 114 case WeakJSConstant: 115 case Identity: 116 case ToThis: 117 case CreateThis: 118 case GetCallee: 119 case GetLocal: 120 case SetLocal: 121 case MovHint: 122 case ZombieHint: 123 case GetArgument: 124 case Phantom: 125 case HardPhantom: 126 case Upsilon: 127 case Phi: 128 case Flush: 129 case PhantomLocal: 130 case GetLocalUnlinked: 131 case SetArgument: 132 case BitAnd: 133 case BitOr: 134 case BitXor: 135 case BitLShift: 136 case BitRShift: 137 case BitURShift: 138 case ValueToInt32: 139 case UInt32ToNumber: 140 case DoubleAsInt32: 141 case ArithAdd: 142 case ArithSub: 143 case ArithNegate: 144 case ArithMul: 145 case ArithIMul: 146 case ArithDiv: 147 case ArithMod: 148 case ArithAbs: 149 case ArithMin: 150 case ArithMax: 151 case ArithSqrt: 152 case ArithFRound: 153 case ArithSin: 154 case ArithCos: 155 case ValueAdd: 156 case GetById: 157 case GetByIdFlush: 158 case PutById: 159 case PutByIdFlush: 160 case PutByIdDirect: 161 case CheckStructure: 162 case CheckExecutable: 163 case GetButterfly: 164 case CheckArray: 165 case Arrayify: 166 case ArrayifyToStructure: 167 case GetScope: 168 case GetMyScope: 169 case SkipTopScope: 170 case SkipScope: 171 case GetClosureRegisters: 172 case GetClosureVar: 173 case PutClosureVar: 174 case GetGlobalVar: 175 case PutGlobalVar: 176 case VariableWatchpoint: 177 case VarInjectionWatchpoint: 178 case CheckFunction: 179 case AllocationProfileWatchpoint: 180 case RegExpExec: 181 case RegExpTest: 182 case CompareLess: 183 case CompareLessEq: 184 case CompareGreater: 185 case CompareGreaterEq: 186 case CompareEq: 187 case CompareEqConstant: 188 case CompareStrictEq: 189 case Call: 190 case Construct: 191 case NewObject: 192 case NewArray: 193 case NewArrayWithSize: 194 case NewArrayBuffer: 195 case NewRegexp: 196 case Breakpoint: 197 case ProfileWillCall: 198 case ProfileDidCall: 199 case CheckHasInstance: 200 case InstanceOf: 201 case IsUndefined: 202 case IsBoolean: 203 case IsNumber: 204 case IsString: 205 case IsObject: 206 case IsFunction: 207 case TypeOf: 208 case LogicalNot: 209 case ToPrimitive: 210 case ToString: 211 case NewStringObject: 212 case MakeRope: 213 case In: 214 case CreateActivation: 215 case TearOffActivation: 216 case CreateArguments: 217 case PhantomArguments: 218 case TearOffArguments: 219 case GetMyArgumentsLength: 220 case GetMyArgumentByVal: 221 case GetMyArgumentsLengthSafe: 222 case GetMyArgumentByValSafe: 223 case CheckArgumentsNotCreated: 224 case NewFunctionNoCheck: 225 case NewFunction: 226 case NewFunctionExpression: 227 case Jump: 228 case Branch: 229 case Switch: 230 case Return: 231 case Throw: 232 case ThrowReferenceError: 233 case CountExecution: 234 case ForceOSRExit: 235 case CheckWatchdogTimer: 236 case StringFromCharCode: 237 case NewTypedArray: 238 case Unreachable: 239 case ExtractOSREntryLocal: 240 case CheckTierUpInLoop: 241 case CheckTierUpAtReturn: 242 case CheckTierUpAndOSREnter: 243 case LoopHint: 244 case StoreBarrier: 245 case StoreBarrierWithNullCheck: 246 case InvalidationPoint: 247 case NotifyWrite: 248 case FunctionReentryWatchpoint: 249 case TypedArrayWatchpoint: 250 case CheckInBounds: 251 case ConstantStoragePointer: 252 case Check: 253 case MultiGetByOffset: 254 case MultiPutByOffset: 255 case ValueRep: 256 case DoubleRep: 257 case Int52Rep: 258 case BooleanToNumber: 259 case FiatInt52: 260 return true; 261 262 case GetByVal: 263 case GetIndexedPropertyStorage: 264 case GetArrayLength: 265 case ArrayPush: 266 case ArrayPop: 267 case StringCharAt: 268 case StringCharCodeAt: 269 return node->arrayMode().alreadyChecked(graph, node, state.forNode(node->child1())); 270 271 case GetTypedArrayByteOffset: 272 return !(state.forNode(node->child1()).m_type & ~(SpecTypedArrayView)); 273 274 case PutByValDirect: 275 case PutByVal: 276 case PutByValAlias: 277 return node->arrayMode().modeForPut().alreadyChecked( 278 graph, node, state.forNode(graph.varArgChild(node, 0))); 279 280 case StructureTransitionWatchpoint: 281 return state.forNode(node->child1()).m_futurePossibleStructure.isSubsetOf( 282 StructureSet(node->structure())); 283 284 case PutStructure: 285 case PhantomPutStructure: 286 case AllocatePropertyStorage: 287 case ReallocatePropertyStorage: 288 return state.forNode(node->child1()).m_currentKnownStructure.isSubsetOf( 289 StructureSet(node->structureTransitionData().previousStructure)); 290 291 case GetByOffset: 292 case PutByOffset: 293 return state.forNode(node->child1()).m_currentKnownStructure.isValidOffset( 294 graph.m_storageAccessData[node->storageAccessDataIndex()].offset); 295 296 case LastNodeType: 297 RELEASE_ASSERT_NOT_REACHED(); 298 return false; 299 } 300 301 RELEASE_ASSERT_NOT_REACHED(); 302 return false; 303} 304 305} } // namespace JSC::DFG 306 307#endif // ENABLE(DFG_JIT) 308 309#endif // DFGSafeToExecute_h 310 311