summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/ftl/FTLCapabilities.cpp
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
commit1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch)
tree46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/JavaScriptCore/ftl/FTLCapabilities.cpp
parent32761a6cee1d0dee366b885b7b9c777e67885688 (diff)
downloadWebKitGtk-tarball-master.tar.gz
Diffstat (limited to 'Source/JavaScriptCore/ftl/FTLCapabilities.cpp')
-rw-r--r--Source/JavaScriptCore/ftl/FTLCapabilities.cpp348
1 files changed, 270 insertions, 78 deletions
diff --git a/Source/JavaScriptCore/ftl/FTLCapabilities.cpp b/Source/JavaScriptCore/ftl/FTLCapabilities.cpp
index 86a28cf8a..81d566583 100644
--- a/Source/JavaScriptCore/ftl/FTLCapabilities.cpp
+++ b/Source/JavaScriptCore/ftl/FTLCapabilities.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2016 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -32,6 +32,11 @@ namespace JSC { namespace FTL {
using namespace DFG;
+static bool verboseCapabilities()
+{
+ return verboseCompilationEnabled() || Options::verboseFTLFailure();
+}
+
inline CapabilityLevel canCompile(Node* node)
{
// NOTE: If we ever have phantom arguments, we can compile them but we cannot
@@ -39,11 +44,15 @@ inline CapabilityLevel canCompile(Node* node)
switch (node->op()) {
case JSConstant:
- case WeakJSConstant:
+ case LazyJSConstant:
case GetLocal:
case SetLocal:
+ case PutStack:
+ case KillStack:
+ case GetStack:
case MovHint:
case ZombieHint:
+ case ExitOK:
case Phantom:
case Flush:
case PhantomLocal:
@@ -56,20 +65,28 @@ inline CapabilityLevel canCompile(Node* node)
case BitLShift:
case BitURShift:
case CheckStructure:
- case StructureTransitionWatchpoint:
+ case DoubleAsInt32:
case ArrayifyToStructure:
case PutStructure:
- case PhantomPutStructure:
case GetButterfly:
case NewObject:
case NewArray:
+ case NewArrayWithSpread:
+ case Spread:
case NewArrayBuffer:
+ case NewTypedArray:
case GetByOffset:
+ case GetGetterSetterByOffset:
+ case GetGetter:
+ case GetSetter:
case PutByOffset:
case GetGlobalVar:
- case PutGlobalVar:
+ case GetGlobalLexicalVariable:
+ case PutGlobalVariable:
case ValueAdd:
+ case StrCat:
case ArithAdd:
+ case ArithClz32:
case ArithSub:
case ArithMul:
case ArithDiv:
@@ -77,61 +94,213 @@ inline CapabilityLevel canCompile(Node* node)
case ArithMin:
case ArithMax:
case ArithAbs:
+ case ArithSin:
+ case ArithCos:
+ case ArithTan:
+ case ArithPow:
+ case ArithRandom:
+ case ArithRound:
+ case ArithFloor:
+ case ArithCeil:
+ case ArithTrunc:
+ case ArithSqrt:
+ case ArithLog:
+ case ArithFRound:
case ArithNegate:
case UInt32ToNumber:
- case Int32ToDouble:
- case CompareEqConstant:
- case CompareStrictEqConstant:
case Jump:
case ForceOSRExit:
case Phi:
case Upsilon:
case ExtractOSREntryLocal:
case LoopHint:
- case Call:
- case Construct:
- case GetMyScope:
case SkipScope:
- case GetClosureRegisters:
+ case GetGlobalObject:
+ case CreateActivation:
+ case NewFunction:
+ case NewGeneratorFunction:
+ case NewAsyncFunction:
case GetClosureVar:
case PutClosureVar:
- case Int52ToValue:
+ case CreateDirectArguments:
+ case CreateScopedArguments:
+ case CreateClonedArguments:
+ case GetFromArguments:
+ case PutToArguments:
+ case GetArgument:
case InvalidationPoint:
case StringCharAt:
- case CheckFunction:
+ case CheckCell:
+ case CheckBadCell:
+ case CheckNotEmpty:
+ case CheckStringIdent:
+ case CheckWatchdogTimer:
case StringCharCodeAt:
+ case StringFromCharCode:
case AllocatePropertyStorage:
- case FunctionReentryWatchpoint:
- case TypedArrayWatchpoint:
- case VariableWatchpoint:
+ case ReallocatePropertyStorage:
+ case NukeStructureAndSetButterfly:
+ case GetTypedArrayByteOffset:
case NotifyWrite:
case StoreBarrier:
- case ConditionalStoreBarrier:
- case StoreBarrierWithNullCheck:
+ case FencedStoreBarrier:
+ case Call:
+ case DirectCall:
+ case TailCall:
+ case DirectTailCall:
+ case TailCallInlinedCaller:
+ case DirectTailCallInlinedCaller:
+ case Construct:
+ case DirectConstruct:
+ case CallVarargs:
+ case CallEval:
+ case TailCallVarargs:
+ case TailCallVarargsInlinedCaller:
+ case ConstructVarargs:
+ case CallForwardVarargs:
+ case TailCallForwardVarargs:
+ case TailCallForwardVarargsInlinedCaller:
+ case ConstructForwardVarargs:
+ case LoadVarargs:
case ValueToInt32:
case Branch:
case LogicalNot:
case CheckInBounds:
case ConstantStoragePointer:
case Check:
- // These are OK.
- break;
+ case CountExecution:
+ case GetExecutable:
+ case GetScope:
+ case GetCallee:
+ case GetArgumentCountIncludingThis:
+ case ToNumber:
+ case ToString:
+ case CallObjectConstructor:
+ case CallStringConstructor:
+ case MakeRope:
+ case NewArrayWithSize:
+ case TryGetById:
case GetById:
- case PutById:
- if (node->child1().useKind() == CellUse)
- break;
- return CannotCompile;
+ case GetByIdFlush:
+ case GetByIdWithThis:
+ case ToThis:
+ case MultiGetByOffset:
+ case MultiPutByOffset:
+ case ToPrimitive:
+ case Throw:
+ case ThrowStaticError:
+ case Unreachable:
+ case In:
+ case HasOwnProperty:
+ case IsCellWithType:
+ case MapHash:
+ case GetMapBucket:
+ case LoadFromJSMapBucket:
+ case IsNonEmptyMapBucket:
+ case IsEmpty:
+ case IsUndefined:
+ case IsBoolean:
+ case IsNumber:
+ case IsObject:
+ case IsObjectOrNull:
+ case IsFunction:
+ case IsTypedArrayView:
+ case CheckTypeInfoFlags:
+ case OverridesHasInstance:
+ case InstanceOf:
+ case InstanceOfCustom:
+ case DoubleRep:
+ case ValueRep:
+ case Int52Rep:
+ case DoubleConstant:
+ case Int52Constant:
+ case BooleanToNumber:
+ case HasGenericProperty:
+ case HasStructureProperty:
+ case GetDirectPname:
+ case GetEnumerableLength:
case GetIndexedPropertyStorage:
- if (node->arrayMode().type() == Array::String)
- break;
- if (isTypedView(node->arrayMode().typedArrayType()))
- break;
- return CannotCompile;
+ case GetPropertyEnumerator:
+ case GetEnumeratorStructurePname:
+ case GetEnumeratorGenericPname:
+ case ToIndexString:
+ case BottomValue:
+ case PhantomNewObject:
+ case PhantomNewFunction:
+ case PhantomNewGeneratorFunction:
+ case PhantomNewAsyncFunction:
+ case PhantomCreateActivation:
+ case PutHint:
+ case CheckStructureImmediate:
+ case MaterializeNewObject:
+ case MaterializeCreateActivation:
+ case PhantomDirectArguments:
+ case PhantomCreateRest:
+ case PhantomSpread:
+ case PhantomNewArrayWithSpread:
+ case PhantomClonedArguments:
+ case GetMyArgumentByVal:
+ case GetMyArgumentByValOutOfBounds:
+ case ForwardVarargs:
+ case Switch:
+ case TypeOf:
+ case PutById:
+ case PutByIdDirect:
+ case PutByIdFlush:
+ case PutByIdWithThis:
+ case PutGetterById:
+ case PutSetterById:
+ case PutGetterSetterById:
+ case PutGetterByVal:
+ case PutSetterByVal:
+ case CreateRest:
+ case GetRestLength:
+ case RegExpExec:
+ case RegExpTest:
+ case NewRegexp:
+ case StringReplace:
+ case StringReplaceRegExp:
+ case GetRegExpObjectLastIndex:
+ case SetRegExpObjectLastIndex:
+ case RecordRegExpCachedResult:
+ case SetFunctionName:
+ case LogShadowChickenPrologue:
+ case LogShadowChickenTail:
+ case ResolveScope:
+ case GetDynamicVar:
+ case PutDynamicVar:
+ case CompareEq:
+ case CompareEqPtr:
+ case CompareLess:
+ case CompareLessEq:
+ case CompareGreater:
+ case CompareGreaterEq:
+ case CompareStrictEq:
+ case DefineDataProperty:
+ case DefineAccessorProperty:
+ case ToLowerCase:
+ case NumberToStringWithRadix:
+ case CheckDOM:
+ case CallDOM:
+ case CallDOMGetter:
+ case ArraySlice:
+ case ParseInt:
+ // These are OK.
+ break;
+
+ case Identity:
+ // No backend handles this because it will be optimized out. But we may check
+ // for capabilities before optimization. It would be a deep error to remove this
+ // case because it would prevent us from catching bugs where the FTL backend
+ // pipeline failed to optimize out an Identity.
+ break;
case CheckArray:
switch (node->arrayMode().type()) {
case Array::Int32:
case Array::Double:
case Array::Contiguous:
+ case Array::DirectArguments:
+ case Array::ScopedArguments:
break;
default:
if (isTypedView(node->arrayMode().typedArrayType()))
@@ -141,17 +310,31 @@ inline CapabilityLevel canCompile(Node* node)
break;
case GetArrayLength:
switch (node->arrayMode().type()) {
+ case Array::Undecided:
case Array::Int32:
case Array::Double:
case Array::Contiguous:
case Array::String:
+ case Array::DirectArguments:
+ case Array::ScopedArguments:
break;
default:
- if (isTypedView(node->arrayMode().typedArrayType()))
+ if (node->arrayMode().isSomeTypedArrayView())
break;
return CannotCompile;
}
break;
+ case HasIndexedProperty:
+ switch (node->arrayMode().type()) {
+ case Array::ForceExit:
+ case Array::Int32:
+ case Array::Double:
+ case Array::Contiguous:
+ break;
+ default:
+ return CannotCompile;
+ }
+ break;
case GetByVal:
switch (node->arrayMode().type()) {
case Array::ForceExit:
@@ -160,6 +343,9 @@ inline CapabilityLevel canCompile(Node* node)
case Array::Int32:
case Array::Double:
case Array::Contiguous:
+ case Array::Undecided:
+ case Array::DirectArguments:
+ case Array::ScopedArguments:
break;
default:
if (isTypedView(node->arrayMode().typedArrayType()))
@@ -167,6 +353,8 @@ inline CapabilityLevel canCompile(Node* node)
return CannotCompile;
}
break;
+ case GetByValWithThis:
+ break;
case PutByVal:
case PutByValAlias:
case PutByValDirect:
@@ -183,45 +371,14 @@ inline CapabilityLevel canCompile(Node* node)
return CannotCompile;
}
break;
- case CompareEq:
- if (node->isBinaryUseKind(Int32Use))
- break;
- if (node->isBinaryUseKind(MachineIntUse))
- break;
- if (node->isBinaryUseKind(NumberUse))
- break;
- if (node->isBinaryUseKind(ObjectUse))
- break;
- if (node->isBinaryUseKind(UntypedUse))
- break;
- return CannotCompile;
- case CompareStrictEq:
- if (node->isBinaryUseKind(Int32Use))
- break;
- if (node->isBinaryUseKind(MachineIntUse))
- break;
- if (node->isBinaryUseKind(NumberUse))
- break;
- if (node->isBinaryUseKind(ObjectUse))
- break;
- return CannotCompile;
- case CompareLess:
- case CompareLessEq:
- case CompareGreater:
- case CompareGreaterEq:
- if (node->isBinaryUseKind(Int32Use))
- break;
- if (node->isBinaryUseKind(MachineIntUse))
- break;
- if (node->isBinaryUseKind(NumberUse))
- break;
- if (node->isBinaryUseKind(UntypedUse))
- break;
- return CannotCompile;
- case Switch:
- switch (node->switchData()->kind) {
- case SwitchImm:
- case SwitchChar:
+ case PutByValWithThis:
+ break;
+ case ArrayPush:
+ case ArrayPop:
+ switch (node->arrayMode().type()) {
+ case Array::Int32:
+ case Array::Contiguous:
+ case Array::Double:
break;
default:
return CannotCompile;
@@ -236,9 +393,21 @@ inline CapabilityLevel canCompile(Node* node)
CapabilityLevel canCompile(Graph& graph)
{
+ if (graph.m_codeBlock->instructionCount() > Options::maximumFTLCandidateInstructionCount()) {
+ if (verboseCapabilities())
+ dataLog("FTL rejecting ", *graph.m_codeBlock, " because it's too big.\n");
+ return CannotCompile;
+ }
+
if (graph.m_codeBlock->codeType() != FunctionCode) {
- if (verboseCompilationEnabled())
- dataLog("FTL rejecting code block that doesn't belong to a function.\n");
+ if (verboseCapabilities())
+ dataLog("FTL rejecting ", *graph.m_codeBlock, " because it doesn't belong to a function.\n");
+ return CannotCompile;
+ }
+
+ if (UNLIKELY(graph.m_codeBlock->ownerScriptExecutable()->neverFTLOptimize())) {
+ if (verboseCapabilities())
+ dataLog("FTL rejecting ", *graph.m_codeBlock, " because it is marked as never FTL compile.\n");
return CannotCompile;
}
@@ -264,23 +433,46 @@ CapabilityLevel canCompile(Graph& graph)
case UntypedUse:
case Int32Use:
case KnownInt32Use:
- case MachineIntUse:
+ case Int52RepUse:
case NumberUse:
- case KnownNumberUse:
case RealNumberUse:
+ case DoubleRepUse:
+ case DoubleRepRealUse:
case BooleanUse:
+ case KnownBooleanUse:
case CellUse:
case KnownCellUse:
+ case CellOrOtherUse:
case ObjectUse:
+ case ArrayUse:
+ case FunctionUse:
case ObjectOrOtherUse:
case StringUse:
+ case StringOrOtherUse:
+ case KnownStringUse:
+ case KnownPrimitiveUse:
+ case StringObjectUse:
+ case StringOrStringObjectUse:
+ case SymbolUse:
+ case MapObjectUse:
+ case SetObjectUse:
case FinalObjectUse:
+ case RegExpObjectUse:
+ case ProxyObjectUse:
+ case DerivedArrayUse:
+ case NotCellUse:
+ case OtherUse:
+ case MiscUse:
+ case StringIdentUse:
+ case NotStringVarUse:
+ case AnyIntUse:
+ case DoubleRepAnyIntUse:
// These are OK.
break;
default:
// Don't know how to handle anything else.
- if (verboseCompilationEnabled()) {
- dataLog("FTL rejecting node because of bad use kind: ", edge.useKind(), " in node:\n");
+ if (verboseCapabilities()) {
+ dataLog("FTL rejecting node in ", *graph.m_codeBlock, " because of bad use kind: ", edge.useKind(), " in node:\n");
graph.dump(WTF::dataFile(), " ", node);
}
return CannotCompile;
@@ -289,8 +481,8 @@ CapabilityLevel canCompile(Graph& graph)
switch (canCompile(node)) {
case CannotCompile:
- if (verboseCompilationEnabled()) {
- dataLog("FTL rejecting node:\n");
+ if (verboseCapabilities()) {
+ dataLog("FTL rejecting node in ", *graph.m_codeBlock, ":\n");
graph.dump(WTF::dataFile(), " ", node);
}
return CannotCompile;