DFGNodeType.h 15.1 KB
Newer Older
1
/*
2
 * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
 *
 * 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. 
 */

#ifndef DFGNodeType_h
#define DFGNodeType_h

#include <wtf/Platform.h>

#if ENABLE(DFG_JIT)

#include "DFGNodeFlags.h"

namespace JSC { namespace DFG {

// This macro defines a set of information about all known node types, used to populate NodeId, NodeType below.
#define FOR_EACH_DFG_OP(macro) \
    /* A constant in the CodeBlock's constant pool. */\
40
    macro(JSConstant, NodeResultJS | NodeDoesNotExit) \
41 42 43
    \
    /* A constant not in the CodeBlock's constant pool. Uses get patched to jumps that exit the */\
    /* code block. */\
44
    macro(WeakJSConstant, NodeResultJS | NodeDoesNotExit) \
45
    \
46 47 48
    /* Marker to indicate that an operation was optimized entirely and all that is left */\
    /* is to make one node alias another. CSE will later usually eliminate this node, */\
    /* though it may choose not to if it would corrupt predictions (very rare). */\
49
    macro(Identity, NodeResultJS) \
50
    \
51
    /* Nodes for handling functions (both as call and as construct). */\
52
    macro(ToThis, NodeResultJS) \
53 54 55
    macro(CreateThis, NodeResultJS) /* Note this is not MustGenerate since we're returning it anyway. */ \
    macro(GetCallee, NodeResultJS) \
    \
56 57 58
    /* Nodes for local variable access. These nodes are linked together using Phi nodes. */\
    /* Any two nodes that are part of the same Phi graph will share the same */\
    /* VariableAccessData, and thus will share predictions. */\
59
    macro(GetLocal, NodeResultJS) \
60
    macro(SetLocal, 0) \
61 62
    macro(MovHint, NodeDoesNotExit) \
    macro(ZombieHint, NodeDoesNotExit) \
63
    macro(GetArgument, NodeResultJS | NodeMustGenerate) \
64
    macro(Phantom, NodeMustGenerate) \
65
    macro(Check, 0) /* Used if we want just a type check but not liveness. DCE eithers kills this or converts it to Phantom. */\
66
    macro(Upsilon, NodeDoesNotExit | NodeRelevantToOSR) \
67
    macro(Phi, NodeDoesNotExit | NodeRelevantToOSR) \
68
    macro(Flush, NodeMustGenerate | NodeDoesNotExit) \
69
    macro(PhantomLocal, NodeMustGenerate | NodeDoesNotExit) \
70
    \
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
    /* Hint that this is where bytecode thinks is a good place to OSR. Note that this */\
    /* will exist even in inlined loops. This has no execution semantics but it must */\
    /* survive all DCE. We treat this as being a can-exit because tier-up to FTL may */\
    /* want all state. */\
    macro(LoopHint, NodeMustGenerate) \
    \
    /* Special node for OSR entry into the FTL. Indicates that we're loading a local */\
    /* variable from the scratch buffer. */\
    macro(ExtractOSREntryLocal, NodeResultJS) \
    \
    /* Tier-up checks from the DFG to the FTL. */\
    macro(CheckTierUpInLoop, NodeMustGenerate) \
    macro(CheckTierUpAndOSREnter, NodeMustGenerate) \
    macro(CheckTierUpAtReturn, NodeMustGenerate) \
    \
86 87 88 89 90
    /* Get the value of a local variable, without linking into the VariableAccessData */\
    /* network. This is only valid for variable accesses whose predictions originated */\
    /* as something other than a local access, and thus had their own profiling. */\
    macro(GetLocalUnlinked, NodeResultJS) \
    \
91
    /* Marker for an argument being set at the prologue of a function. */\
92 93 94 95 96
    macro(SetArgument, NodeDoesNotExit) \
    \
    /* Marker of location in the IR where we may possibly perform jump replacement to */\
    /* invalidate this code block. */\
    macro(InvalidationPoint, NodeMustGenerate) \
97 98
    \
    /* Nodes for bitwise operations. */\
fpizlo@apple.com's avatar
fpizlo@apple.com committed
99 100 101 102 103 104
    macro(BitAnd, NodeResultInt32) \
    macro(BitOr, NodeResultInt32) \
    macro(BitXor, NodeResultInt32) \
    macro(BitLShift, NodeResultInt32) \
    macro(BitRShift, NodeResultInt32) \
    macro(BitURShift, NodeResultInt32) \
105
    /* Bitwise operators call ToInt32 on their operands. */\
106
    macro(ValueToInt32, NodeResultInt32) \
107
    /* Used to box the result of URShift nodes (result has range 0..2^32-1). */\
108
    macro(UInt32ToNumber, NodeResultNumber) \
109
    \
110 111 112
    /* Used to cast known integers to doubles, so as to separate the double form */\
    /* of the value from the integer form. */\
    macro(Int32ToDouble, NodeResultNumber) \
113
    /* Used to speculate that a double value is actually an integer. */\
114
    macro(DoubleAsInt32, NodeResultInt32) \
115 116 117 118
    /* Used to separate representation and register allocation of Int52's represented */\
    /* as values. */\
    macro(Int52ToValue, NodeResultJS) \
    macro(Int52ToDouble, NodeResultNumber) \
119 120
    \
    /* Nodes for arithmetic operations. */\
fpizlo@apple.com's avatar
fpizlo@apple.com committed
121 122 123 124 125 126 127 128 129 130 131 132 133
    macro(ArithAdd, NodeResultNumber) \
    macro(ArithSub, NodeResultNumber) \
    macro(ArithNegate, NodeResultNumber) \
    macro(ArithMul, NodeResultNumber) \
    macro(ArithIMul, NodeResultInt32) \
    macro(ArithDiv, NodeResultNumber) \
    macro(ArithMod, NodeResultNumber) \
    macro(ArithAbs, NodeResultNumber) \
    macro(ArithMin, NodeResultNumber) \
    macro(ArithMax, NodeResultNumber) \
    macro(ArithSqrt, NodeResultNumber) \
    macro(ArithSin, NodeResultNumber) \
    macro(ArithCos, NodeResultNumber) \
134 135
    \
    /* Add of values may either be arithmetic, or result in string concatenation. */\
fpizlo@apple.com's avatar
fpizlo@apple.com committed
136
    macro(ValueAdd, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
137 138 139 140
    \
    /* Property access. */\
    /* PutByValAlias indicates a 'put' aliases a prior write to the same property. */\
    /* Since a put to 'length' may invalidate optimizations here, */\
141 142
    /* this must be the directly subsequent property put. Note that PutByVal */\
    /* opcodes use VarArgs beause they may have up to 4 children. */\
143
    macro(GetByVal, NodeResultJS | NodeMustGenerate | NodeMightClobber) \
144
    macro(PutByValDirect, NodeMustGenerate | NodeHasVarArgs | NodeMightClobber) \
145 146
    macro(PutByVal, NodeMustGenerate | NodeHasVarArgs | NodeMightClobber) \
    macro(PutByValAlias, NodeMustGenerate | NodeHasVarArgs | NodeMightClobber) \
147 148 149 150 151
    macro(GetById, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
    macro(GetByIdFlush, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
    macro(PutById, NodeMustGenerate | NodeClobbersWorld) \
    macro(PutByIdDirect, NodeMustGenerate | NodeClobbersWorld) \
    macro(CheckStructure, NodeMustGenerate) \
152
    macro(CheckExecutable, NodeMustGenerate) \
153 154 155 156 157 158 159 160 161 162 163 164
    /* Transition watchpoints are a contract between the party setting the watchpoint */\
    /* and the runtime system, where the party promises that the child object once had */\
    /* the structure being watched, and the runtime system in turn promises that the */\
    /* watchpoint will be turned into an OSR exit if any object with that structure */\
    /* ever transitions to a different structure. Hence, the child object must have */\
    /* previously had a CheckStructure executed on it or we're dealing with an object */\
    /* constant (WeakJSConstant) and the object was known to have that structure at */\
    /* compile-time. In the latter case this means that no structure checks have to be */\
    /* performed for this object by JITted code. In the former case this means that*/\
    /* the object's structure does not need to be rechecked due to side-effecting */\
    /* (clobbering) operations. */\
    macro(StructureTransitionWatchpoint, NodeMustGenerate) \
165 166
    macro(PutStructure, NodeMustGenerate) \
    macro(PhantomPutStructure, NodeMustGenerate | NodeDoesNotExit) \
167 168
    macro(AllocatePropertyStorage, NodeMustGenerate | NodeDoesNotExit | NodeResultStorage) \
    macro(ReallocatePropertyStorage, NodeMustGenerate | NodeDoesNotExit | NodeResultStorage) \
169
    macro(GetButterfly, NodeResultStorage) \
170
    macro(CheckArray, NodeMustGenerate) \
171 172
    macro(Arrayify, NodeMustGenerate) \
    macro(ArrayifyToStructure, NodeMustGenerate) \
173
    macro(GetIndexedPropertyStorage, NodeResultStorage) \
174
    macro(ConstantStoragePointer, NodeResultStorage) \
175
    macro(TypedArrayWatchpoint, NodeMustGenerate) \
176
    macro(GetByOffset, NodeResultJS) \
177
    macro(PutByOffset, NodeMustGenerate) \
178
    macro(GetArrayLength, NodeResultInt32) \
179
    macro(GetTypedArrayByteOffset, NodeResultInt32) \
180
    macro(GetScope, NodeResultJS) \
181 182 183
    macro(GetMyScope, NodeResultJS) \
    macro(SkipTopScope, NodeResultJS) \
    macro(SkipScope, NodeResultJS) \
184 185 186
    macro(GetClosureRegisters, NodeResultStorage) \
    macro(GetClosureVar, NodeResultJS) \
    macro(PutClosureVar, NodeMustGenerate) \
187
    macro(GetGlobalVar, NodeResultJS) \
188
    macro(PutGlobalVar, NodeMustGenerate) \
189 190
    macro(NotifyWrite, NodeMustGenerate) \
    macro(VariableWatchpoint, NodeMustGenerate) \
191
    macro(VarInjectionWatchpoint, NodeMustGenerate) \
192
    macro(FunctionReentryWatchpoint, NodeMustGenerate) \
193
    macro(CheckFunction, NodeMustGenerate) \
194
    macro(AllocationProfileWatchpoint, NodeMustGenerate) \
195
    macro(CheckInBounds, NodeMustGenerate) \
196 197 198 199 200
    \
    /* Optimizations for array mutation. */\
    macro(ArrayPush, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
    macro(ArrayPop, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
    \
201 202 203 204
    /* Optimizations for regular expression matching. */\
    macro(RegExpExec, NodeResultJS | NodeMustGenerate) \
    macro(RegExpTest, NodeResultJS | NodeMustGenerate) \
    \
205 206 207
    /* Optimizations for string access */ \
    macro(StringCharCodeAt, NodeResultInt32) \
    macro(StringCharAt, NodeResultJS) \
208
    macro(StringFromCharCode, NodeResultJS) \
209 210
    \
    /* Nodes for comparison operations. */\
fpizlo@apple.com's avatar
fpizlo@apple.com committed
211 212 213 214 215 216
    macro(CompareLess, NodeResultBoolean | NodeMustGenerate | NodeClobbersWorld) \
    macro(CompareLessEq, NodeResultBoolean | NodeMustGenerate | NodeClobbersWorld) \
    macro(CompareGreater, NodeResultBoolean | NodeMustGenerate | NodeClobbersWorld) \
    macro(CompareGreaterEq, NodeResultBoolean | NodeMustGenerate | NodeClobbersWorld) \
    macro(CompareEq, NodeResultBoolean | NodeMustGenerate | NodeClobbersWorld) \
    macro(CompareEqConstant, NodeResultBoolean) \
217
    macro(CompareStrictEq, NodeResultBoolean) \
218
    macro(CompareStrictEqConstant, NodeResultBoolean) \
219 220 221 222 223 224 225 226
    \
    /* Calls. */\
    macro(Call, NodeResultJS | NodeMustGenerate | NodeHasVarArgs | NodeClobbersWorld) \
    macro(Construct, NodeResultJS | NodeMustGenerate | NodeHasVarArgs | NodeClobbersWorld) \
    \
    /* Allocations. */\
    macro(NewObject, NodeResultJS) \
    macro(NewArray, NodeResultJS | NodeHasVarArgs) \
227
    macro(NewArrayWithSize, NodeResultJS) \
228
    macro(NewArrayBuffer, NodeResultJS) \
229
    macro(NewTypedArray, NodeResultJS | NodeClobbersWorld | NodeMustGenerate) \
230 231 232 233 234 235
    macro(NewRegexp, NodeResultJS) \
    \
    /* Nodes for misc operations. */\
    macro(Breakpoint, NodeMustGenerate | NodeClobbersWorld) \
    macro(CheckHasInstance, NodeMustGenerate) \
    macro(InstanceOf, NodeResultBoolean) \
236 237 238 239 240 241
    macro(IsUndefined, NodeResultBoolean) \
    macro(IsBoolean, NodeResultBoolean) \
    macro(IsNumber, NodeResultBoolean) \
    macro(IsString, NodeResultBoolean) \
    macro(IsObject, NodeResultBoolean) \
    macro(IsFunction, NodeResultBoolean) \
242
    macro(TypeOf, NodeResultJS) \
243
    macro(LogicalNot, NodeResultBoolean) \
244
    macro(ToPrimitive, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
245 246
    macro(ToString, NodeResultJS | NodeMustGenerate | NodeMightClobber) \
    macro(NewStringObject, NodeResultJS) \
247
    macro(MakeRope, NodeResultJS) \
248
    macro(In, NodeResultBoolean | NodeMustGenerate | NodeClobbersWorld) \
249 250 251 252 253 254 255
    \
    /* Nodes used for activations. Activation support works by having it anchored at */\
    /* epilgoues via TearOffActivation, and all CreateActivation nodes kept alive by */\
    /* being threaded with each other. */\
    macro(CreateActivation, NodeResultJS) \
    macro(TearOffActivation, NodeMustGenerate) \
    \
256 257 258
    /* Nodes used for arguments. Similar to activation support, only it makes even less */\
    /* sense. */\
    macro(CreateArguments, NodeResultJS) \
259
    macro(PhantomArguments, NodeResultJS | NodeDoesNotExit) \
260
    macro(TearOffArguments, NodeMustGenerate) \
261 262 263 264
    macro(GetMyArgumentsLength, NodeResultJS | NodeMustGenerate) \
    macro(GetMyArgumentByVal, NodeResultJS | NodeMustGenerate) \
    macro(GetMyArgumentsLengthSafe, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
    macro(GetMyArgumentByValSafe, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
265
    macro(CheckArgumentsNotCreated, NodeMustGenerate) \
266
    \
267 268 269 270 271
    /* Nodes for creating functions. */\
    macro(NewFunctionNoCheck, NodeResultJS) \
    macro(NewFunction, NodeResultJS) \
    macro(NewFunctionExpression, NodeResultJS) \
    \
272 273 274 275
    /* These aren't terminals but always exit */ \
    macro(Throw, NodeMustGenerate) \
    macro(ThrowReferenceError, NodeMustGenerate) \
    \
276 277 278
    /* Block terminals. */\
    macro(Jump, NodeMustGenerate) \
    macro(Branch, NodeMustGenerate) \
279
    macro(Switch, NodeMustGenerate) \
280
    macro(Return, NodeMustGenerate) \
281
    macro(Unreachable, NodeMustGenerate) \
282
    \
283 284 285
    /* Count execution. */\
    macro(CountExecution, NodeMustGenerate) \
    \
286 287 288
    /* This is a pseudo-terminal. It means that execution should fall out of DFG at */\
    /* this point, but execution does continue in the basic block - just in a */\
    /* different compiler. */\
289 290 291 292 293
    macro(ForceOSRExit, NodeMustGenerate) \
    \
    /* Checks the watchdog timer. If the timer has fired, we OSR exit to the */ \
    /* baseline JIT to redo the watchdog timer check, and service the timer. */ \
    macro(CheckWatchdogTimer, NodeMustGenerate) \
294 295 296 297
    /* Write barriers ! */\
    macro(StoreBarrier, NodeMustGenerate) \
    macro(ConditionalStoreBarrier, NodeMustGenerate) \
    macro(StoreBarrierWithNullCheck, NodeMustGenerate) \
298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315

// This enum generates a monotonically increasing id for all Node types,
// and is used by the subsequent enum to fill out the id (as accessed via the NodeIdMask).
enum NodeType {
#define DFG_OP_ENUM(opcode, flags) opcode,
    FOR_EACH_DFG_OP(DFG_OP_ENUM)
#undef DFG_OP_ENUM
    LastNodeType
};

// Specifies the default flags for each node.
inline NodeFlags defaultFlags(NodeType op)
{
    switch (op) {
#define DFG_OP_ENUM(opcode, flags) case opcode: return flags;
    FOR_EACH_DFG_OP(DFG_OP_ENUM)
#undef DFG_OP_ENUM
    default:
316
        RELEASE_ASSERT_NOT_REACHED();
317 318 319 320 321 322 323 324 325 326
        return 0;
    }
}

} } // namespace JSC::DFG

#endif // ENABLE(DFG_JIT)

#endif // DFGNodeType_h