Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

488488 0F7C11AD1BC3862C00C74CDB /* CopyBarrier.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F7C11AC1BC3862C00C74CDB /* CopyBarrier.h */; settings = {ATTRIBUTES = (Private, ); }; };
489489 0F7C39FB1C8F629300480151 /* RegExpInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F7C39FA1C8F629300480151 /* RegExpInlines.h */; };
490490 0F7C39FD1C8F659500480151 /* RegExpObjectInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F7C39FC1C8F659500480151 /* RegExpObjectInlines.h */; };
 491 0F7C39FF1C90C55B00480151 /* DFGOpInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F7C39FE1C90C55B00480151 /* DFGOpInfo.h */; };
491492 0F8023EA1613832B00A0BA45 /* ByValInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F8023E91613832300A0BA45 /* ByValInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
492493 0F8335B71639C1E6001443B5 /* ArrayAllocationProfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F8335B41639C1E3001443B5 /* ArrayAllocationProfile.cpp */; };
493494 0F8335B81639C1EA001443B5 /* ArrayAllocationProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F8335B51639C1E3001443B5 /* ArrayAllocationProfile.h */; settings = {ATTRIBUTES = (Private, ); }; };

26402641 0F7C11AC1BC3862C00C74CDB /* CopyBarrier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CopyBarrier.h; sourceTree = "<group>"; };
26412642 0F7C39FA1C8F629300480151 /* RegExpInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegExpInlines.h; sourceTree = "<group>"; };
26422643 0F7C39FC1C8F659500480151 /* RegExpObjectInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegExpObjectInlines.h; sourceTree = "<group>"; };
 2644 0F7C39FE1C90C55B00480151 /* DFGOpInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGOpInfo.h; path = dfg/DFGOpInfo.h; sourceTree = "<group>"; };
26432645 0F8023E91613832300A0BA45 /* ByValInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ByValInfo.h; sourceTree = "<group>"; };
26442646 0F8335B41639C1E3001443B5 /* ArrayAllocationProfile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ArrayAllocationProfile.cpp; sourceTree = "<group>"; };
26452647 0F8335B51639C1E3001443B5 /* ArrayAllocationProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArrayAllocationProfile.h; sourceTree = "<group>"; };

62456247 0F2B9CDD19D0BA7D00B1D1B5 /* DFGObjectMaterializationData.h */,
62466248 86EC9DBF1328DF82002B2AD7 /* DFGOperations.cpp */,
62476249 86EC9DC01328DF82002B2AD7 /* DFGOperations.h */,
 6250 0F7C39FE1C90C55B00480151 /* DFGOpInfo.h */,
62486251 A7D89CEE17A0B8CC00773AD8 /* DFGOSRAvailabilityAnalysisPhase.cpp */,
62496252 A7D89CEF17A0B8CC00773AD8 /* DFGOSRAvailabilityAnalysisPhase.h */,
62506253 0FD82E52141DAEDE00179C94 /* DFGOSREntry.cpp */,

74457448 0F64EAF31C4ECD0600621E9B /* AirArgInlines.h in Headers */,
74467449 A5EA710519F6DE740098F5EC /* generate_objc_configuration_header.py in Headers */,
74477450 A5EA710619F6DE760098F5EC /* generate_objc_configuration_implementation.py in Headers */,
 7451 0F7C39FF1C90C55B00480151 /* DFGOpInfo.h in Headers */,
74487452 A5EA710719F6DE780098F5EC /* generate_objc_protocol_type_conversions_header.py in Headers */,
74497453 0F338DF61BE93D550013C88F /* B3ConstrainedValue.h in Headers */,
74507454 A5EA710819F6DE7A0098F5EC /* generate_objc_frontend_dispatcher_implementation.py in Headers */,
197981

Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h

@@bool AbstractInterpreter<AbstractStateTy
19521952 break;
19531953
19541954 case SetRegExpObjectLastIndex:
 1955 case RecordRegExpCachedResult:
19551956 break;
19561957
19571958 case GetFromArguments:
197981

Source/JavaScriptCore/dfg/DFGClobberize.h

@@void clobberize(Graph& graph, Node* node
923923 write(RegExpObject_lastIndex);
924924 def(HeapLocation(RegExpObjectLastIndexLoc, RegExpObject_lastIndex, node->child1()), LazyNode(node->child2().node()));
925925 return;
 926
 927 case RecordRegExpCachedResult:
 928 write(RegExpState);
 929 return;
926930
927931 case GetFromArguments: {
928932 AbstractHeap heap(DirectArgumentsProperties, node->capturedArgumentsOffset().offset());

@@void clobberize(Graph& graph, Node* node
10861090 if (node->child2().useKind() == RegExpObjectUse
10871091 && node->child3().useKind() == StringUse) {
10881092 read(RegExpState);
 1093 read(RegExpObject_lastIndex);
10891094 write(RegExpState);
 1095 write(RegExpObject_lastIndex);
10901096 return;
10911097 }
10921098 read(World);

@@void clobberize(Graph& graph, Node* node
10981104 && node->child2().useKind() == RegExpObjectUse
10991105 && node->child3().useKind() == StringUse) {
11001106 read(RegExpState);
 1107 read(RegExpObject_lastIndex);
11011108 write(RegExpState);
 1109 write(RegExpObject_lastIndex);
11021110 return;
11031111 }
11041112 read(World);
197981

Source/JavaScriptCore/dfg/DFGDoesGC.cpp

@@bool doesGC(Graph& graph, Node* node)
117117 case PutClosureVar:
118118 case GetRegExpObjectLastIndex:
119119 case SetRegExpObjectLastIndex:
 120 case RecordRegExpCachedResult:
120121 case GetGlobalVar:
121122 case GetGlobalLexicalVariable:
122123 case PutGlobalVariable:
197981

Source/JavaScriptCore/dfg/DFGFixupPhase.cpp

@@private:
13001300 case StoreBarrier:
13011301 case GetRegExpObjectLastIndex:
13021302 case SetRegExpObjectLastIndex:
 1303 case RecordRegExpCachedResult:
13031304 // These are just nodes that we don't currently expect to see during fixup.
13041305 // If we ever wanted to insert them prior to fixup, then we just have to create
13051306 // fixup rules for them.
197981

Source/JavaScriptCore/dfg/DFGGraph.cpp

@@void Graph::dump(PrintStream& out, const
315315 out.print(anotherComma, pointerDumpInContext(freeze(m_codeBlock->constantBuffer(node->startConstant())[i]), context));
316316 out.print("]");
317317 }
 318 if (node->hasLazyJSValue())
 319 out.print(comma, node->lazyJSValue());
318320 if (node->hasIndexingType())
319321 out.print(comma, IndexingTypeDump(node->indexingType()));
320322 if (node->hasTypedArrayType())
197981

Source/JavaScriptCore/dfg/DFGInsertionSet.cpp

@@void InsertionSet::insertSlow(const Inse
4545 m_insertions.insert(0, insertion);
4646}
4747
48 void InsertionSet::execute(BasicBlock* block)
 48size_t InsertionSet::execute(BasicBlock* block)
4949{
50  executeInsertions(*block, m_insertions);
 50 return executeInsertions(*block, m_insertions);
5151}
5252
5353} } // namespace JSC::DFG
197981

Source/JavaScriptCore/dfg/DFGInsertionSet.h

@@public:
129129 return nullptr;
130130 }
131131
132  void execute(BasicBlock* block);
 132 size_t execute(BasicBlock* block);
133133
134134private:
135135 void insertSlow(const Insertion&);
197981

Source/JavaScriptCore/dfg/DFGNode.h

4242#include "DFGNodeOrigin.h"
4343#include "DFGNodeType.h"
4444#include "DFGObjectMaterializationData.h"
 45#include "DFGOpInfo.h"
4546#include "DFGTransition.h"
4647#include "DFGUseKind.h"
4748#include "DFGVariableAccessData.h"

@@struct StackAccessData {
219220 FlushedAt flushedAt() { return FlushedAt(format, machineLocal); }
220221};
221222
222 // This type used in passing an immediate argument to Node constructor;
223 // distinguishes an immediate value (typically an index into a CodeBlock data structure -
224 // a constant index, argument, or identifier) from a Node*.
225 struct OpInfo {
226  OpInfo() : m_value(0) { }
227  explicit OpInfo(int32_t value) : m_value(static_cast<uintptr_t>(value)) { }
228  explicit OpInfo(uint32_t value) : m_value(static_cast<uintptr_t>(value)) { }
229 #if OS(DARWIN) || USE(JSVALUE64)
230  explicit OpInfo(size_t value) : m_value(static_cast<uintptr_t>(value)) { }
231 #endif
232  explicit OpInfo(void* value) : m_value(reinterpret_cast<uintptr_t>(value)) { }
233  uintptr_t m_value;
234 };
235 
236223// === Node ===
237224//
238225// Node represents a single operation in the data flow graph.
197981

Source/JavaScriptCore/dfg/DFGNodeType.h

