oliver@apple.com | 83d2d02 | 2013-07-25 04:05:20 +0000 | [diff] [blame] | 1 | /* |
mark.lam@apple.com | eb19fea | 2014-01-23 23:13:23 +0000 | [diff] [blame] | 2 | * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. |
oliver@apple.com | 83d2d02 | 2013-07-25 04:05:20 +0000 | [diff] [blame] | 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 | |
oliver@apple.com | 83d2d02 | 2013-07-25 04:05:20 +0000 | [diff] [blame] | 29 | #if ENABLE(DFG_JIT) |
| 30 | |
| 31 | #include "DFGGraph.h" |
| 32 | |
| 33 | namespace JSC { namespace DFG { |
| 34 | |
| 35 | template<typename AbstractStateType> |
| 36 | class SafeToExecuteEdge { |
| 37 | public: |
| 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 RealNumberUse: |
| 50 | case NumberUse: |
| 51 | case BooleanUse: |
| 52 | case CellUse: |
| 53 | case ObjectUse: |
fpizlo@apple.com | 0fa8386 | 2013-09-06 19:01:21 +0000 | [diff] [blame] | 54 | case FinalObjectUse: |
oliver@apple.com | 83d2d02 | 2013-07-25 04:05:20 +0000 | [diff] [blame] | 55 | case ObjectOrOtherUse: |
| 56 | case StringIdentUse: |
| 57 | case StringUse: |
| 58 | case StringObjectUse: |
| 59 | case StringOrStringObjectUse: |
fpizlo@apple.com | 385a33a | 2014-03-18 20:53:07 +0000 | [diff] [blame^] | 60 | case NotStringVarUse: |
oliver@apple.com | 83d2d02 | 2013-07-25 04:05:20 +0000 | [diff] [blame] | 61 | case NotCellUse: |
| 62 | case OtherUse: |
fpizlo@apple.com | e079bb5 | 2014-03-05 07:41:03 +0000 | [diff] [blame] | 63 | case MiscUse: |
fpizlo@apple.com | 6921b29 | 2013-09-18 17:14:02 +0000 | [diff] [blame] | 64 | case MachineIntUse: |
oliver@apple.com | 83d2d02 | 2013-07-25 04:05:20 +0000 | [diff] [blame] | 65 | return; |
| 66 | |
| 67 | case KnownInt32Use: |
| 68 | if (m_state.forNode(edge).m_type & ~SpecInt32) |
| 69 | m_result = false; |
| 70 | return; |
| 71 | |
| 72 | case KnownNumberUse: |
fpizlo@apple.com | 6921b29 | 2013-09-18 17:14:02 +0000 | [diff] [blame] | 73 | if (m_state.forNode(edge).m_type & ~SpecFullNumber) |
oliver@apple.com | 83d2d02 | 2013-07-25 04:05:20 +0000 | [diff] [blame] | 74 | m_result = false; |
| 75 | return; |
| 76 | |
| 77 | case KnownCellUse: |
| 78 | if (m_state.forNode(edge).m_type & ~SpecCell) |
| 79 | m_result = false; |
| 80 | return; |
| 81 | |
| 82 | case KnownStringUse: |
| 83 | if (m_state.forNode(edge).m_type & ~SpecString) |
| 84 | m_result = false; |
| 85 | return; |
| 86 | |
| 87 | case LastUseKind: |
| 88 | RELEASE_ASSERT_NOT_REACHED(); |
| 89 | break; |
| 90 | } |
| 91 | RELEASE_ASSERT_NOT_REACHED(); |
| 92 | } |
| 93 | |
| 94 | bool result() const { return m_result; } |
| 95 | private: |
| 96 | AbstractStateType& m_state; |
| 97 | bool m_result; |
| 98 | }; |
| 99 | |
| 100 | // Determines if it's safe to execute a node within the given abstract state. This may |
| 101 | // return false conservatively. If it returns true, then you can hoist the given node |
| 102 | // up to the given point and expect that it will not crash. This doesn't guarantee that |
| 103 | // the node will produce the result you wanted other than not crashing. |
| 104 | template<typename AbstractStateType> |
| 105 | bool safeToExecute(AbstractStateType& state, Graph& graph, Node* node) |
| 106 | { |
| 107 | SafeToExecuteEdge<AbstractStateType> safeToExecuteEdge(state); |
| 108 | DFG_NODE_DO_TO_CHILDREN(graph, node, safeToExecuteEdge); |
| 109 | if (!safeToExecuteEdge.result()) |
| 110 | return false; |
| 111 | |
| 112 | switch (node->op()) { |
| 113 | case JSConstant: |
| 114 | case WeakJSConstant: |
| 115 | case Identity: |
| 116 | case ToThis: |
| 117 | case CreateThis: |
| 118 | case GetCallee: |
oliver@apple.com | 83d2d02 | 2013-07-25 04:05:20 +0000 | [diff] [blame] | 119 | case GetLocal: |
| 120 | case SetLocal: |
oliver@apple.com | 83d2d02 | 2013-07-25 04:05:20 +0000 | [diff] [blame] | 121 | case MovHint: |
| 122 | case ZombieHint: |
| 123 | case GetArgument: |
| 124 | case Phantom: |
fpizlo@apple.com | 4c96a84 | 2014-02-13 22:46:51 +0000 | [diff] [blame] | 125 | case HardPhantom: |
oliver@apple.com | 83d2d02 | 2013-07-25 04:05:20 +0000 | [diff] [blame] | 126 | case Upsilon: |
| 127 | case Phi: |
| 128 | case Flush: |
| 129 | case PhantomLocal: |
| 130 | case GetLocalUnlinked: |
| 131 | case SetArgument: |
oliver@apple.com | 83d2d02 | 2013-07-25 04:05:20 +0000 | [diff] [blame] | 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 Int32ToDouble: |
oliver@apple.com | 83d2d02 | 2013-07-25 04:05:20 +0000 | [diff] [blame] | 141 | case DoubleAsInt32: |
| 142 | case ArithAdd: |
| 143 | case ArithSub: |
| 144 | case ArithNegate: |
| 145 | case ArithMul: |
| 146 | case ArithIMul: |
| 147 | case ArithDiv: |
| 148 | case ArithMod: |
| 149 | case ArithAbs: |
| 150 | case ArithMin: |
| 151 | case ArithMax: |
| 152 | case ArithSqrt: |
fpizlo@apple.com | b3336c7 | 2013-10-31 19:19:15 +0000 | [diff] [blame] | 153 | case ArithSin: |
| 154 | case ArithCos: |
oliver@apple.com | 83d2d02 | 2013-07-25 04:05:20 +0000 | [diff] [blame] | 155 | case ValueAdd: |
| 156 | case GetById: |
| 157 | case GetByIdFlush: |
| 158 | case PutById: |
oliver@apple.com | 11ce5ff | 2014-03-06 21:27:13 +0000 | [diff] [blame] | 159 | case PutByIdFlush: |
oliver@apple.com | 83d2d02 | 2013-07-25 04:05:20 +0000 | [diff] [blame] | 160 | case PutByIdDirect: |
| 161 | case CheckStructure: |
| 162 | case CheckExecutable: |
oliver@apple.com | 83d2d02 | 2013-07-25 04:05:20 +0000 | [diff] [blame] | 163 | case GetButterfly: |
| 164 | case CheckArray: |
oliver@apple.com | 83d2d02 | 2013-07-25 04:05:20 +0000 | [diff] [blame] | 165 | case Arrayify: |
| 166 | case ArrayifyToStructure: |
| 167 | case GetScope: |
| 168 | case GetMyScope: |
oliver@apple.com | 83d2d02 | 2013-07-25 04:05:20 +0000 | [diff] [blame] | 169 | case SkipTopScope: |
| 170 | case SkipScope: |
| 171 | case GetClosureRegisters: |
| 172 | case GetClosureVar: |
| 173 | case PutClosureVar: |
| 174 | case GetGlobalVar: |
| 175 | case PutGlobalVar: |
fpizlo@apple.com | 8646834 | 2013-11-27 02:47:43 +0000 | [diff] [blame] | 176 | case VariableWatchpoint: |
oliver@apple.com | 83d2d02 | 2013-07-25 04:05:20 +0000 | [diff] [blame] | 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: |
oliver@apple.com | 83d2d02 | 2013-07-25 04:05:20 +0000 | [diff] [blame] | 189 | case Call: |
| 190 | case Construct: |
| 191 | case NewObject: |
| 192 | case NewArray: |
| 193 | case NewArrayWithSize: |
| 194 | case NewArrayBuffer: |
| 195 | case NewRegexp: |
| 196 | case Breakpoint: |
mark.lam@apple.com | eb19fea | 2014-01-23 23:13:23 +0000 | [diff] [blame] | 197 | case ProfileWillCall: |
| 198 | case ProfileDidCall: |
oliver@apple.com | 83d2d02 | 2013-07-25 04:05:20 +0000 | [diff] [blame] | 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: |
oliver@apple.com | 83d2d02 | 2013-07-25 04:05:20 +0000 | [diff] [blame] | 235 | case CheckWatchdogTimer: |
| 236 | case StringFromCharCode: |
fpizlo@apple.com | 372fa82 | 2013-08-21 19:43:47 +0000 | [diff] [blame] | 237 | case NewTypedArray: |
oliver@apple.com | 1fc0418 | 2013-08-19 19:40:13 +0000 | [diff] [blame] | 238 | case Unreachable: |
fpizlo@apple.com | 532f1e5 | 2013-09-04 06:26:04 +0000 | [diff] [blame] | 239 | case ExtractOSREntryLocal: |
| 240 | case CheckTierUpInLoop: |
| 241 | case CheckTierUpAtReturn: |
| 242 | case CheckTierUpAndOSREnter: |
| 243 | case LoopHint: |
fpizlo@apple.com | 6921b29 | 2013-09-18 17:14:02 +0000 | [diff] [blame] | 244 | case Int52ToDouble: |
| 245 | case Int52ToValue: |
mhahnenberg@apple.com | 4968e1a | 2013-12-18 22:50:40 +0000 | [diff] [blame] | 246 | case StoreBarrier: |
mhahnenberg@apple.com | 4968e1a | 2013-12-18 22:50:40 +0000 | [diff] [blame] | 247 | case StoreBarrierWithNullCheck: |
fpizlo@apple.com | d84425d | 2013-10-30 19:58:08 +0000 | [diff] [blame] | 248 | case InvalidationPoint: |
fpizlo@apple.com | 8646834 | 2013-11-27 02:47:43 +0000 | [diff] [blame] | 249 | case NotifyWrite: |
fpizlo@apple.com | a4ea066 | 2013-12-02 19:09:15 +0000 | [diff] [blame] | 250 | case FunctionReentryWatchpoint: |
fpizlo@apple.com | ce995b2 | 2013-12-08 19:01:17 +0000 | [diff] [blame] | 251 | case TypedArrayWatchpoint: |
fpizlo@apple.com | 8624c4b | 2013-12-10 03:24:31 +0000 | [diff] [blame] | 252 | case CheckInBounds: |
fpizlo@apple.com | 9ca951e | 2013-12-09 01:08:53 +0000 | [diff] [blame] | 253 | case ConstantStoragePointer: |
fpizlo@apple.com | 9df7fef | 2013-12-29 21:50:55 +0000 | [diff] [blame] | 254 | case Check: |
fpizlo@apple.com | 51614cc | 2014-02-17 06:35:32 +0000 | [diff] [blame] | 255 | case MultiGetByOffset: |
fpizlo@apple.com | 4321952 | 2014-02-25 02:02:50 +0000 | [diff] [blame] | 256 | case MultiPutByOffset: |
oliver@apple.com | 83d2d02 | 2013-07-25 04:05:20 +0000 | [diff] [blame] | 257 | return true; |
| 258 | |
| 259 | case GetByVal: |
| 260 | case GetIndexedPropertyStorage: |
| 261 | case GetArrayLength: |
| 262 | case ArrayPush: |
| 263 | case ArrayPop: |
| 264 | case StringCharAt: |
| 265 | case StringCharCodeAt: |
| 266 | return node->arrayMode().alreadyChecked(graph, node, state.forNode(node->child1())); |
| 267 | |
fpizlo@apple.com | 537a477 | 2013-08-19 23:16:01 +0000 | [diff] [blame] | 268 | case GetTypedArrayByteOffset: |
| 269 | return !(state.forNode(node->child1()).m_type & ~(SpecTypedArrayView)); |
oliver@apple.com | e050d64 | 2013-10-19 00:09:28 +0000 | [diff] [blame] | 270 | |
| 271 | case PutByValDirect: |
oliver@apple.com | 83d2d02 | 2013-07-25 04:05:20 +0000 | [diff] [blame] | 272 | case PutByVal: |
| 273 | case PutByValAlias: |
| 274 | return node->arrayMode().modeForPut().alreadyChecked( |
| 275 | graph, node, state.forNode(graph.varArgChild(node, 0))); |
| 276 | |
| 277 | case StructureTransitionWatchpoint: |
oliver@apple.com | 83d2d02 | 2013-07-25 04:05:20 +0000 | [diff] [blame] | 278 | return state.forNode(node->child1()).m_futurePossibleStructure.isSubsetOf( |
| 279 | StructureSet(node->structure())); |
| 280 | |
| 281 | case PutStructure: |
| 282 | case PhantomPutStructure: |
| 283 | case AllocatePropertyStorage: |
| 284 | case ReallocatePropertyStorage: |
| 285 | return state.forNode(node->child1()).m_currentKnownStructure.isSubsetOf( |
| 286 | StructureSet(node->structureTransitionData().previousStructure)); |
| 287 | |
| 288 | case GetByOffset: |
| 289 | case PutByOffset: |
| 290 | return state.forNode(node->child1()).m_currentKnownStructure.isValidOffset( |
| 291 | graph.m_storageAccessData[node->storageAccessDataIndex()].offset); |
| 292 | |
| 293 | case LastNodeType: |
| 294 | RELEASE_ASSERT_NOT_REACHED(); |
| 295 | return false; |
| 296 | } |
| 297 | |
| 298 | RELEASE_ASSERT_NOT_REACHED(); |
| 299 | return false; |
| 300 | } |
| 301 | |
| 302 | } } // namespace JSC::DFG |
| 303 | |
| 304 | #endif // ENABLE(DFG_JIT) |
| 305 | |
| 306 | #endif // DFGSafeToExecute_h |
| 307 | |