blob: 79dfc5d2e7730b3422f3568735d7c0b01a5ab030 [file] [log] [blame]
/*
* 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.
*/
#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. */\
macro(JSConstant, NodeResultJS | NodeDoesNotExit) \
\
/* A constant not in the CodeBlock's constant pool. Uses get patched to jumps that exit the */\
/* code block. */\
macro(WeakJSConstant, NodeResultJS | NodeDoesNotExit) \
\
/* 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). */\
macro(Identity, NodeResultJS | NodeDoesNotExit) \
\
/* Nodes for handling functions (both as call and as construct). */\
macro(ConvertThis, NodeResultJS) \
macro(CreateThis, NodeResultJS) /* Note this is not MustGenerate since we're returning it anyway. */ \
macro(GetCallee, NodeResultJS) \
\
/* 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. */\
macro(GetLocal, NodeResultJS) \
macro(SetLocal, 0) \
macro(Phantom, NodeMustGenerate | NodeDoesNotExit) \
macro(Nop, 0 | NodeDoesNotExit) \
macro(Phi, 0 | NodeDoesNotExit) \
macro(Flush, NodeMustGenerate | NodeDoesNotExit) \
\
/* 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) \
\
/* Marker for an argument being set at the prologue of a function. */\
macro(SetArgument, 0 | NodeDoesNotExit) \
\
/* Hint that inlining begins here. No code is generated for this node. It's only */\
/* used for copying OSR data into inline frame data, to support reification of */\
/* call frames of inlined functions. */\
macro(InlineStart, 0 | NodeDoesNotExit) \
\
/* Nodes for bitwise operations. */\
macro(BitAnd, NodeResultInt32) \
macro(BitOr, NodeResultInt32) \
macro(BitXor, NodeResultInt32) \
macro(BitLShift, NodeResultInt32) \
macro(BitRShift, NodeResultInt32) \
macro(BitURShift, NodeResultInt32) \
/* Bitwise operators call ToInt32 on their operands. */\
macro(ValueToInt32, NodeResultInt32 | NodeMustGenerate) \
/* Used to box the result of URShift nodes (result has range 0..2^32-1). */\
macro(UInt32ToNumber, NodeResultNumber) \
\
/* Used to cast known integers to doubles, so as to separate the double form */\
/* of the value from the integer form. */\
macro(Int32ToDouble, NodeResultNumber) \
/* Used to speculate that a double value is actually an integer. */\
macro(DoubleAsInt32, NodeResultInt32) \
/* Used to record places where we must check if a value is a number. */\
macro(CheckNumber, NodeMustGenerate) \
\
/* Nodes for arithmetic operations. */\
macro(ArithAdd, NodeResultNumber | NodeMustGenerate) \
macro(ArithSub, NodeResultNumber | NodeMustGenerate) \
macro(ArithNegate, NodeResultNumber | NodeMustGenerate) \
macro(ArithMul, NodeResultNumber | NodeMustGenerate) \
macro(ArithDiv, NodeResultNumber | NodeMustGenerate) \
macro(ArithMod, NodeResultNumber | NodeMustGenerate) \
macro(ArithAbs, NodeResultNumber | NodeMustGenerate) \
macro(ArithMin, NodeResultNumber | NodeMustGenerate) \
macro(ArithMax, NodeResultNumber | NodeMustGenerate) \
macro(ArithSqrt, NodeResultNumber | NodeMustGenerate) \
\
/* Add of values may either be arithmetic, or result in string concatenation. */\
macro(ValueAdd, NodeResultJS | NodeMustGenerate | NodeMightClobber) \
\
/* Property access. */\
/* PutByValAlias indicates a 'put' aliases a prior write to the same property. */\
/* Since a put to 'length' may invalidate optimizations here, */\
/* this must be the directly subsequent property put. Note that PutByVal */\
/* opcodes use VarArgs beause they may have up to 4 children. */\
macro(GetByVal, NodeResultJS | NodeMustGenerate | NodeMightClobber) \
macro(PutByVal, NodeMustGenerate | NodeHasVarArgs | NodeMightClobber) \
macro(PutByValAlias, NodeMustGenerate | NodeHasVarArgs | NodeMightClobber) \
macro(GetById, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
macro(GetByIdFlush, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
macro(PutById, NodeMustGenerate | NodeClobbersWorld) \
macro(PutByIdDirect, NodeMustGenerate | NodeClobbersWorld) \
macro(CheckStructure, NodeMustGenerate) \
macro(ForwardCheckStructure, NodeMustGenerate) \
/* 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) \
macro(ForwardStructureTransitionWatchpoint, NodeMustGenerate) \
macro(PutStructure, NodeMustGenerate) \
macro(PhantomPutStructure, NodeMustGenerate | NodeDoesNotExit) \
macro(AllocatePropertyStorage, NodeMustGenerate | NodeDoesNotExit | NodeResultStorage) \
macro(ReallocatePropertyStorage, NodeMustGenerate | NodeDoesNotExit | NodeResultStorage) \
macro(GetButterfly, NodeResultStorage) \
macro(CheckArray, NodeMustGenerate) \
macro(Arrayify, NodeMustGenerate) \
macro(ArrayifyToStructure, NodeMustGenerate) \
macro(GetIndexedPropertyStorage, NodeResultStorage) \
macro(GetByOffset, NodeResultJS) \
macro(PutByOffset, NodeMustGenerate) \
macro(GetArrayLength, NodeResultInt32) \
macro(GetMyScope, NodeResultJS) \
macro(SkipTopScope, NodeResultJS) \
macro(SkipScope, NodeResultJS) \
macro(GetScopeRegisters, NodeResultStorage) \
macro(GetScopedVar, NodeResultJS) \
macro(PutScopedVar, NodeMustGenerate) \
macro(GetGlobalVar, NodeResultJS) \
macro(PutGlobalVar, NodeMustGenerate) \
macro(GlobalVarWatchpoint, NodeMustGenerate) \
macro(PutGlobalVarCheck, NodeMustGenerate) \
macro(CheckFunction, NodeMustGenerate) \
macro(InheritorIDWatchpoint, NodeMustGenerate) \
\
/* Optimizations for array mutation. */\
macro(ArrayPush, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
macro(ArrayPop, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
\
/* Optimizations for regular expression matching. */\
macro(RegExpExec, NodeResultJS | NodeMustGenerate) \
macro(RegExpTest, NodeResultJS | NodeMustGenerate) \
\
/* Optimizations for string access */ \
macro(StringCharCodeAt, NodeResultInt32) \
macro(StringCharAt, NodeResultJS) \
\
/* Nodes for comparison operations. */\
macro(CompareLess, NodeResultBoolean | NodeMustGenerate | NodeMightClobber) \
macro(CompareLessEq, NodeResultBoolean | NodeMustGenerate | NodeMightClobber) \
macro(CompareGreater, NodeResultBoolean | NodeMustGenerate | NodeMightClobber) \
macro(CompareGreaterEq, NodeResultBoolean | NodeMustGenerate | NodeMightClobber) \
macro(CompareEq, NodeResultBoolean | NodeMustGenerate | NodeMightClobber) \
macro(CompareStrictEq, NodeResultBoolean) \
\
/* Calls. */\
macro(Call, NodeResultJS | NodeMustGenerate | NodeHasVarArgs | NodeClobbersWorld) \
macro(Construct, NodeResultJS | NodeMustGenerate | NodeHasVarArgs | NodeClobbersWorld) \
\
/* Allocations. */\
macro(NewObject, NodeResultJS) \
macro(NewArray, NodeResultJS | NodeHasVarArgs) \
macro(NewArrayWithSize, NodeResultJS) \
macro(NewArrayBuffer, NodeResultJS) \
macro(NewRegexp, NodeResultJS) \
\
/* Resolve nodes. */\
macro(Resolve, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
macro(ResolveBase, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
macro(ResolveBaseStrictPut, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
macro(ResolveGlobal, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
\
/* Nodes for misc operations. */\
macro(Breakpoint, NodeMustGenerate | NodeClobbersWorld) \
macro(CheckHasInstance, NodeMustGenerate) \
macro(InstanceOf, NodeResultBoolean) \
macro(IsUndefined, NodeResultBoolean) \
macro(IsBoolean, NodeResultBoolean) \
macro(IsNumber, NodeResultBoolean) \
macro(IsString, NodeResultBoolean) \
macro(IsObject, NodeResultBoolean) \
macro(IsFunction, NodeResultBoolean) \
macro(LogicalNot, NodeResultBoolean) \
macro(ToPrimitive, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
macro(StrCat, NodeResultJS | NodeMustGenerate | NodeHasVarArgs | NodeClobbersWorld) \
\
/* 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) \
\
/* Nodes used for arguments. Similar to activation support, only it makes even less */\
/* sense. */\
macro(CreateArguments, NodeResultJS) \
macro(PhantomArguments, NodeResultJS | NodeDoesNotExit) \
macro(TearOffArguments, NodeMustGenerate) \
macro(GetMyArgumentsLength, NodeResultJS | NodeMustGenerate) \
macro(GetMyArgumentByVal, NodeResultJS | NodeMustGenerate) \
macro(GetMyArgumentsLengthSafe, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
macro(GetMyArgumentByValSafe, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
macro(CheckArgumentsNotCreated, NodeMustGenerate) \
\
/* Nodes for creating functions. */\
macro(NewFunctionNoCheck, NodeResultJS) \
macro(NewFunction, NodeResultJS) \
macro(NewFunctionExpression, NodeResultJS) \
\
/* Block terminals. */\
macro(Jump, NodeMustGenerate) \
macro(Branch, NodeMustGenerate) \
macro(Return, NodeMustGenerate) \
macro(Throw, NodeMustGenerate) \
macro(ThrowReferenceError, NodeMustGenerate) \
\
macro(GarbageValue, NodeResultJS | NodeClobbersWorld) \
\
/* Count execution. */\
macro(CountExecution, NodeMustGenerate) \
\
/* 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. */\
macro(ForceOSRExit, NodeMustGenerate)
// 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:
ASSERT_NOT_REACHED();
return 0;
}
}
} } // namespace JSC::DFG
#endif // ENABLE(DFG_JIT)
#endif // DFGNodeType_h