@@namespace JSC { namespace DFG {
224224 macro(VarInjectionWatchpoint, NodeMustGenerate) \
225225 macro(GetRegExpObjectLastIndex, NodeResultJS) \
226226 macro(SetRegExpObjectLastIndex, NodeMustGenerate) \
 227 macro(RecordRegExpCachedResult, NodeMustGenerate | NodeHasVarArgs) \
227228 macro(CheckCell, NodeMustGenerate) \
228229 macro(CheckNotEmpty, NodeMustGenerate) \
229230 macro(CheckBadCell, NodeMustGenerate) \
197981

Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp

@@private:
19741974
19751975 case NamedPropertyPLoc: {
19761976 ASSERT(location.base() == allocation.identifier());
1977  data.m_properties.append(PhantomPropertyValue(location.info()));
 1977 data.m_properties.append(location.descriptor());
19781978 Node* value = resolve(block, location);
19791979 if (m_sinkCandidates.contains(value))
19801980 m_graph.m_varArgChildren.append(m_bottom);

@@private:
20242024
20252025 case ClosureVarPLoc: {
20262026 ASSERT(location.base() == allocation.identifier());
2027  data.m_properties.append(PhantomPropertyValue(location.info()));
 2027 data.m_properties.append(location.descriptor());
20282028 Node* value = resolve(block, location);
20292029 if (m_sinkCandidates.contains(value))
20302030 m_graph.m_varArgChildren.append(m_bottom);
197981

Source/JavaScriptCore/dfg/DFGObjectMaterializationData.cpp

11/*
2  * Copyright (C) 2014 Apple Inc. All rights reserved.
 2 * Copyright (C) 2014, 2016 Apple Inc. All rights reserved.
33 *
44 * Redistribution and use in source and binary forms, with or without
55 * modification, are permitted provided that the following conditions

3232
3333namespace JSC { namespace DFG {
3434
35 void PhantomPropertyValue::dump(PrintStream& out) const
36 {
37  out.print("id", m_identifierNumber);
38 }
39 
4035void ObjectMaterializationData::dump(PrintStream& out) const
4136{
4237 out.print("[", listDump(m_properties), "]");
4338}
4439
45 float ObjectMaterializationData::oneWaySimilarityScore(
46  const ObjectMaterializationData& other) const
47 {
48  unsigned numHits = 0;
49  for (PhantomPropertyValue value : m_properties) {
50  if (other.m_properties.contains(value))
51  numHits++;
52  }
53  return static_cast<float>(numHits) / static_cast<float>(m_properties.size());
54 }
55 
56 float ObjectMaterializationData::similarityScore(const ObjectMaterializationData& other) const
57 {
58  return std::min(oneWaySimilarityScore(other), other.oneWaySimilarityScore(*this));
59 }
60 
6140} } // namespace JSC::DFG
6241
6342#endif // ENABLE(DFG_JIT)
197981

Source/JavaScriptCore/dfg/DFGObjectMaterializationData.h

11/*
2  * Copyright (C) 2014 Apple Inc. All rights reserved.
 2 * Copyright (C) 2014, 2016 Apple Inc. All rights reserved.
33 *
44 * Redistribution and use in source and binary forms, with or without
55 * modification, are permitted provided that the following conditions

2828
2929#if ENABLE(DFG_JIT)
3030
 31#include "DFGPromotedHeapLocation.h"
3132#include <limits.h>
3233#include <wtf/MathExtras.h>
3334#include <wtf/PrintStream.h>

3536
3637namespace JSC { namespace DFG {
3738
38 struct PhantomPropertyValue {
39  PhantomPropertyValue()
40  : m_identifierNumber(UINT_MAX)
41  {
42  }
43 
44  PhantomPropertyValue(unsigned identifierNumber)
45  : m_identifierNumber(identifierNumber)
46  {
47  }
48 
49  unsigned m_identifierNumber;
50 
51  bool operator==(const PhantomPropertyValue& other) const
52  {
53  return m_identifierNumber == other.m_identifierNumber;
54  }
55 
56  void dump(PrintStream&) const;
57 };
58 
5939struct ObjectMaterializationData {
6040 // Determines the meaning of the passed nodes.
61  Vector<PhantomPropertyValue> m_properties;
 41 Vector<PromotedLocationDescriptor> m_properties;
6242
6343 void dump(PrintStream&) const;
64 
65  // The fraction of my properties that the other data has.
66  float oneWaySimilarityScore(const ObjectMaterializationData&) const;
67 
68  // The minimum of the two possible one-way scores.
69  float similarityScore(const ObjectMaterializationData&) const;
7044};
7145
7246} } // namespace JSC::DFG
197981

Source/JavaScriptCore/dfg/DFGOpInfo.h

 1/*
 2 * Copyright (C) 2016 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 DFGOpInfo_h
 27#define DFGOpInfo_h
 28
 29#include <wtf/StdLibExtras.h>
 30
 31#if ENABLE(DFG_JIT)
 32
 33namespace JSC { namespace DFG {
 34
 35// This type used in passing an immediate argument to Node constructor;
 36// distinguishes an immediate value (typically an index into a CodeBlock data structure -
 37// a constant index, argument, or identifier) from a Node*.
 38struct OpInfo {
 39 OpInfo() : m_value(0) { }
 40 explicit OpInfo(int32_t value) : m_value(static_cast<uintptr_t>(value)) { }
 41 explicit OpInfo(uint32_t value) : m_value(static_cast<uintptr_t>(value)) { }
 42#if OS(DARWIN) || USE(JSVALUE64)
 43 explicit OpInfo(size_t value) : m_value(static_cast<uintptr_t>(value)) { }
 44#endif
 45 explicit OpInfo(void* value) : m_value(reinterpret_cast<uintptr_t>(value)) { }
 46 uintptr_t m_value;
 47};
 48
 49} } // namespace JSC::DFG
 50
 51#endif // ENABLE(DFG_JIT)
 52
 53#endif // DFGOpInfo_h
 54
0

Source/JavaScriptCore/dfg/DFGOperations.cpp

@@size_t JIT_OPERATION operationDefaultHas
14011401 return 0;
14021402}
14031403
 1404char* JIT_OPERATION operationNewRawObject(ExecState* exec, Structure* structure, int32_t length)
 1405{
 1406 VM& vm = exec->vm();
 1407 NativeCallFrameTracer tracer(&vm, exec);
 1408
 1409 Butterfly* butterfly;
 1410 if (structure->outOfLineCapacity() || hasIndexedProperties(structure->indexingType())) {
 1411 IndexingHeader header;
 1412 header.setVectorLength(length);
 1413 header.setPublicLength(0);
 1414
 1415 butterfly = Butterfly::create(
 1416 vm, nullptr, 0, structure->outOfLineCapacity(),
 1417 hasIndexedProperties(structure->indexingType()), header,
 1418 length * sizeof(EncodedJSValue));
 1419 } else
 1420 butterfly = nullptr;
 1421
 1422 JSObject* result = JSObject::createRawObject(exec, structure, butterfly);
 1423 result->butterfly(); // Ensure that the butterfly is in to-space.
 1424 return bitwise_cast<char*>(result);
 1425}
 1426
 1427JSCell* JIT_OPERATION operationNewObjectWithButterfly(ExecState* exec, Structure* structure)
 1428{
 1429 VM& vm = exec->vm();
 1430 NativeCallFrameTracer tracer(&vm, exec);
 1431
 1432 Butterfly* butterfly = Butterfly::create(
 1433 vm, nullptr, 0, structure->outOfLineCapacity(), false, IndexingHeader(), 0);
 1434
 1435 JSObject* result = JSObject::createRawObject(exec, structure, butterfly);
 1436 result->butterfly(); // Ensure that the butterfly is in to-space.
 1437 return result;
 1438}
 1439
 1440JSCell* JIT_OPERATION operationNewObjectWithButterflyWithIndexingHeaderAndVectorLength(ExecState* exec, Structure* structure, unsigned length)
 1441{
 1442 VM& vm = exec->vm();
 1443 NativeCallFrameTracer tracer(&vm, exec);
 1444
 1445 IndexingHeader header;
 1446 header.setVectorLength(length);
 1447 header.setPublicLength(0);
 1448 Butterfly* butterfly = Butterfly::create(
 1449 vm, nullptr, 0, structure->outOfLineCapacity(), true, header,
 1450 sizeof(EncodedJSValue) * length);
 1451
 1452 // Paradoxically this may allocate a JSArray. That's totally cool.
 1453 JSObject* result = JSObject::createRawObject(exec, structure, butterfly);
 1454 result->butterfly(); // Ensure that the butterfly is in to-space.
 1455 return result;
 1456}
 1457
14041458void JIT_OPERATION operationProcessTypeProfilerLogDFG(ExecState* exec)
14051459{
14061460 exec->vm().typeProfilerLog()->processLogEntries(ASCIILiteral("Log Full, called from inside DFG."));
197981

Source/JavaScriptCore/dfg/DFGOperations.h

@@int64_t JIT_OPERATION operationConvertDo
157157
158158size_t JIT_OPERATION operationDefaultHasInstance(ExecState*, JSCell* value, JSCell* proto);
159159
 160char* JIT_OPERATION operationNewRawObject(ExecState*, Structure*, int32_t) WTF_INTERNAL;
 161JSCell* JIT_OPERATION operationNewObjectWithButterfly(ExecState*, Structure*) WTF_INTERNAL;
 162JSCell* JIT_OPERATION operationNewObjectWithButterflyWithIndexingHeaderAndVectorLength(ExecState*, Structure*, unsigned length) WTF_INTERNAL;
 163
160164void JIT_OPERATION operationProcessTypeProfilerLogDFG(ExecState*) WTF_INTERNAL;
161165
162166void JIT_OPERATION debugOperationPrintSpeculationFailure(ExecState*, void*, void*) WTF_INTERNAL;
197981

Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp

@@private:
668668 case GetStack:
669669 case GetRegExpObjectLastIndex:
670670 case SetRegExpObjectLastIndex:
 671 case RecordRegExpCachedResult:
671672 case LazyJSConstant: {
672673 // This node should never be visible at this stage of compilation. It is
673674 // inserted by fixup(), which follows this phase.
197981

Source/JavaScriptCore/dfg/DFGPromotedHeapLocation.cpp

11/*
2  * Copyright (C) 2014, 2015 Apple Inc. All rights reserved.
 2 * Copyright (C) 2014-2016 Apple Inc. All rights reserved.
33 *
44 * Redistribution and use in source and binary forms, with or without
55 * modification, are permitted provided that the following conditions

@@void printInternal(PrintStream& out, Pro
7474 case NamedPropertyPLoc:
7575 out.print("NamedPropertyPLoc");
7676 return;
 77
 78 case IndexedPropertyPLoc:
 79 out.print("IndexedPropertyPLoc");
 80 return;
7781
7882 case ArgumentPLoc:
7983 out.print("ArgumentPLoc");

@@void printInternal(PrintStream& out, Pro
102106 case ClosureVarPLoc:
103107 out.print("ClosureVarPLoc");
104108 return;
 109
 110 case PublicLengthPLoc:
 111 out.print("PublicLengthPLoc");
 112 return;
 113
 114 case VectorLengthPLoc:
 115 out.print("VectorLengthPLoc");
 116 return;
105117 }
106118
107119 RELEASE_ASSERT_NOT_REACHED();
197981

Source/JavaScriptCore/dfg/DFGPromotedHeapLocation.h

11/*
2  * Copyright (C) 2014, 2015 Apple Inc. All rights reserved.
 2 * Copyright (C) 2014-2016 Apple Inc. All rights reserved.
33 *
44 * Redistribution and use in source and binary forms, with or without
55 * modification, are permitted provided that the following conditions

2828
2929#if ENABLE(DFG_JIT)
3030
31 #include "DFGNode.h"
 31#include "DFGEdge.h"
 32#include "DFGNodeOrigin.h"
 33#include "DFGOpInfo.h"
 34#include <wtf/HashTable.h>
3235#include <wtf/PrintStream.h>
3336
3437namespace JSC { namespace DFG {
3538
 39struct Node;
 40
 41// Promoted locations are like heap locations but are meant to be more precise. A heap location is
 42// applicable to CSE scenarios, where it makes sense to speak of a location very abstractly. A
 43// promoted heap location is for cases where we speak of a specific object and the compiler knows
 44// this object's identity - for example, the object allocation has been eliminated and we turned the
 45// fields into local variables. Because these two cases have subtly different needs, we use subtly
 46// different structures. One of the really significant differences is that promoted locations can be
 47// spoken of using either a descriptor which does not refer to any Node*'s or with a heap location,
 48// which is a descriptor with a Node* base.
 49
3650enum PromotedLocationKind {
3751 InvalidPromotedLocationKind,
3852
39  StructurePLoc,
 53 ActivationScopePLoc,
4054 ActivationSymbolTablePLoc,
41  NamedPropertyPLoc,
42  ArgumentPLoc,
4355 ArgumentCountPLoc,
 56 ArgumentPLoc,
4457 ArgumentsCalleePLoc,
45 
46  FunctionExecutablePLoc,
 58 ClosureVarPLoc,
4759 FunctionActivationPLoc,
48  ActivationScopePLoc,
49  ClosureVarPLoc
 60 FunctionExecutablePLoc,
 61 IndexedPropertyPLoc,
 62 NamedPropertyPLoc,
 63 PublicLengthPLoc,
 64 StructurePLoc,
 65 VectorLengthPLoc
5066};
5167
5268class PromotedLocationDescriptor {
197981

Source/JavaScriptCore/dfg/DFGSafeToExecute.h

@@bool safeToExecute(AbstractStateType& st
336336 case StringReplace:
337337 case GetRegExpObjectLastIndex:
338338 case SetRegExpObjectLastIndex:
 339 case RecordRegExpCachedResult:
339340 return true;
340341
341342 case BottomValue:
197981

Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp

@@void SpeculativeJIT::compile(Node* node)
30473047 break;
30483048 }
30493049
 3050 case RecordRegExpCachedResult: {
 3051 compileRecordRegExpCachedResult(node);
 3052 break;
 3053 }
 3054
30503055 case ArrayPush: {
30513056 ASSERT(node->arrayMode().isJSArray());
30523057

@@void SpeculativeJIT::compile(Node* node)
34923497 GPRReg resultGPR = result.gpr();
34933498 GPRReg storageGPR = storage.gpr();
34943499
3495  emitAllocateJSArray(resultGPR, structure, storageGPR, numElements);
 3500 emitAllocateRawObject(resultGPR, structure, storageGPR, numElements, numElements);
34963501
34973502 // At this point, one way or another, resultGPR and storageGPR have pointers to
34983503 // the JSArray and the Butterfly, respectively.

@@void SpeculativeJIT::compile(Node* node)
37283733 GPRReg resultGPR = result.gpr();
37293734 GPRReg storageGPR = storage.gpr();
37303735
3731  emitAllocateJSArray(resultGPR, globalObject->arrayStructureForIndexingTypeDuringAllocation(indexingType), storageGPR, numElements);
 3736 emitAllocateRawObject(resultGPR, globalObject->arrayStructureForIndexingTypeDuringAllocation(indexingType), storageGPR, numElements, numElements);
37323737
37333738 if (node->indexingType() == ArrayWithDouble) {
37343739 JSValue* data = m_jit.codeBlock()->constantBuffer(node->startConstant());

@@void SpeculativeJIT::compile(Node* node)
49784983 noResult(node);
49794984 break;
49804985
4981 
 4986 case MaterializeNewObject:
 4987 compileMaterializeNewObject(node);
 4988 break;
 4989
49824990 case Unreachable:
49834991 RELEASE_ASSERT_NOT_REACHED();
49844992 break;
197981

Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp

@@void SpeculativeJIT::compile(Node* node)
31713171 compileSetRegExpObjectLastIndex(node);
31723172 break;
31733173 }
 3174
 3175 case RecordRegExpCachedResult: {
 3176 compileRecordRegExpCachedResult(node);
 3177 break;
 3178 }
31743179
31753180 case ArrayPush: {
31763181 ASSERT(node->arrayMode().isJSArray());

@@void SpeculativeJIT::compile(Node* node)
35423547 GPRReg resultGPR = result.gpr();
35433548 GPRReg storageGPR = storage.gpr();
35443549
3545  emitAllocateJSArray(resultGPR, structure, storageGPR, numElements);
 3550 emitAllocateRawObject(resultGPR, structure, storageGPR, numElements, numElements);
35463551
35473552 // At this point, one way or another, resultGPR and storageGPR have pointers to
35483553 // the JSArray and the Butterfly, respectively.

@@void SpeculativeJIT::compile(Node* node)
37783783 GPRReg resultGPR = result.gpr();
37793784 GPRReg storageGPR = storage.gpr();
37803785
3781  emitAllocateJSArray(resultGPR, globalObject->arrayStructureForIndexingTypeDuringAllocation(indexingType), storageGPR, numElements);
 3786 emitAllocateRawObject(resultGPR, globalObject->arrayStructureForIndexingTypeDuringAllocation(indexingType), storageGPR, numElements, numElements);
37823787
37833788 DFG_ASSERT(m_jit.graph(), node, indexingType & IsArray);
37843789 JSValue* data = m_jit.codeBlock()->constantBuffer(node->startConstant());

@@void SpeculativeJIT::compile(Node* node)
49714976 break;
49724977 }
49734978
 4979 case MaterializeNewObject:
 4980 compileMaterializeNewObject(node);
 4981 break;
 4982
49744983#if ENABLE(FTL_JIT)
49754984 case CheckTierUpInLoop: {
49764985 MacroAssembler::Jump done = m_jit.branchAdd32(

@@void SpeculativeJIT::compile(Node* node)
50615070 case GetMyArgumentByVal:
50625071 case PutHint:
50635072 case CheckStructureImmediate:
5064  case MaterializeNewObject:
50655073 case MaterializeCreateActivation:
50665074 case PutStack:
50675075 case KillStack:
197981

Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

5252#include "JSGeneratorFunction.h"
5353#include "JSLexicalEnvironment.h"
5454#include "LinkBuffer.h"
 55#include "RegExpConstructor.h"
5556#include "ScopedArguments.h"
5657#include "ScratchRegisterAllocator.h"
5758#include "WriteBarrierBuffer.h"

@@SpeculativeJIT::~SpeculativeJIT()
7778{
7879}
7980
80 void SpeculativeJIT::emitAllocateJSArray(GPRReg resultGPR, Structure* structure, GPRReg storageGPR, unsigned numElements)
 81void SpeculativeJIT::emitAllocateRawObject(GPRReg resultGPR, Structure* structure, GPRReg storageGPR, unsigned numElements, unsigned vectorLength)
8182{
82  ASSERT(hasUndecided(structure->indexingType()) || hasInt32(structure->indexingType()) || hasDouble(structure->indexingType()) || hasContiguous(structure->indexingType()));
 83 IndexingType indexingType = structure->indexingType();
 84 bool hasIndexingHeader = hasIndexedProperties(indexingType);
 85
 86 unsigned inlineCapacity = structure->inlineCapacity();
 87 unsigned outOfLineCapacity = structure->outOfLineCapacity();
8388
8489 GPRTemporary scratch(this);
8590 GPRTemporary scratch2(this);
8691 GPRReg scratchGPR = scratch.gpr();
8792 GPRReg scratch2GPR = scratch2.gpr();
88 
89  unsigned vectorLength = std::max(BASE_VECTOR_LEN, numElements);
 93
 94 ASSERT(vectorLength >= numElements);
 95 vectorLength = std::max(BASE_VECTOR_LEN, vectorLength);
9096
9197 JITCompiler::JumpList slowCases;
92 
93  slowCases.append(
94  emitAllocateBasicStorage(TrustedImm32(vectorLength * sizeof(JSValue) + sizeof(IndexingHeader)), storageGPR));
95  m_jit.subPtr(TrustedImm32(vectorLength * sizeof(JSValue)), storageGPR);
96  emitAllocateJSObject<JSArray>(resultGPR, TrustedImmPtr(structure), storageGPR, scratchGPR, scratch2GPR, slowCases);
97 
98  m_jit.store32(TrustedImm32(numElements), MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
99  m_jit.store32(TrustedImm32(vectorLength), MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength()));
100 
 98
 99 size_t size = 0;
 100 if (hasIndexingHeader)
 101 size += vectorLength * sizeof(JSValue) + sizeof(IndexingHeader);
 102 size += outOfLineCapacity * sizeof(JSValue);
 103
 104 if (size) {
 105 slowCases.append(
 106 emitAllocateBasicStorage(TrustedImm32(size), storageGPR));
 107 if (hasIndexingHeader)
 108 m_jit.subPtr(TrustedImm32(vectorLength * sizeof(JSValue)), storageGPR);
 109 else
 110 m_jit.addPtr(TrustedImm32(sizeof(IndexingHeader)), storageGPR);
 111 } else
 112 m_jit.move(TrustedImmPtr(0), storageGPR);
 113
 114 size_t allocationSize = JSFinalObject::allocationSize(inlineCapacity);
 115 MarkedAllocator* allocatorPtr = &m_jit.vm()->heap.allocatorForObjectWithoutDestructor(allocationSize);
 116 m_jit.move(TrustedImmPtr(allocatorPtr), scratchGPR);
 117 emitAllocateJSObject(resultGPR, scratchGPR, TrustedImmPtr(structure), storageGPR, scratch2GPR, slowCases);
 118
 119 if (hasIndexingHeader)
 120 m_jit.store32(TrustedImm32(vectorLength), MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength()));
 121
101122 if (hasDouble(structure->indexingType()) && numElements < vectorLength) {
102123#if USE(JSVALUE64)
103124 m_jit.move(TrustedImm64(bitwise_cast<int64_t>(PNaN)), scratchGPR);

@@void SpeculativeJIT::emitAllocateJSArray
117138 // what this custom CallArrayAllocatorSlowPathGenerator gives me. It's a lot
118139 // of work for a very small piece of functionality. :-/
119140 addSlowPathGenerator(std::make_unique<CallArrayAllocatorSlowPathGenerator>(
120  slowCases, this, operationNewArrayWithSize, resultGPR, storageGPR,
121  structure, numElements));
 141 slowCases, this, operationNewRawObject, resultGPR, storageGPR,
 142 structure, vectorLength));
 143
 144 if (hasIndexingHeader)
 145 m_jit.store32(TrustedImm32(numElements), MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
122146}
123147
124148void SpeculativeJIT::emitGetLength(InlineCallFrame* inlineCallFrame, GPRReg lengthGPR, bool includeThis)

@@void SpeculativeJIT::compileLazyJSConsta
76557679 jsValueResult(resultRegs, node);
76567680}
76577681
 7682void SpeculativeJIT::compileMaterializeNewObject(Node* node)
 7683{
 7684 Structure* structure = node->structureSet()[0];
 7685 ASSERT(m_jit.graph().varArgChild(node, 0)->dynamicCastConstant<Structure*>() == structure);
 7686
 7687 ObjectMaterializationData& data = node->objectMaterializationData();
 7688
 7689 IndexingType indexingType = structure->indexingType();
 7690 bool hasIndexingHeader = hasIndexedProperties(indexingType);
 7691 int32_t publicLength = 0;
 7692 int32_t vectorLength = 0;
 7693
 7694 if (hasIndexingHeader) {
 7695 for (unsigned i = data.m_properties.size(); i--;) {
 7696 Edge edge = m_jit.graph().varArgChild(node, 1 + i);
 7697 switch (data.m_properties[i].kind()) {
 7698 case PublicLengthPLoc:
 7699 publicLength = edge->asInt32();
 7700 break;
 7701 case VectorLengthPLoc:
 7702 vectorLength = edge->asInt32();
 7703 break;
 7704 default:
 7705 break;
 7706 }
 7707 }
 7708 }
 7709
 7710 GPRTemporary result(this);
 7711 GPRTemporary storage(this);
 7712 GPRReg resultGPR = result.gpr();
 7713 GPRReg storageGPR = storage.gpr();
 7714
 7715 emitAllocateRawObject(resultGPR, structure, storageGPR, 0, vectorLength);
 7716
 7717 m_jit.store32(
 7718 JITCompiler::TrustedImm32(publicLength),
 7719 JITCompiler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
 7720
 7721 for (unsigned i = data.m_properties.size(); i--;) {
 7722 Edge edge = m_jit.graph().varArgChild(node, 1 + i);
 7723 PromotedLocationDescriptor descriptor = data.m_properties[i];
 7724 switch (descriptor.kind()) {
 7725 case IndexedPropertyPLoc: {
 7726 JSValueOperand value(this, edge);
 7727 m_jit.storeValue(
 7728 value.jsValueRegs(),
 7729 JITCompiler::Address(storageGPR, sizeof(EncodedJSValue) * descriptor.info()));
 7730 break;
 7731 }
 7732
 7733 case NamedPropertyPLoc: {
 7734 StringImpl* uid = m_jit.graph().identifiers()[descriptor.info()];
 7735 for (PropertyMapEntry entry : structure->getPropertiesConcurrently()) {
 7736 if (uid != entry.key)
 7737 continue;
 7738
 7739 JSValueOperand value(this, edge);
 7740 GPRReg baseGPR = isInlineOffset(entry.offset) ? resultGPR : storageGPR;
 7741 m_jit.storeValue(
 7742 value.jsValueRegs(),
 7743 JITCompiler::Address(baseGPR, offsetRelativeToBase(entry.offset)));
 7744 }
 7745 break;
 7746 }
 7747
 7748 default:
 7749 break;
 7750 }
 7751 }
 7752
 7753 cellResult(resultGPR, node);
 7754}
 7755
 7756void SpeculativeJIT::compileRecordRegExpCachedResult(Node* node)
 7757{
 7758 Edge constructorEdge = m_jit.graph().varArgChild(node, 0);
 7759 Edge regExpEdge = m_jit.graph().varArgChild(node, 1);
 7760 Edge stringEdge = m_jit.graph().varArgChild(node, 2);
 7761 Edge startEdge = m_jit.graph().varArgChild(node, 3);
 7762 Edge endEdge = m_jit.graph().varArgChild(node, 4);
 7763
 7764 SpeculateCellOperand constructor(this, constructorEdge);
 7765 SpeculateCellOperand regExp(this, regExpEdge);
 7766 SpeculateCellOperand string(this, stringEdge);
 7767 SpeculateInt32Operand start(this, startEdge);
 7768 SpeculateInt32Operand end(this, endEdge);
 7769
 7770 GPRReg constructorGPR = constructor.gpr();
 7771 GPRReg regExpGPR = regExp.gpr();
 7772 GPRReg stringGPR = string.gpr();
 7773 GPRReg startGPR = start.gpr();
 7774 GPRReg endGPR = end.gpr();
 7775
 7776 ptrdiff_t offset = RegExpConstructor::offsetOfCachedResult();
 7777
 7778 m_jit.storePtr(
 7779 regExpGPR,
 7780 JITCompiler::Address(constructorGPR, offset + RegExpCachedResult::offsetOfLastRegExp()));
 7781 m_jit.storePtr(
 7782 stringGPR,
 7783 JITCompiler::Address(constructorGPR, offset + RegExpCachedResult::offsetOfLastInput()));
 7784 m_jit.store32(
 7785 startGPR,
 7786 JITCompiler::Address(
 7787 constructorGPR,
 7788 offset + RegExpCachedResult::offsetOfResult() + OBJECT_OFFSETOF(MatchResult, start)));
 7789 m_jit.store32(
 7790 endGPR,
 7791 JITCompiler::Address(
 7792 constructorGPR,
 7793 offset + RegExpCachedResult::offsetOfResult() + OBJECT_OFFSETOF(MatchResult, end)));
 7794 m_jit.store8(
 7795 TrustedImm32(0),
 7796 JITCompiler::Address(constructorGPR, offset + RegExpCachedResult::offsetOfReified()));
 7797
 7798 noResult(node);
 7799}
 7800
76587801} } // namespace JSC::DFG
76597802
76607803#endif
197981

Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h

@@public:
24012401 void compileGetRegExpObjectLastIndex(Node*);
24022402 void compileSetRegExpObjectLastIndex(Node*);
24032403 void compileLazyJSConstant(Node*);
 2404 void compileMaterializeNewObject(Node*);
 2405 void compileRecordRegExpCachedResult(Node*);
24042406
24052407 void moveTrueTo(GPRReg);
24062408 void moveFalseTo(GPRReg);

@@public:
25162518 m_jit.storePtr(TrustedImmPtr(structure->classInfo()), MacroAssembler::Address(resultGPR, JSDestructibleObject::classInfoOffset()));
25172519 }
25182520
2519  void emitAllocateJSArray(GPRReg resultGPR, Structure*, GPRReg storageGPR, unsigned numElements);
 2521 void emitAllocateRawObject(GPRReg resultGPR, Structure*, GPRReg storageGPR, unsigned numElements, unsigned vectorLength);
25202522
25212523 void emitGetLength(InlineCallFrame*, GPRReg lengthGPR, bool includeThis = false);
25222524 void emitGetLength(CodeOrigin, GPRReg lengthGPR, bool includeThis = false);
197981

Source/JavaScriptCore/dfg/DFGStoreBarrierInsertionPhase.cpp

@@private:
253253 break;
254254 }
255255
 256 case PutById:
 257 case PutByIdFlush:
 258 case PutByIdDirect:
256259 case PutStructure: {
257260 considerBarrier(m_node->child1());
258261 break;
259262 }
260 
 263
 264 case RecordRegExpCachedResult: {
 265 considerBarrier(m_graph.varArgChild(m_node, 0));
 266 break;
 267 }
 268
261269 case PutClosureVar:
262270 case PutToArguments:
263271 case SetRegExpObjectLastIndex:

@@private:
266274 break;
267275 }
268276
269  case PutById:
270  case PutByIdFlush:
271  case PutByIdDirect: {
272  considerBarrier(m_node->child1());
273  break;
274  }
275 
276277 case PutByOffset: {
277278 considerBarrier(m_node->child2(), m_node->child3());
278279 break;
197981

Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp

11/*
2  * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
 2 * Copyright (C) 2013-2016 Apple Inc. All rights reserved.
33 *
44 * Redistribution and use in source and binary forms, with or without
55 * modification, are permitted provided that the following conditions

3636#include "DFGPredictionPropagationPhase.h"
3737#include "DFGVariableAccessDataDump.h"
3838#include "JSCInlines.h"
 39#include "RegExpConstructor.h"
3940#include <cstdlib>
4041
4142namespace JSC { namespace DFG {

@@private:
331332 if (!!string) {
332333 m_graph.convertToConstant(m_node, jsNumber(string.length()));
333334 m_changed = true;
 335 break;
334336 }
335337 }
336338 break;
337339 }
338340
 341 case GetGlobalObject: {
 342 if (JSObject* object = m_node->child1()->dynamicCastConstant<JSObject*>()) {
 343 m_graph.convertToConstant(m_node, object->globalObject());
 344 m_changed = true;
 345 break;
 346 }
 347 break;
 348 }
 349
 350 case RegExpExec:
 351 case RegExpTest: {
 352 dataLog("Here!\n");
 353 JSGlobalObject* globalObject = m_node->child1()->dynamicCastConstant<JSGlobalObject*>();
 354 if (!globalObject)
 355 break;
 356
 357 dataLog("Here.\n");
 358
 359 if (globalObject->isHavingABadTime())
 360 break;
 361
 362 dataLog("Getting regexp!\n");
 363
 364 Node* regExpObjectNode = m_node->child2().node();
 365 RegExp* regExp;
 366 if (RegExpObject* regExpObject = regExpObjectNode->dynamicCastConstant<RegExpObject*>())
 367 regExp = regExpObject->regExp();
 368 else if (regExpObjectNode->op() == NewRegexp)
 369 regExp = codeBlock()->regexp(regExpObjectNode->regexpIndex());
 370 else
 371 break;
 372
 373 Node* stringNode = m_node->child3().node();
 374
 375 dataLog("Still here!\n");
 376
 377 // NOTE: This mostly already protects us from having the compiler execute a regexp
 378 // operation on a ginormous string by preventing us from getting our hands on ginormous
 379 // strings in the first place.
 380 String string = m_node->child3()->tryGetString(m_graph);
 381 if (!string)
 382 break;
 383
 384 FrozenValue* regExpFrozenValue = m_graph.freeze(regExp);
 385
 386 // Refuse to do things with regular expressions that have a ginormous number of
 387 // subpatterns.
 388 unsigned ginormousNumberOfSubPatterns = 1000;
 389 if (regExp->numSubpatterns() > ginormousNumberOfSubPatterns)
 390 break;
 391
 392 dataLog("And still here!\n");
 393
 394 unsigned lastIndex;
 395 if (regExp->globalOrSticky()) {
 396 // This will only work if we can prove what the value of lastIndex is. To do this
 397 // safely, we need to execute the insertion set so that we see any previous strength
 398 // reductions. This is needed for soundness since otherwise the effectfulness of any
 399 // previous strength reductions would be invisible to us.
 400 executeInsertionSet();
 401 lastIndex = UINT_MAX;
 402 for (unsigned otherNodeIndex = m_nodeIndex; otherNodeIndex--;) {
 403 Node* otherNode = m_block->at(otherNodeIndex);
 404 if (otherNode == regExpObjectNode) {
 405 lastIndex = 0;
 406 break;
 407 }
 408 if (otherNode->op() == SetRegExpObjectLastIndex
 409 && otherNode->child1() == regExpObjectNode
 410 && otherNode->child2()->isInt32Constant()
 411 && otherNode->child2()->asInt32() >= 0) {
 412 lastIndex = static_cast<unsigned>(otherNode->child2()->asInt32());
 413 break;
 414 }
 415 if (writesOverlap(m_graph, otherNode, RegExpObject_lastIndex))
 416 break;
 417 }
 418 if (lastIndex == UINT_MAX)
 419 break;
 420 } else
 421 lastIndex = 0;
 422
 423 m_graph.watchpoints().addLazily(globalObject->havingABadTimeWatchpoint());
 424
 425 Structure* structure = globalObject->regExpMatchesArrayStructure();
 426 if (structure->indexingType() != ArrayWithContiguous) {
 427 // This is further protection against a race with haveABadTime.
 428 break;
 429 }
 430 m_graph.registerStructure(structure);
 431
 432 RegExpConstructor* constructor = globalObject->regExpConstructor();
 433 FrozenValue* constructorFrozenValue = m_graph.freeze(constructor);
 434
 435 int position;
 436 Vector<int, 32> ovector;
 437 if (!regExp->matchConcurrently(vm(), string, lastIndex, position, ovector))
 438 break;
 439
 440 // We've constant-folded the regexp. Now we're committed to replacing RegExpExec/Test.
 441
 442 m_changed = true;
 443
 444 NodeOrigin origin = m_node->origin;
 445
 446 m_insertionSet.insertNode(
 447 m_nodeIndex, SpecNone, Check, origin, m_node->children.justChecks());
 448
 449 if (m_node->op() == RegExpExec) {
 450 StructureSet* structureSet = m_graph.addStructureSet(structure);
 451
 452 // Create an array modeling the JS array that we will try to allocate. This is
 453 // basically createRegExpMatchesArray but over C++ strings instead of JSStrings.
 454 Vector<String> resultArray;
 455 resultArray.append(string.substring(position, ovector[1]));
 456 for (unsigned i = 1; i <= regExp->numSubpatterns(); ++i) {
 457 int start = ovector[2 * i];
 458 if (start >= 0)
 459 resultArray.append(string.substring(start, ovector[2 * i + 1] - start));
 460 else
 461 resultArray.append(String());
 462 }
 463
 464 unsigned publicLength = resultArray.size();
 465 unsigned vectorLength = std::max(BASE_VECTOR_LEN, publicLength);
 466
 467 UniquedStringImpl* indexUID = vm().propertyNames->index.impl();
 468 UniquedStringImpl* inputUID = vm().propertyNames->input.impl();
 469 unsigned indexIndex = m_graph.identifiers().ensure(indexUID);
 470 unsigned inputIndex = m_graph.identifiers().ensure(inputUID);
 471
 472 unsigned firstChild = m_graph.m_varArgChildren.size();
 473 m_graph.m_varArgChildren.append(
 474 m_insertionSet.insertConstantForUse(
 475 m_nodeIndex, origin, structure, KnownCellUse));
 476 ObjectMaterializationData* data = m_graph.m_objectMaterializationData.add();
 477
 478 m_graph.m_varArgChildren.append(
 479 m_insertionSet.insertConstantForUse(
 480 m_nodeIndex, origin, jsNumber(publicLength), KnownInt32Use));
 481 data->m_properties.append(PublicLengthPLoc);
 482
 483 m_graph.m_varArgChildren.append(
 484 m_insertionSet.insertConstantForUse(
 485 m_nodeIndex, origin, jsNumber(vectorLength), KnownInt32Use));
 486 data->m_properties.append(VectorLengthPLoc);
 487
 488 m_graph.m_varArgChildren.append(
 489 m_insertionSet.insertConstantForUse(
 490 m_nodeIndex, origin, jsNumber(position), UntypedUse));
 491 data->m_properties.append(
 492 PromotedLocationDescriptor(NamedPropertyPLoc, indexIndex));
 493
 494 m_graph.m_varArgChildren.append(Edge(stringNode, UntypedUse));
 495 data->m_properties.append(
 496 PromotedLocationDescriptor(NamedPropertyPLoc, inputIndex));
 497
 498 auto materializeString = [&] (const String& string) -> Node* {
 499 if (string.isNull())
 500 return nullptr;
 501 if (string.isEmpty()) {
 502 return m_insertionSet.insertConstant(
 503 m_nodeIndex, origin, vm().smallStrings.emptyString());
 504 }
 505 return m_insertionSet.insertNode(
 506 m_nodeIndex, SpecNone, LazyJSConstant, origin,
 507 OpInfo(m_graph.m_lazyJSValues.add(LazyJSValue::newString(m_graph, string))));
 508 };
 509
 510 for (unsigned i = 0; i < resultArray.size(); ++i) {
 511 if (Node* node = materializeString(resultArray[i])) {
 512 m_graph.m_varArgChildren.append(Edge(node, UntypedUse));
 513 data->m_properties.append(
 514 PromotedLocationDescriptor(IndexedPropertyPLoc, i));
 515 }
 516 }
 517
 518 Node* resultNode = m_insertionSet.insertNode(
 519 m_nodeIndex, SpecArray, Node::VarArg, MaterializeNewObject, origin,
 520 OpInfo(structureSet), OpInfo(data), firstChild,
 521 m_graph.m_varArgChildren.size() - firstChild);
 522
 523 m_node->convertToIdentityOn(resultNode);
 524 } else
 525 m_graph.convertToConstant(m_node, jsBoolean(position != -1));
 526
 527 // Whether it's Exec or Test, we need to tell the constructor and RegExpObject what's up.
 528 if (position != -1) {
 529 unsigned firstChild = m_graph.m_varArgChildren.size();
 530 m_graph.m_varArgChildren.append(
 531 m_insertionSet.insertConstantForUse(
 532 m_nodeIndex, origin, constructorFrozenValue, KnownCellUse));
 533 m_graph.m_varArgChildren.append(
 534 m_insertionSet.insertConstantForUse(
 535 m_nodeIndex, origin, regExpFrozenValue, KnownCellUse));
 536 m_graph.m_varArgChildren.append(Edge(stringNode, KnownCellUse));
 537 m_graph.m_varArgChildren.append(
 538 m_insertionSet.insertConstantForUse(
 539 m_nodeIndex, origin, jsNumber(position), KnownInt32Use));
 540 m_graph.m_varArgChildren.append(
 541 m_insertionSet.insertConstantForUse(
 542 m_nodeIndex, origin, jsNumber(ovector[1]), KnownInt32Use));
 543 m_insertionSet.insertNode(
 544 m_nodeIndex, SpecNone, Node::VarArg, RecordRegExpCachedResult, origin,
 545 OpInfo(), OpInfo(), firstChild, m_graph.m_varArgChildren.size() - firstChild);
 546
 547 origin = origin.withInvalidExit();
 548 }
 549
 550 if (regExp->globalOrSticky()) {
 551 m_insertionSet.insertNode(
 552 m_nodeIndex, SpecNone, SetRegExpObjectLastIndex, origin,
 553 Edge(regExpObjectNode, RegExpObjectUse),
 554 m_insertionSet.insertConstantForUse(
 555 m_nodeIndex, m_node->origin,
 556 jsNumber(position == -1 ? 0 : ovector[1]), UntypedUse));
 557
 558 origin = origin.withInvalidExit();
 559 }
 560
 561 m_node->origin = origin;
 562 break;
 563 }
 564
339565 default:
340566 break;
341567 }

@@private:
380606 return;
381607 }
382608 }
 609
 610 void executeInsertionSet()
 611 {
 612 m_nodeIndex = m_insertionSet.execute(m_block);
 613 }
383614
384615 InsertionSet m_insertionSet;
385616 BasicBlock* m_block;
197981

Source/JavaScriptCore/dfg/DFGValidate.cpp

11/*
2  * Copyright (C) 2012-2015 Apple Inc. All rights reserved.
 2 * Copyright (C) 2012-2016 Apple Inc. All rights reserved.
33 *
44 * Redistribution and use in source and binary forms, with or without
55 * modification, are permitted provided that the following conditions

@@public:
278278 VALIDATE((node), !variant.oldStructureForTransition()->dfgShouldWatch());
279279 }
280280 break;
 281 case MaterializeNewObject:
 282 for (Structure* structure : node->structureSet()) {
 283 // This only supports structures that are JSFinalObject or JSArray.
 284 VALIDATE(
 285 (node),
 286 structure->classInfo() == JSFinalObject::info()
 287 || structure->classInfo() == JSArray::info());
 288
 289 // We only support certain indexing shapes.
 290 VALIDATE((node), !hasAnyArrayStorage(structure->indexingType()));
 291 }
 292 break;
281293 case DoubleConstant:
282294 case Int52Constant:
283295 VALIDATE((node), node->isNumberConstant());

@@private:
461473 case GetMyArgumentByVal:
462474 case PutHint:
463475 case CheckStructureImmediate:
464  case MaterializeNewObject:
465476 case MaterializeCreateActivation:
466477 case PutStack:
467478 case KillStack:
468479 case GetStack:
469480 VALIDATE((node), !"unexpected node type in CPS");
470481 break;
 482 case MaterializeNewObject: {
 483 // CPS only allows array lengths to be constant. This constraint only exists
 484 // because we don't have DFG support for anything more and we don't need any
 485 // other kind of support for now.
 486 ObjectMaterializationData& data = node->objectMaterializationData();
 487 for (unsigned i = data.m_properties.size(); i--;) {
 488 PromotedLocationDescriptor descriptor = data.m_properties[i];
 489 Edge edge = m_graph.varArgChild(node, 1 + i);
 490 switch (descriptor.kind()) {
 491 case PublicLengthPLoc:
 492 case VectorLengthPLoc:
 493 VALIDATE((node, edge), edge->isInt32Constant());
 494 break;
 495 default:
 496 break;
 497 }
 498 }
 499
 500 // CPS only allows one structure.
 501 VALIDATE((node), node->structureSet().size() == 1);
 502
 503 // CPS disallows int32 and double arrays. Those require weird type checks and
 504 // conversions. They are not needed in the DFG right now. We should add support
 505 // for these if the DFG ever needs it.
 506 for (Structure* structure : node->structureSet()) {
 507 VALIDATE((node), !hasInt32(structure->indexingType()));
 508 VALIDATE((node), !hasDouble(structure->indexingType()));
 509 }
 510 break;
 511 }
471512 case Phantom:
472513 VALIDATE((node), m_graph.m_fixpointState != FixpointNotConverged);
473514 break;
197981

Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.cpp

3939#include "JSPropertyNameEnumerator.h"
4040#include "JSScope.h"
4141#include "JSCInlines.h"
 42#include "RegExpConstructor.h"
4243#include "RegExpObject.h"
4344#include "ScopedArguments.h"
4445#include "ScopedArgumentsTable.h"
197981

Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h

@@namespace JSC { namespace FTL {
7777 macro(JSSymbolTableObject_symbolTable, JSSymbolTableObject::offsetOfSymbolTable()) \
7878 macro(JSWrapperObject_internalValue, JSWrapperObject::internalValueOffset()) \
7979 macro(MarkedAllocator_freeListHead, MarkedAllocator::offsetOfFreeListHead()) \
 80 macro(RegExpConstructor_cachedResult_lastRegExp, RegExpConstructor::offsetOfCachedResult() + RegExpCachedResult::offsetOfLastRegExp()) \
 81 macro(RegExpConstructor_cachedResult_lastInput, RegExpConstructor::offsetOfCachedResult() + RegExpCachedResult::offsetOfLastInput()) \
 82 macro(RegExpConstructor_cachedResult_result_start, RegExpConstructor::offsetOfCachedResult() + RegExpCachedResult::offsetOfResult() + OBJECT_OFFSETOF(MatchResult, start)) \
 83 macro(RegExpConstructor_cachedResult_result_end, RegExpConstructor::offsetOfCachedResult() + RegExpCachedResult::offsetOfResult() + OBJECT_OFFSETOF(MatchResult, end)) \
 84 macro(RegExpConstructor_cachedResult_reified, RegExpConstructor::offsetOfCachedResult() + RegExpCachedResult::offsetOfReified()) \
8085 macro(RegExpObject_lastIndex, RegExpObject::offsetOfLastIndex()) \
8186 macro(RegExpObject_lastIndexIsWritable, RegExpObject::offsetOfLastIndexIsWritable()) \
8287 macro(ScopedArguments_overrodeThings, ScopedArguments::offsetOfOverrodeThings()) \
197981

Source/JavaScriptCore/ftl/FTLCapabilities.cpp

@@inline CapabilityLevel canCompile(Node*
228228 case StringReplace:
229229 case GetRegExpObjectLastIndex:
230230 case SetRegExpObjectLastIndex:
 231 case RecordRegExpCachedResult:
231232 // These are OK.
232233 break;
233234
197981

Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp

@@private:
938938 case SetRegExpObjectLastIndex:
939939 compileSetRegExpObjectLastIndex();
940940 break;
 941 case RecordRegExpCachedResult:
 942 compileRecordRegExpCachedResult();
 943 break;
941944
942945 case PhantomLocal:
943946 case LoopHint:

@@private:
37163719
37173720 m_out.store32(publicLength, butterfly, m_heaps.Butterfly_publicLength);
37183721 m_out.store32(vectorLength, butterfly, m_heaps.Butterfly_vectorLength);
3719 
3720  if (hasDouble(m_node->indexingType())) {
3721  LBasicBlock initLoop = m_out.newBlock();
3722  LBasicBlock initDone = m_out.newBlock();
3723 
3724  ValueFromBlock originalIndex = m_out.anchor(vectorLength);
3725  ValueFromBlock originalPointer = m_out.anchor(butterfly);
3726  m_out.branch(
3727  m_out.notZero32(vectorLength), unsure(initLoop), unsure(initDone));
3728 
3729  LBasicBlock initLastNext = m_out.appendTo(initLoop, initDone);
3730  LValue index = m_out.phi(m_out.int32, originalIndex);
3731  LValue pointer = m_out.phi(m_out.intPtr, originalPointer);
3732 
3733  m_out.store64(
3734  m_out.constInt64(bitwise_cast<int64_t>(PNaN)),
3735  TypedPointer(m_heaps.indexedDoubleProperties.atAnyIndex(), pointer));
3736 
3737  LValue nextIndex = m_out.sub(index, m_out.int32One);
3738  m_out.addIncomingToPhi(index, m_out.anchor(nextIndex));
3739  m_out.addIncomingToPhi(pointer, m_out.anchor(m_out.add(pointer, m_out.intPtrEight)));
3740  m_out.branch(
3741  m_out.notZero32(nextIndex), unsure(initLoop), unsure(initDone));
3742 
3743  m_out.appendTo(initDone, initLastNext);
3744  }
 3722
 3723 initializeArrayElements(m_node->indexingType(), vectorLength, butterfly);
37453724
37463725 ValueFromBlock fastResult = m_out.anchor(object);
37473726 m_out.jump(continuation);

@@private:
62866265 // Lower the values first, to avoid creating values inside a control flow diamond.
62876266
62886267 Vector<LValue, 8> values;
6289  for (unsigned i = 0; i < data.m_properties.size(); ++i)
6290  values.append(lowJSValue(m_graph.varArgChild(m_node, 1 + i)));
 6268 for (unsigned i = 0; i < data.m_properties.size(); ++i) {
 6269 Edge edge = m_graph.varArgChild(m_node, 1 + i);
 6270 switch (data.m_properties[i].kind()) {
 6271 case PublicLengthPLoc:
 6272 case VectorLengthPLoc:
 6273 values.append(lowInt32(edge));
 6274 break;
 6275 default:
 6276 values.append(lowJSValue(edge));
 6277 break;
 6278 }
 6279 }
62916280
62926281 const StructureSet& set = m_node->structureSet();
6293 
 6282
62946283 Vector<LBasicBlock, 1> blocks(set.size());
62956284 for (unsigned i = set.size(); i--;)
62966285 blocks[i] = m_out.newBlock();

@@private:
63156304 LValue object;
63166305 LValue butterfly;
63176306
6318  if (structure->outOfLineCapacity()) {
 6307 if (structure->outOfLineCapacity() || hasIndexedProperties(structure->indexingType())) {
63196308 size_t allocationSize = JSFinalObject::allocationSize(structure->inlineCapacity());
63206309 MarkedAllocator* allocator = &vm().heap.allocatorForObjectWithoutDestructor(allocationSize);
 6310
 6311 bool hasIndexingHeader = hasIndexedProperties(structure->indexingType());
 6312 unsigned indexingHeaderSize = 0;
 6313 LValue indexingPayloadSizeInBytes = m_out.intPtrZero;
 6314 LValue vectorLength = m_out.int32Zero;
 6315 LValue publicLength = m_out.int32Zero;
 6316 if (hasIndexingHeader) {
 6317 indexingHeaderSize = sizeof(IndexingHeader);
 6318 for (unsigned i = data.m_properties.size(); i--;) {
 6319 PromotedLocationDescriptor descriptor = data.m_properties[i];
 6320 switch (descriptor.kind()) {
 6321 case PublicLengthPLoc:
 6322 publicLength = values[i];
 6323 break;
 6324 case VectorLengthPLoc:
 6325 vectorLength = values[i];
 6326 break;
 6327 default:
 6328 break;
 6329 }
 6330 }
 6331 indexingPayloadSizeInBytes =
 6332 m_out.mul(m_out.zeroExtPtr(vectorLength), m_out.intPtrEight);
 6333 }
 6334
 6335 LValue butterflySize = m_out.add(
 6336 m_out.constIntPtr(
 6337 structure->outOfLineCapacity() * sizeof(JSValue) + indexingHeaderSize),
 6338 indexingPayloadSizeInBytes);
63216339
63226340 LBasicBlock slowPath = m_out.newBlock();
63236341 LBasicBlock continuation = m_out.newBlock();
63246342
63256343 LBasicBlock lastNext = m_out.insertNewBlocksBefore(slowPath);
63266344
6327  LValue endOfStorage = allocateBasicStorageAndGetEnd(
6328  m_out.constIntPtr(structure->outOfLineCapacity() * sizeof(JSValue)),
6329  slowPath);
6330 
 6345 LValue endOfStorage = allocateBasicStorageAndGetEnd(butterflySize, slowPath);
 6346
63316347 LValue fastButterflyValue = m_out.add(
6332  m_out.constIntPtr(sizeof(IndexingHeader)), endOfStorage);
 6348 m_out.sub(endOfStorage, indexingPayloadSizeInBytes),
 6349 m_out.constIntPtr(sizeof(IndexingHeader) - indexingHeaderSize));
 6350
 6351 m_out.store32(vectorLength, fastButterflyValue, m_heaps.Butterfly_vectorLength);
63336352
63346353 LValue fastObjectValue = allocateObject(
63356354 m_out.constIntPtr(allocator), structure, fastButterflyValue, slowPath);

@@private:
63406359
63416360 m_out.appendTo(slowPath, continuation);
63426361
6343  LValue slowObjectValue = lazySlowPath(
6344  [=] (const Vector<Location>& locations) -> RefPtr<LazySlowPath::Generator> {
6345  return createLazyCallGenerator(
6346  operationNewObjectWithButterfly, locations[0].directGPR(),
6347  CCallHelpers::TrustedImmPtr(structure));
6348  });
 6362 LValue slowObjectValue;
 6363 if (hasIndexingHeader) {
 6364 slowObjectValue = lazySlowPath(
 6365 [=] (const Vector<Location>& locations) -> RefPtr<LazySlowPath::Generator> {
 6366 return createLazyCallGenerator(
 6367 operationNewObjectWithButterflyWithIndexingHeaderAndVectorLength,
 6368 locations[0].directGPR(), CCallHelpers::TrustedImmPtr(structure),
 6369 locations[1].directGPR());
 6370 },
 6371 vectorLength);
 6372 } else {
 6373 slowObjectValue = lazySlowPath(
 6374 [=] (const Vector<Location>& locations) -> RefPtr<LazySlowPath::Generator> {
 6375 return createLazyCallGenerator(
 6376 operationNewObjectWithButterfly, locations[0].directGPR(),
 6377 CCallHelpers::TrustedImmPtr(structure));
 6378 });
 6379 }
63496380 ValueFromBlock slowObject = m_out.anchor(slowObjectValue);
63506381 ValueFromBlock slowButterfly = m_out.anchor(
63516382 m_out.loadPtr(slowObjectValue, m_heaps.JSObject_butterfly));

@@private:
63566387
63576388 object = m_out.phi(m_out.intPtr, fastObject, slowObject);
63586389 butterfly = m_out.phi(m_out.intPtr, fastButterfly, slowButterfly);
 6390
 6391 m_out.store32(publicLength, butterfly, m_heaps.Butterfly_publicLength);
 6392
 6393 initializeArrayElements(structure->indexingType(), vectorLength, butterfly);
 6394
 6395 HashMap<
 6396 int32_t, LValue, DefaultHash<int32_t>::Hash,
 6397 WTF::UnsignedWithZeroKeyHashTraits<int32_t>> indexMap;
 6398 Vector<int32_t> indices;
 6399 for (unsigned i = data.m_properties.size(); i--;) {
 6400 PromotedLocationDescriptor descriptor = data.m_properties[i];
 6401 if (descriptor.kind() != IndexedPropertyPLoc)
 6402 continue;
 6403 int32_t index = static_cast<int32_t>(descriptor.info());
 6404
 6405 auto result = indexMap.add(index, values[i]);
 6406 DFG_ASSERT(m_graph, m_node, result); // Duplicates are illegal.
 6407
 6408 indices.append(index);
 6409 }
 6410
 6411 if (!indices.isEmpty()) {
 6412 std::sort(indices.begin(), indices.end());
 6413
 6414 Vector<LBasicBlock> blocksWithStores(indices.size());
 6415 Vector<LBasicBlock> blocksWithChecks(indices.size());
 6416
 6417 for (unsigned i = indices.size(); i--;) {
 6418 blocksWithStores[i] = m_out.newBlock();
 6419 blocksWithChecks[i] = m_out.newBlock(); // blocksWithChecks[0] is the continuation.
 6420 }
 6421
 6422 LBasicBlock indexLastNext = m_out.m_nextBlock;
 6423
 6424 for (unsigned i = indices.size(); i--;) {
 6425 int32_t index = indices[i];
 6426 LValue value = indexMap.get(index);
 6427
 6428 m_out.branch(
 6429 m_out.below(m_out.constInt32(index), publicLength),
 6430 unsure(blocksWithStores[i]), unsure(blocksWithChecks[i]));
 6431
 6432 m_out.appendTo(blocksWithStores[i], blocksWithChecks[i]);
 6433
 6434 // This has to type-check and convert its inputs, but it cannot do so in a
 6435 // way that updates AI. That's a bit annoying, but if you think about how
 6436 // sinking works, it's actually not a bad thing. We are virtually guaranteed
 6437 // that these type checks will not fail, since the type checks that guarded
 6438 // the original stores to the array are still somewhere above this point.
 6439 Output::StoreType storeType;
 6440 IndexedAbstractHeap* heap;
 6441 switch (structure->indexingType()) {
 6442 case ALL_INT32_INDEXING_TYPES:
 6443 // FIXME: This could use the proven type if we had the Edge for the
 6444 // value. https://bugs.webkit.org/show_bug.cgi?id=155311
 6445 speculate(BadType, noValue(), nullptr, isNotInt32(value));
 6446 storeType = Output::Store64;
 6447 heap = &m_heaps.indexedInt32Properties;
 6448 break;
 6449
 6450 case ALL_DOUBLE_INDEXING_TYPES: {
 6451 // FIXME: If the source is ValueRep, we should avoid emitting any
 6452 // checks. We could also avoid emitting checks if we had the Edge of
 6453 // this value. https://bugs.webkit.org/show_bug.cgi?id=155311
 6454
 6455 LBasicBlock intCase = m_out.newBlock();
 6456 LBasicBlock doubleCase = m_out.newBlock();
 6457 LBasicBlock continuation = m_out.newBlock();
 6458
 6459 m_out.branch(isInt32(value), unsure(intCase), unsure(doubleCase));
 6460
 6461 LBasicBlock lastNext = m_out.appendTo(intCase, doubleCase);
 6462
 6463 ValueFromBlock intResult =
 6464 m_out.anchor(m_out.intToDouble(unboxInt32(value)));
 6465 m_out.jump(continuation);
 6466
 6467 m_out.appendTo(doubleCase, continuation);
 6468
 6469 speculate(BadType, noValue(), nullptr, isNumber(value));
 6470 ValueFromBlock doubleResult = m_out.anchor(unboxDouble(value));
 6471 m_out.jump(continuation);
 6472
 6473 m_out.appendTo(continuation, lastNext);
 6474 value = m_out.phi(Double, intResult, doubleResult);
 6475 storeType = Output::StoreDouble;
 6476 heap = &m_heaps.indexedDoubleProperties;
 6477 break;
 6478 }
 6479
 6480 case ALL_CONTIGUOUS_INDEXING_TYPES:
 6481 storeType = Output::Store64;
 6482 heap = &m_heaps.indexedContiguousProperties;
 6483 break;
 6484
 6485 default:
 6486 DFG_CRASH(m_graph, m_node, "Invalid indexing type");
 6487 break;
 6488 }
 6489
 6490 m_out.store(value, m_out.address(butterfly, heap->at(index)), storeType);
 6491
 6492 m_out.jump(blocksWithChecks[i]);
 6493 m_out.appendTo(
 6494 blocksWithChecks[i], i ? blocksWithStores[i - 1] : indexLastNext);
 6495 }
 6496 }
63596497 } else {
63606498 // In the easy case where we can do a one-shot allocation, we simply allocate the
63616499 // object to directly have the desired structure.

@@private:
63656503
63666504 for (PropertyMapEntry entry : structure->getPropertiesConcurrently()) {
63676505 for (unsigned i = data.m_properties.size(); i--;) {
6368  PhantomPropertyValue value = data.m_properties[i];
6369  if (m_graph.identifiers()[value.m_identifierNumber] != entry.key)
 6506 PromotedLocationDescriptor descriptor = data.m_properties[i];
 6507 if (descriptor.kind() != NamedPropertyPLoc)
 6508 continue;
 6509 if (m_graph.identifiers()[descriptor.info()] != entry.key)
63706510 continue;
63716511
63726512 LValue base = isInlineOffset(entry.offset) ? object : butterfly;
6373  storeProperty(values[i], base, value.m_identifierNumber, entry.offset);
 6513 storeProperty(values[i], base, descriptor.info(), entry.offset);
63746514 break;
63756515 }
63766516 }

@@private:
64356575 LValue activation = m_out.phi(m_out.intPtr, fastResult, slowResult);
64366576 RELEASE_ASSERT(data.m_properties.size() == table->scopeSize());
64376577 for (unsigned i = 0; i < data.m_properties.size(); ++i) {
6438  m_out.store64(values[i],
6439  activation,
6440  m_heaps.JSEnvironmentRecord_variables[data.m_properties[i].m_identifierNumber]);
 6578 PromotedLocationDescriptor descriptor = data.m_properties[i];
 6579 ASSERT(descriptor.kind() == ClosureVarPLoc);
 6580 m_out.store64(
 6581 values[i], activation,
 6582 m_heaps.JSEnvironmentRecord_variables[descriptor.info()]);
64416583 }
64426584
64436585 if (validationEnabled()) {

@@private:
64466588 for (auto iter = table->begin(locker), end = table->end(locker); iter != end; ++iter) {
64476589 bool found = false;
64486590 for (unsigned i = 0; i < data.m_properties.size(); ++i) {
6449  if (iter->value.scopeOffset().offset() == data.m_properties[i].m_identifierNumber) {
 6591 PromotedLocationDescriptor descriptor = data.m_properties[i];
 6592 ASSERT(descriptor.kind() == ClosureVarPLoc);
 6593 if (iter->value.scopeOffset().offset() == descriptor.info()) {
64506594 found = true;
64516595 break;
64526596 }

@@private:
66136757 m_out.store64(value, regExp, m_heaps.RegExpObject_lastIndex);
66146758 }
66156759
 6760 void compileRecordRegExpCachedResult()
 6761 {
 6762 Edge constructorEdge = m_graph.varArgChild(m_node, 0);
 6763 Edge regExpEdge = m_graph.varArgChild(m_node, 1);
 6764 Edge stringEdge = m_graph.varArgChild(m_node, 2);
 6765 Edge startEdge = m_graph.varArgChild(m_node, 3);
 6766 Edge endEdge = m_graph.varArgChild(m_node, 4);
 6767
 6768 LValue constructor = lowCell(constructorEdge);
 6769 LValue regExp = lowCell(regExpEdge);
 6770 LValue string = lowCell(stringEdge);
 6771 LValue start = lowInt32(startEdge);
 6772 LValue end = lowInt32(endEdge);
 6773
 6774 m_out.storePtr(regExp, constructor, m_heaps.RegExpConstructor_cachedResult_lastRegExp);
 6775 m_out.storePtr(string, constructor, m_heaps.RegExpConstructor_cachedResult_lastInput);
 6776 m_out.store32(start, constructor, m_heaps.RegExpConstructor_cachedResult_result_start);
 6777 m_out.store32(end, constructor, m_heaps.RegExpConstructor_cachedResult_result_end);
 6778 m_out.store32As8(
 6779 m_out.constInt32(0),
 6780 m_out.address(constructor, m_heaps.RegExpConstructor_cachedResult_reified));
 6781 }
 6782
66166783 LValue didOverflowStack()
66176784 {
66186785 // This does a very simple leaf function analysis. The invariant of FTL call

@@private:
69707137
69717138 return result;
69727139 }
 7140
 7141 void initializeArrayElements(IndexingType indexingType, LValue vectorLength, LValue butterfly)
 7142 {
 7143 if (!hasDouble(indexingType)) {
 7144 // The GC already initialized everything to JSValue() for us.
 7145 return;
 7146 }
 7147
 7148 // Doubles must be initialized to PNaN.
 7149 LBasicBlock initLoop = m_out.newBlock();
 7150 LBasicBlock initDone = m_out.newBlock();
 7151
 7152 ValueFromBlock originalIndex = m_out.anchor(vectorLength);
 7153 ValueFromBlock originalPointer = m_out.anchor(butterfly);
 7154 m_out.branch(
 7155 m_out.notZero32(vectorLength), unsure(initLoop), unsure(initDone));
 7156
 7157 LBasicBlock initLastNext = m_out.appendTo(initLoop, initDone);
 7158 LValue index = m_out.phi(m_out.int32, originalIndex);
 7159 LValue pointer = m_out.phi(m_out.intPtr, originalPointer);
 7160
 7161 m_out.store64(
 7162 m_out.constInt64(bitwise_cast<int64_t>(PNaN)),
 7163 TypedPointer(m_heaps.indexedDoubleProperties.atAnyIndex(), pointer));
 7164
 7165 LValue nextIndex = m_out.sub(index, m_out.int32One);
 7166 m_out.addIncomingToPhi(index, m_out.anchor(nextIndex));
 7167 m_out.addIncomingToPhi(pointer, m_out.anchor(m_out.add(pointer, m_out.intPtrEight)));
 7168 m_out.branch(
 7169 m_out.notZero32(nextIndex), unsure(initLoop), unsure(initDone));
 7170
 7171 m_out.appendTo(initDone, initLastNext);
 7172 }
69737173
69747174 LValue allocatePropertyStorage(LValue object, Structure* previousStructure)
69757175 {

@@private:
92579457 return proven;
92589458 return m_out.testNonZero64(jsValue, m_tagTypeNumber);
92599459 }
9260 
 9460
92619461 LValue unboxDouble(LValue jsValue)
92629462 {
92639463 return m_out.bitCast(m_out.add(jsValue, m_tagTypeNumber), m_out.doubleType);
197981

Source/JavaScriptCore/ftl/FTLOperations.cpp

@@namespace JSC { namespace FTL {
4141
4242using namespace JSC::DFG;
4343
44 extern "C" JSCell* JIT_OPERATION operationNewObjectWithButterfly(ExecState* exec, Structure* structure)
45 {
46  VM& vm = exec->vm();
47  NativeCallFrameTracer tracer(&vm, exec);
48 
49  Butterfly* butterfly = Butterfly::create(
50  vm, nullptr, 0, structure->outOfLineCapacity(), false, IndexingHeader(), 0);
51 
52  JSObject* result = JSFinalObject::create(exec, structure, butterfly);
53  result->butterfly(); // Ensure that the butterfly is in to-space.
54  return result;
55 }
56 
5744extern "C" void JIT_OPERATION operationPopulateObjectInOSR(
5845 ExecState* exec, ExitTimeObjectMaterialization* materialization,
5946 EncodedJSValue* encodedValue, EncodedJSValue* values)
197981

Source/JavaScriptCore/ftl/FTLOperations.h

@@class LazySlowPath;
3737
3838extern "C" {
3939
40 JSCell* JIT_OPERATION operationNewObjectWithButterfly(ExecState*, Structure*) WTF_INTERNAL;
41 
4240JSCell* JIT_OPERATION operationMaterializeObjectInOSR(
4341 ExecState*, ExitTimeObjectMaterialization*, EncodedJSValue*) WTF_INTERNAL;
4442
197981

Source/JavaScriptCore/runtime/JSObject.h

@@class JSObject : public JSCell {
9696public:
9797 typedef JSCell Base;
9898
 99 // This is a super dangerous method for JITs. Sometimes the JITs will want to create either a
 100 // JSFinalObject or a JSArray. This is the method that will do that.
 101 static JSObject* createRawObject(ExecState* exec, Structure* structure, Butterfly* = nullptr);
 102
99103 JS_EXPORT_PRIVATE static size_t estimatedSize(JSCell*);
100104 JS_EXPORT_PRIVATE static void visitChildren(JSCell*, SlotVisitor&);
101105 JS_EXPORT_PRIVATE static void copyBackingStore(JSCell*, CopyVisitor&, CopyToken);

@@private:
10341038
10351039JS_EXPORT_PRIVATE EncodedJSValue JSC_HOST_CALL objectPrivateFuncInstanceOf(ExecState*);
10361040
 1041inline JSObject* JSObject::createRawObject(
 1042 ExecState* exec, Structure* structure, Butterfly* butterfly)
 1043{
 1044 JSObject* finalObject = new (
 1045 NotNull,
 1046 allocateCell<JSFinalObject>(
 1047 *exec->heap(),
 1048 JSFinalObject::allocationSize(structure->inlineCapacity())
 1049 )
 1050 ) JSObject(exec->vm(), structure, butterfly);
 1051 finalObject->finishCreation(exec->vm());
 1052 return finalObject;
 1053}
 1054
10371055inline JSFinalObject* JSFinalObject::create(
10381056 ExecState* exec, Structure* structure, Butterfly* butterfly)
10391057{
197981

Source/JavaScriptCore/runtime/RegExp.cpp

@@RegExp* RegExp::create(VM& vm, const Str
262262
263263void RegExp::compile(VM* vm, Yarr::YarrCharSize charSize)
264264{
 265 ConcurrentJITLocker locker(m_lock);
 266
265267 Yarr::YarrPattern pattern(m_patternString, m_flags, &m_constructionError);
266268 if (m_constructionError) {
267269 RELEASE_ASSERT_NOT_REACHED();

@@int RegExp::match(VM& vm, const String&
299301 return matchInline(vm, s, startOffset, ovector);
300302}
301303
 304bool RegExp::matchConcurrently(
 305 VM& vm, const String& s, unsigned startOffset, int& position, Vector<int, 32>& ovector)
 306{
 307 ConcurrentJITLocker locker(m_lock);
 308
 309 if (!hasCodeFor(s.is8Bit() ? Yarr::Char8 : Yarr::Char16))
 310 return false;
 311
 312 position = match(vm, s, startOffset, ovector);
 313 return true;
 314}
 315
302316void RegExp::compileMatchOnly(VM* vm, Yarr::YarrCharSize charSize)
303317{
 318 ConcurrentJITLocker locker(m_lock);
 319
304320 Yarr::YarrPattern pattern(m_patternString, m_flags, &m_constructionError);
305321 if (m_constructionError) {
306322 RELEASE_ASSERT_NOT_REACHED();

@@MatchResult RegExp::match(VM& vm, const
340356
341357void RegExp::deleteCode()
342358{
 359 ConcurrentJITLocker locker(m_lock);
 360
343361 if (!hasCode())
344362 return;
345363 m_state = NotCompiled;
197981

Source/JavaScriptCore/runtime/RegExp.h

2222#ifndef RegExp_h
2323#define RegExp_h
2424
 25#include "ConcurrentJITLock.h"
2526#include "ExecutableAllocator.h"
2627#include "MatchResult.h"
2728#include "RegExpKey.h"

@@public:
5657 bool ignoreCase() const { return m_flags & FlagIgnoreCase; }
5758 bool multiline() const { return m_flags & FlagMultiline; }
5859 bool sticky() const { return m_flags & FlagSticky; }
 60 bool globalOrSticky() const { return global() || sticky(); }
5961 bool unicode() const { return m_flags & FlagUnicode; }
6062
6163 const String& pattern() const { return m_patternString; }

@@public:
6466 const char* errorMessage() const { return m_constructionError; }
6567
6668 JS_EXPORT_PRIVATE int match(VM&, const String&, unsigned startOffset, Vector<int, 32>& ovector);
 69
 70 // Returns false if we couldn't run the regular expression for any reason.
 71 bool matchConcurrently(VM&, const String&, unsigned startOffset, int& position, Vector<int, 32>& ovector);
 72
6773 JS_EXPORT_PRIVATE MatchResult match(VM&, const String&, unsigned startOffset);
6874
6975 // Call these versions of the match functions if you're desperate for performance.

@@public:
7783 return m_state != NotCompiled;
7884 }
7985
 86 bool hasCodeFor(Yarr::YarrCharSize);
 87
8088 void deleteCode();
8189
8290#if ENABLE(REGEXP_TRACING)

@@private:
132140 unsigned m_rtMatchCallCount;
133141 unsigned m_rtMatchFoundCount;
134142#endif
 143 ConcurrentJITLock m_lock;
135144
136145#if ENABLE(YARR_JIT)
137146 Yarr::YarrCodeBlock m_regExpJITCode;
197981

Source/JavaScriptCore/runtime/RegExpCachedResult.h

@@public:
7474
7575 void visitChildren(SlotVisitor&);
7676
 77 static ptrdiff_t offsetOfLastRegExp() { return OBJECT_OFFSETOF(RegExpCachedResult, m_lastRegExp); }
 78 static ptrdiff_t offsetOfLastInput() { return OBJECT_OFFSETOF(RegExpCachedResult, m_lastInput); }
 79 static ptrdiff_t offsetOfResult() { return OBJECT_OFFSETOF(RegExpCachedResult, m_result); }
 80 static ptrdiff_t offsetOfReified() { return OBJECT_OFFSETOF(RegExpCachedResult, m_reified); }
 81
7782private:
7883 MatchResult m_result;
7984 bool m_reified;
197981

Source/JavaScriptCore/runtime/RegExpConstructor.h

@@public:
6969
7070 static void visitChildren(JSCell*, SlotVisitor&);
7171
 72 static ptrdiff_t offsetOfCachedResult() { return OBJECT_OFFSETOF(RegExpConstructor, m_cachedResult); }
 73
7274protected:
7375 void finishCreation(VM&, RegExpPrototype*, GetterSetter* species);
7476
197981

Source/JavaScriptCore/runtime/RegExpInlines.h

@@private:
6767};
6868#endif // REGEXP_FUNC_TEST_DATA_GEN
6969
70 ALWAYS_INLINE void RegExp::compileIfNecessary(VM& vm, Yarr::YarrCharSize charSize)
 70ALWAYS_INLINE bool RegExp::hasCodeFor(Yarr::YarrCharSize charSize)
7171{
7272 if (hasCode()) {
7373#if ENABLE(YARR_JIT)
7474 if (m_state != JITCode)
75  return;
 75 return true;
7676 if ((charSize == Yarr::Char8) && (m_regExpJITCode.has8BitCode()))
77  return;
 77 return true;
7878 if ((charSize == Yarr::Char16) && (m_regExpJITCode.has16BitCode()))
79  return;
 79 return true;
8080#else
81  return;
 81 return true;
8282#endif
8383 }
 84 return false;
 85}
 86
 87ALWAYS_INLINE void RegExp::compileIfNecessary(VM& vm, Yarr::YarrCharSize charSize)
 88{
 89 if (hasCodeFor(charSize))
 90 return;
8491
8592 compile(&vm, charSize);
8693}
197981

Source/JavaScriptCore/runtime/RegExpMatchesArray.h

@@ALWAYS_INLINE JSArray* createRegExpMatch
5656
5757 Vector<int, 32> subpatternResults;
5858 int position = regExp->matchInline(vm, inputValue, startOffset, subpatternResults);
 59 ASSERT(position == subpatternResults[0]);
5960 if (position == -1) {
6061 result = MatchResult::failed();
6162 return nullptr;
197981

Source/JavaScriptCore/runtime/RegExpObjectInlines.h

@@JSValue RegExpObject::execInline(ExecSta
6363 String input = string->value(exec); // FIXME: Handle errors. https://bugs.webkit.org/show_bug.cgi?id=155145
6464 VM& vm = globalObject->vm();
6565
66  bool globalOrSticky = regExp->global() || regExp->sticky();
 66 bool globalOrSticky = regExp->globalOrSticky();
6767
6868 unsigned lastIndex;
6969 if (globalOrSticky) {
197981

Source/JavaScriptCore/tests/stress/simple-regexp-exec-folding.js

 1function foo() {
 2 return /(f)(o)(o)/.exec("foo");
 3}
 4
 5noInline(foo);
 6
 7for (var i = 0; i < 10000; ++i) {
 8 var result = foo();
 9 if (result.length != 4)
 10 throw "Error: bad result: " + result;
 11 if (result[0] != "foo")
 12 throw "Error: bad result: " + result;
 13 if (result[1] != "f")
 14 throw "Error: bad result: " + result;
 15 if (result[2] != "o")
 16 throw "Error: bad result: " + result;
 17 if (result[3] != "o")
 18 throw "Error: bad result: " + result;
 19}
0

Source/WTF/wtf/Insertion.h

11/*
2  * Copyright (C) 2013, 2015 Apple Inc. All rights reserved.
 2 * Copyright (C) 2013, 2015-2016 Apple Inc. All rights reserved.
33 *
44 * Redistribution and use in source and binary forms, with or without
55 * modification, are permitted provided that the following conditions

@@private:
5555};
5656
5757template<typename TargetVectorType, typename InsertionVectorType>
58 void executeInsertions(TargetVectorType& target, InsertionVectorType& insertions)
 58size_t executeInsertions(TargetVectorType& target, InsertionVectorType& insertions)
5959{
60  if (!insertions.size())
61  return;
62  target.grow(target.size() + insertions.size());
 60 size_t numInsertions = insertions.size();
 61 if (!numInsertions)
 62 return 0;
 63 target.grow(target.size() + numInsertions);
6364 size_t lastIndex = target.size();
6465 size_t originalTargetSize = target.size();
65  for (size_t indexInInsertions = insertions.size(); indexInInsertions--;) {
 66 for (size_t indexInInsertions = numInsertions; indexInInsertions--;) {
6667 ASSERT(!indexInInsertions || insertions[indexInInsertions].index() >= insertions[indexInInsertions - 1].index());
6768 ASSERT_UNUSED(originalTargetSize, insertions[indexInInsertions].index() < originalTargetSize);
6869 size_t firstIndex = insertions[indexInInsertions].index() + indexInInsertions;

@@void executeInsertions(TargetVectorType&
7374 lastIndex = firstIndex;
7475 }
7576 insertions.resize(0);
 77 return numInsertions;
7678}
7779
7880} // namespace WTF
197981

LayoutTests/js/regress/simple-regexp-exec-folding-expected.txt

 1JSRegress/simple-regexp-exec-folding
 2
 3On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 4
 5
 6PASS no exception thrown
 7PASS successfullyParsed is true
 8
 9TEST COMPLETE
 10
0

LayoutTests/js/regress/simple-regexp-exec-folding.html

 1<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
 2<html>
 3<head>
 4<script src="../../resources/js-test-pre.js"></script>
 5</head>
 6<body>
 7<script src="../../resources/regress-pre.js"></script>
 8<script src="script-tests/simple-regexp-exec-folding.js"></script>
 9<script src="../../resources/regress-post.js"></script>
 10<script src="../../resources/js-test-post.js"></script>
 11</body>
 12</html>
0

LayoutTests/js/regress/script-tests/simple-regexp-exec-folding.js

 1(function() {
 2 for (var i = 0; i < 1000000; ++i)
 3 /foo/.exec("foo");
 4})();
 5
0