| Differences between
and this patch
- Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj -4 / +12 lines
Lines 86-91 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec1
86
		0F04396E1B03DC0B009598B7 /* DFGCombinedLiveness.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F04396C1B03DC0B009598B7 /* DFGCombinedLiveness.h */; settings = {ATTRIBUTES = (Private, ); }; };
86
		0F04396E1B03DC0B009598B7 /* DFGCombinedLiveness.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F04396C1B03DC0B009598B7 /* DFGCombinedLiveness.h */; settings = {ATTRIBUTES = (Private, ); }; };
87
		0F05C3B41683CF9200BAF45B /* DFGArrayifySlowPathGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F05C3B21683CF8F00BAF45B /* DFGArrayifySlowPathGenerator.h */; settings = {ATTRIBUTES = (Private, ); }; };
87
		0F05C3B41683CF9200BAF45B /* DFGArrayifySlowPathGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F05C3B21683CF8F00BAF45B /* DFGArrayifySlowPathGenerator.h */; settings = {ATTRIBUTES = (Private, ); }; };
88
		0F0776BF14FF002B00102332 /* JITCompilationEffort.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0776BD14FF002800102332 /* JITCompilationEffort.h */; settings = {ATTRIBUTES = (Private, ); }; };
88
		0F0776BF14FF002B00102332 /* JITCompilationEffort.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0776BD14FF002800102332 /* JITCompilationEffort.h */; settings = {ATTRIBUTES = (Private, ); }; };
89
		0F0A75221B94BFA900110660 /* InferredType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F0A75201B94BFA900110660 /* InferredType.cpp */; };
90
		0F0A75231B94BFA900110660 /* InferredType.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0A75211B94BFA900110660 /* InferredType.h */; settings = {ATTRIBUTES = (Private, ); }; };
89
		0F0B839C14BCF46300885B4F /* LLIntThunks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F0B839714BCF45A00885B4F /* LLIntThunks.cpp */; };
91
		0F0B839C14BCF46300885B4F /* LLIntThunks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F0B839714BCF45A00885B4F /* LLIntThunks.cpp */; };
90
		0F0B839D14BCF46600885B4F /* LLIntThunks.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0B839814BCF45A00885B4F /* LLIntThunks.h */; settings = {ATTRIBUTES = (Private, ); }; };
92
		0F0B839D14BCF46600885B4F /* LLIntThunks.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0B839814BCF45A00885B4F /* LLIntThunks.h */; settings = {ATTRIBUTES = (Private, ); }; };
91
		0F0B83A714BCF50700885B4F /* CodeType.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0B83A514BCF50400885B4F /* CodeType.h */; settings = {ATTRIBUTES = (Private, ); }; };
93
		0F0B83A714BCF50700885B4F /* CodeType.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0B83A514BCF50400885B4F /* CodeType.h */; settings = {ATTRIBUTES = (Private, ); }; };
Lines 1907-1912 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec2
1907
		0F04396C1B03DC0B009598B7 /* DFGCombinedLiveness.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGCombinedLiveness.h; path = dfg/DFGCombinedLiveness.h; sourceTree = "<group>"; };
1909
		0F04396C1B03DC0B009598B7 /* DFGCombinedLiveness.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGCombinedLiveness.h; path = dfg/DFGCombinedLiveness.h; sourceTree = "<group>"; };
1908
		0F05C3B21683CF8F00BAF45B /* DFGArrayifySlowPathGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGArrayifySlowPathGenerator.h; path = dfg/DFGArrayifySlowPathGenerator.h; sourceTree = "<group>"; };
1910
		0F05C3B21683CF8F00BAF45B /* DFGArrayifySlowPathGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGArrayifySlowPathGenerator.h; path = dfg/DFGArrayifySlowPathGenerator.h; sourceTree = "<group>"; };
1909
		0F0776BD14FF002800102332 /* JITCompilationEffort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITCompilationEffort.h; sourceTree = "<group>"; };
1911
		0F0776BD14FF002800102332 /* JITCompilationEffort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITCompilationEffort.h; sourceTree = "<group>"; };
1912
		0F0A75201B94BFA900110660 /* InferredType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InferredType.cpp; sourceTree = "<group>"; };
1913
		0F0A75211B94BFA900110660 /* InferredType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InferredType.h; sourceTree = "<group>"; };
1910
		0F0B839714BCF45A00885B4F /* LLIntThunks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LLIntThunks.cpp; path = llint/LLIntThunks.cpp; sourceTree = "<group>"; };
1914
		0F0B839714BCF45A00885B4F /* LLIntThunks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LLIntThunks.cpp; path = llint/LLIntThunks.cpp; sourceTree = "<group>"; };
1911
		0F0B839814BCF45A00885B4F /* LLIntThunks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLIntThunks.h; path = llint/LLIntThunks.h; sourceTree = "<group>"; };
1915
		0F0B839814BCF45A00885B4F /* LLIntThunks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLIntThunks.h; path = llint/LLIntThunks.h; sourceTree = "<group>"; };
1912
		0F0B83A514BCF50400885B4F /* CodeType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeType.h; sourceTree = "<group>"; };
1916
		0F0B83A514BCF50400885B4F /* CodeType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeType.h; sourceTree = "<group>"; };
Lines 4628-4635 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec3
4628
				BC02E98B0E183E38000F9297 /* ErrorInstance.h */,
4632
				BC02E98B0E183E38000F9297 /* ErrorInstance.h */,
4629
				BC02E9060E1839DB000F9297 /* ErrorPrototype.cpp */,
4633
				BC02E9060E1839DB000F9297 /* ErrorPrototype.cpp */,
4630
				BC02E9070E1839DB000F9297 /* ErrorPrototype.h */,
4634
				BC02E9070E1839DB000F9297 /* ErrorPrototype.h */,
4631
				FE1C0FFC1B193E9800B53FCA /* Exception.h */,
4632
				FE1C0FFE1B194FD100B53FCA /* Exception.cpp */,
4635
				FE1C0FFE1B194FD100B53FCA /* Exception.cpp */,
4636
				FE1C0FFC1B193E9800B53FCA /* Exception.h */,
4633
				0F12DE0D1979D5FD0006FF4E /* ExceptionFuzz.cpp */,
4637
				0F12DE0D1979D5FD0006FF4E /* ExceptionFuzz.cpp */,
4634
				0F12DE0E1979D5FD0006FF4E /* ExceptionFuzz.h */,
4638
				0F12DE0E1979D5FD0006FF4E /* ExceptionFuzz.h */,
4635
				1429D8770ED21ACD00B89619 /* ExceptionHelpers.cpp */,
4639
				1429D8770ED21ACD00B89619 /* ExceptionHelpers.cpp */,
Lines 4662-4667 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec4
4662
				0FB7F38E15ED8E3800F167B2 /* IndexingHeaderInlines.h */,
4666
				0FB7F38E15ED8E3800F167B2 /* IndexingHeaderInlines.h */,
4663
				0F13E04C16164A1B00DC8DE7 /* IndexingType.cpp */,
4667
				0F13E04C16164A1B00DC8DE7 /* IndexingType.cpp */,
4664
				0FB7F38F15ED8E3800F167B2 /* IndexingType.h */,
4668
				0FB7F38F15ED8E3800F167B2 /* IndexingType.h */,
4669
				0F0A75201B94BFA900110660 /* InferredType.cpp */,
4670
				0F0A75211B94BFA900110660 /* InferredType.h */,
4665
				0FF8BDE81AD4CF7100DFE884 /* InferredValue.cpp */,
4671
				0FF8BDE81AD4CF7100DFE884 /* InferredValue.cpp */,
4666
				0FF8BDE91AD4CF7100DFE884 /* InferredValue.h */,
4672
				0FF8BDE91AD4CF7100DFE884 /* InferredValue.h */,
4667
				E178636C0D9BEEC300D74E75 /* InitializeThreading.cpp */,
4673
				E178636C0D9BEEC300D74E75 /* InitializeThreading.cpp */,
Lines 4712-4721 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec5
4712
				0F2B66BC17B6B5AB00A7AE3F /* JSArrayBufferViewInlines.h */,
4718
				0F2B66BC17B6B5AB00A7AE3F /* JSArrayBufferViewInlines.h */,
4713
				A7BDAEC417F4EA1400F6140C /* JSArrayIterator.cpp */,
4719
				A7BDAEC417F4EA1400F6140C /* JSArrayIterator.cpp */,
4714
				A7BDAEC517F4EA1400F6140C /* JSArrayIterator.h */,
4720
				A7BDAEC517F4EA1400F6140C /* JSArrayIterator.h */,
4715
				86FA9E8F142BBB2D001773B7 /* JSBoundFunction.cpp */,
4716
				86FA9E90142BBB2E001773B7 /* JSBoundFunction.h */,
4717
				8B0F424B1ABD6DE2003917EA /* JSArrowFunction.cpp */,
4721
				8B0F424B1ABD6DE2003917EA /* JSArrowFunction.cpp */,
4718
				8B0F424A1ABD6D2F003917EA /* JSArrowFunction.h */,
4722
				8B0F424A1ABD6D2F003917EA /* JSArrowFunction.h */,
4723
				86FA9E8F142BBB2D001773B7 /* JSBoundFunction.cpp */,
4724
				86FA9E90142BBB2E001773B7 /* JSBoundFunction.h */,
4719
				657CF45619BF6662004ACBF2 /* JSCallee.cpp */,
4725
				657CF45619BF6662004ACBF2 /* JSCallee.cpp */,
4720
				657CF45719BF6662004ACBF2 /* JSCallee.h */,
4726
				657CF45719BF6662004ACBF2 /* JSCallee.h */,
4721
				BC7F8FBA0E19D1EF008632C0 /* JSCell.cpp */,
4727
				BC7F8FBA0E19D1EF008632C0 /* JSCell.cpp */,
Lines 5013-5021 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec6
5013
				0FE050241AA9095600D33B33 /* VarOffset.h */,
5019
				0FE050241AA9095600D33B33 /* VarOffset.h */,
5014
				E18E3A570DF9278C00D90B34 /* VM.cpp */,
5020
				E18E3A570DF9278C00D90B34 /* VM.cpp */,
5015
				E18E3A560DF9278C00D90B34 /* VM.h */,
5021
				E18E3A560DF9278C00D90B34 /* VM.h */,
5016
				FE90BB3A1B7CF64E006B3F03 /* VMInlines.h */,
5017
				FE5932A5183C5A2600A1ECCC /* VMEntryScope.cpp */,
5022
				FE5932A5183C5A2600A1ECCC /* VMEntryScope.cpp */,
5018
				FE5932A6183C5A2600A1ECCC /* VMEntryScope.h */,
5023
				FE5932A6183C5A2600A1ECCC /* VMEntryScope.h */,
5024
				FE90BB3A1B7CF64E006B3F03 /* VMInlines.h */,
5019
				FED94F2B171E3E2300BE77A4 /* Watchdog.cpp */,
5025
				FED94F2B171E3E2300BE77A4 /* Watchdog.cpp */,
5020
				FED94F2C171E3E2300BE77A4 /* Watchdog.h */,
5026
				FED94F2C171E3E2300BE77A4 /* Watchdog.h */,
5021
				14BFCE6810CDB1FC00364CCE /* WeakGCMap.h */,
5027
				14BFCE6810CDB1FC00364CCE /* WeakGCMap.h */,
Lines 6008-6013 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec7
6008
				0FBD7E691447999600481315 /* CodeOrigin.h in Headers */,
6014
				0FBD7E691447999600481315 /* CodeOrigin.h in Headers */,
6009
				7B0247591B868EB700542440 /* WASMFunctionSyntaxChecker.h in Headers */,
6015
				7B0247591B868EB700542440 /* WASMFunctionSyntaxChecker.h in Headers */,
6010
				0F21C27D14BE727A00ADC64B /* CodeSpecializationKind.h in Headers */,
6016
				0F21C27D14BE727A00ADC64B /* CodeSpecializationKind.h in Headers */,
6017
				0F0A75231B94BFA900110660 /* InferredType.h in Headers */,
6011
				0F0B83A714BCF50700885B4F /* CodeType.h in Headers */,
6018
				0F0B83A714BCF50700885B4F /* CodeType.h in Headers */,
6012
				BC18C3F30E16F5CD00B34460 /* CommonIdentifiers.h in Headers */,
6019
				BC18C3F30E16F5CD00B34460 /* CommonIdentifiers.h in Headers */,
6013
				709FB86C1AE335C60039D069 /* WeakSetPrototype.h in Headers */,
6020
				709FB86C1AE335C60039D069 /* WeakSetPrototype.h in Headers */,
Lines 7811-7816 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec8
7811
				86C568E011A213EE0007F7F0 /* MacroAssemblerARM.cpp in Sources */,
7818
				86C568E011A213EE0007F7F0 /* MacroAssemblerARM.cpp in Sources */,
7812
				E33F50741B8421C000413856 /* JSInternalPromisePrototype.cpp in Sources */,
7819
				E33F50741B8421C000413856 /* JSInternalPromisePrototype.cpp in Sources */,
7813
				A729009C17976C6000317298 /* MacroAssemblerARMv7.cpp in Sources */,
7820
				A729009C17976C6000317298 /* MacroAssemblerARMv7.cpp in Sources */,
7821
				0F0A75221B94BFA900110660 /* InferredType.cpp in Sources */,
7814
				A53CE08518BC1A5600BEDF76 /* ConsolePrototype.cpp in Sources */,
7822
				A53CE08518BC1A5600BEDF76 /* ConsolePrototype.cpp in Sources */,
7815
				A7A4AE0817973B26005612B1 /* MacroAssemblerX86Common.cpp in Sources */,
7823
				A7A4AE0817973B26005612B1 /* MacroAssemblerX86Common.cpp in Sources */,
7816
				A5B6A74D18C6DBA600F11E91 /* ConsoleClient.cpp in Sources */,
7824
				A5B6A74D18C6DBA600F11E91 /* ConsoleClient.cpp in Sources */,
- Source/JavaScriptCore/bytecode/Watchpoint.h -1 / +33 lines
Lines 335-341 public: Source/JavaScriptCore/bytecode/Watchpoint.h_sec1
335
    {
335
    {
336
        touch(StringFireDetail(reason));
336
        touch(StringFireDetail(reason));
337
    }
337
    }
338
    
338
339
    // Note that for any watchpoint that is visible from the DFG, it would be incorrect to write code like:
340
    //
341
    // if (w.isBeingWatched())
342
    //     w.fireAll()
343
    //
344
    // Concurrently to this, the DFG could do:
345
    //
346
    // if (w.isStillValid())
347
    //     perform optimizations;
348
    // if (!w.isStillValid())
349
    //     retry compilation;
350
    //
351
    // Note that the DFG algorithm is widespread, and sound, because fireAll() and invalidate() will leave
352
    // the watchpoint in a !isStillValid() state. Hence, if fireAll() or invalidate() interleaved between
353
    // the first isStillValid() check and the second one, then it would simply cause the DFG to retry
354
    // compilation later.
355
    //
356
    // But, if you change some piece of state that the DFG might optimize for, but invalidate the
357
    // watchpoint by doing:
358
    //
359
    // if (w.isBeingWatched())
360
    //     w.fireAll()
361
    //
362
    // then the DFG would never know that you invalidated state between the two checks.
363
    //
364
    // There are two ways to work around this:
365
    //
366
    // - Call fireAll() without a isBeingWatched() check. Then, the DFG will know that the watchpoint has
367
    //   been invalidated when it does its second check.
368
    //
369
    // - Do not expose the watchpoint set to the DFG directly, and have your own way of validating whether
370
    //   the assumptions that the DFG thread used are still valid when the DFG code is installed.
339
    bool isBeingWatched() const
371
    bool isBeingWatched() const
340
    {
372
    {
341
        if (isFat())
373
        if (isFat())
- Source/JavaScriptCore/runtime/InferredType.cpp +373 lines
Line 0 Source/JavaScriptCore/runtime/InferredType.cpp_sec1
1
/*
2
 * Copyright (C) 2015 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
#include "config.h"
27
#include "InferredType.h"
28
29
namespace JSC {
30
31
const ClassInfo InferredType::s_info = { "InferredType", 0, 0, CREATE_METHOD_TABLE(InferredType) };
32
33
InferredType* InferredType::create(VM& vm)
34
{
35
    InferredType* result = new (NotNull, allocateCell<InferredType>(vm.heap)) InferredType(vm);
36
    result->finishCreation();
37
    return result;
38
}
39
40
void InferredType::destroy(JSCell* cell)
41
{
42
    InferredType* inferredType = static_cast<InferredType*>(cell);
43
    inferredType->InferredType::~InferredType();
44
}
45
46
Structure* InferredType::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
47
{
48
    return Structure::create(vm, globalObject, prototype, TypeInfo(CellType, StructureFlags), info());
49
}
50
51
void InferredType::visitChildren(JSCell* cell, SlotVisitor& visitor)
52
{
53
    InferredType* inferredType = jsCast<InferredType*>(cell);
54
55
    if (inferredType->m_structure)
56
        visitor.addUnconditionalFinalizer(inferredType->m_structure.get());
57
}
58
59
InferredType::Descriptor InferredType::Descriptor::forValue(JSValue value)
60
{
61
    if (value.isBoolean())
62
        return Boolean;
63
    if (value.isUndefinedOrNull())
64
        return Other;
65
    if (value.isInt32())
66
        return Int32;
67
    if (value.isDouble())
68
        return Double;
69
    if (value.isCell()) {
70
        JSCell* cell = value.asCell();
71
        if (cell->isString())
72
            return String;
73
        if (cell->isObject()) {
74
            if (cell->structure()->transitionWatchpointSetIsStillValid())
75
                return Descriptor(ObjectWithStructure, cell->structure());
76
            return Object;
77
        }
78
    }
79
    return Top;
80
}
81
82
void InferredType::Descriptor::merge(const Descriptor& other)
83
{
84
    if (*this == other)
85
        return;
86
    
87
    switch (m_kind) {
88
    case Bottom:
89
        *this = other;
90
        return;
91
    case Boolean:
92
    case String:
93
        *this = Top;
94
        return;
95
    case Other:
96
        switch (other.m_kind) {
97
        case ObjectWithStructure:
98
            m_kind = ObjectWithStructureOrOther;
99
            return;
100
        case Object:
101
            m_kind = ObjectOrOther;
102
            return;
103
        default:
104
            *this = Top;
105
            return;
106
        }
107
    case Int32:
108
        switch (other.m_kind) {
109
        case Double:
110
        case Number:
111
            m_kind = Number;
112
            return;
113
        default:
114
            *this = Top;
115
            return;
116
        }
117
    case Double:
118
        switch (other.m_kind) {
119
        case Int32:
120
        case Number:
121
            m_kind = Number;
122
            return;
123
        default:
124
            *this = Top;
125
            return;
126
        }
127
    case Number:
128
        switch (other.m_kind) {
129
        case Int32:
130
        case Double:
131
            return;
132
        default:
133
            *this = Top;
134
            return;
135
        }
136
    case ObjectWithStructure:
137
        switch (other.m_kind) {
138
        case ObjectWithStructure:
139
        case Object:
140
            *this = Object;
141
            return;
142
        case ObjectWithStructureOrOther:
143
            if (m_structure == other.m_structure) {
144
                *this = other;
145
                return;
146
            }
147
            *this = ObjectOrOther;
148
            return;
149
        case ObjectOrOther:
150
            *this = ObjectOrOther;
151
            return;
152
        case Other:
153
            m_kind = ObjectWithStructureOrOther;
154
            return;
155
        default:
156
            *this = Top;
157
            return;
158
        }
159
    case ObjectWithStructureOrOther:
160
        switch (other.m_kind) {
161
        case ObjectWithStructure:
162
            if (m_structure == other.m_structure)
163
                return;
164
            *this = ObjectOrOther;
165
            return;
166
        case Object:
167
        case ObjectWithStructureOrOther:
168
        case ObjectOrOther:
169
            *this = ObjectOrOther;
170
            return;
171
        case Other:
172
            return;
173
        default:
174
            *this = Top;
175
            return;
176
        }
177
    case Object:
178
        switch (other.m_kind) {
179
        case ObjectWithStructure:
180
            return;
181
        case ObjectWithStructureOrOther:
182
        case ObjectOrOther:
183
        case Other:
184
            m_kind = ObjectOrOther;
185
            return;
186
        default:
187
            *this = Top;
188
            return;
189
        }
190
    case ObjectOrOther:
191
        switch (other.m_kind) {
192
        case ObjectWithStructure:
193
        case ObjectWithStructureOrOther:
194
        case Object:
195
        case Other:
196
            return;
197
        default:
198
            *this = Top;
199
            return;
200
        }
201
    case Top:
202
        return;
203
    }
204
205
    RELEASE_ASSERT_NOT_REACHED();
206
}
207
208
void InferredType::Descriptor::removeStructure()
209
{
210
    switch (m_kind) {
211
    case ObjectWithStructure:
212
        *this = Object;
213
        return;
214
    case ObjectWithStructureOrOther:
215
        *this = ObjectOrOther;
216
        return;
217
    default:
218
        return;
219
    }
220
}
221
222
bool InferredType::Descriptor::subsumes(const Descriptor& other) const
223
{
224
    Descriptor merged = *this;
225
    merged.merge(other);
226
    return *this == merged;
227
}
228
229
void InferredType::Descriptor::dump(PrintStream& out) const
230
{
231
    out.print(m_kind);
232
    if (m_structure)
233
        out.print(":", *m_structure);
234
}
235
236
InferredType::InferredType(VM& vm)
237
    : Base(vm, vm.inferredTypeStructure.get())
238
    , m_watchpointSet(ClearWatchpoint)
239
{
240
}
241
242
InferredType::~InferredType()
243
{
244
}
245
246
bool InferredType::isStillValid(const ConcurrentJITLocker& locker, const Descriptor& expected)
247
{
248
    if (expected.kind() == Top)
249
        return false;
250
    
251
    return descriptor(locker) == expected;
252
}
253
254
bool InferredType::isStillValid(const Descriptor& expected)
255
{
256
    ConcurrentJITLocker locker(m_lock);
257
    return isStillValid(locker, expected);
258
}
259
260
void InferredType::addWatchpoint(const ConcurrentJITLocker& locker, Watchpoint* watchpoint)
261
{
262
    RELEASE_ASSERT(descriptor(locker).kind() != Top);
263
264
    m_watchpointSet.add(watchpoint);
265
}
266
267
void InferredType::addWatchpoint(Watchpoint* watchpoint)
268
{
269
    ConcurrentJITLocker locker(m_lock);
270
    addWatchpoint(locker, watchpoint);
271
}
272
273
void InferredType::dump(PrintStream& out) const
274
{
275
    out.print(descriptor());
276
}
277
278
void InferredType::willStoreValueSlow(const ConcurrentJITLocker& locker, VM& vm, JSValue value)
279
{
280
    Descriptor myType = descriptor(locker);
281
    Descriptor otherType = Descriptor::forValue(value);
282
283
    myType.merge(otherType);
284
285
    ASSERT(descriptor(locker) != myType); // The type must have changed if we're on the slow path.
286
287
    set(locker, vm, myType);
288
}
289
290
void InferredType::set(const ConcurrentJITLocker& locker, VM& vm, Descriptor newDescriptor)
291
{
292
    // Be defensive: if we're not really changing the type, then we don't have to do anything.
293
    if (descriptor(locker) == newDescriptor)
294
        return;
295
296
    // The new descriptor must be more general than the previous one.
297
    ASSERT(newDescriptor.subsumes(descriptor(locker)));
298
299
    // If the new descriptors have different structures, then it can only be because one is null.
300
    if (descriptor(locker).structure() != newDescriptor.structure())
301
        ASSERT(!descriptor(locker).structure() || !newDescriptor.structure());
302
303
    // We are changing the type, so make sure that if anyone was watching, they find out about it now. If
304
    // anyone is watching, we make sure to go to Top so that we don't do this sort of thing again.
305
    if (m_watchpointSet.state() != ClearWatchpoint) {
306
        // We cannot have been invalidated, since if we were, then we'd already be at Top.
307
        ASSERT(m_watchpointSet.state() != IsInvalidated);
308
309
        // We're about to do expensive things because some compiler thread decided to watch this type and
310
        // then the type changed. Assume that this property is crazy, and don't ever do any more things for
311
        // it.
312
        newDescriptor = Top;
313
314
        m_watchpointSet.fireAll("Inferred type changed");
315
    }
316
317
    // Remove the old InferredStructure object if we no longer need it.
318
    if (!newDescriptor.structure())
319
        m_structure = nullptr;
320
321
    // Add a new InferredStructure object if we need one now.
322
    if (newDescriptor.structure()) {
323
        if (m_structure) {
324
            // We should agree on the structures if we get here.
325
            ASSERT(newDescriptor.structure() == m_structure->structure());
326
        } else {
327
            m_structure = std::make_unique<InferredStructure>(this, newDescriptor.structure());
328
            newDescriptor.structure()->addTransitionWatchpoint(m_structure.get());
329
        }
330
    }
331
332
    // Finally, set the descriptor kind.
333
    m_kind = newDescriptor.kind();
334
335
    // Assert that we did things.
336
    ASSERT(descriptor(locker) == newDescriptor);
337
}
338
339
void InferredType::removeStructure()
340
{
341
    VM& vm = *Heap::heap(this)->vm();
342
343
    ConcurrentJITLocker locker(m_parent->m_lock);
344
    
345
    Descriptor newDescriptor = descriptor(locker);
346
    newDescriptor.removeStructure();
347
    
348
    set(locker, vm, newDescriptor);
349
}
350
351
void InferredType::InferredStructure::InferredStructure(InferredType* parent, Structure* structure)
352
    : m_parent(parent)
353
    , m_structure(vm, parent, structure)
354
{
355
}
356
357
void InferredType::InferredStructure::fireInternal(const FireDetail&)
358
{
359
    m_parent->removeStructure();
360
}
361
362
void InferredType::InferredStructure::finalizeUnconditionally()
363
{
364
    VM& vm = *Heap::heap(m_parent)->vm();
365
366
    ASSERT(Heap::isMarked(m_parent));
367
    
368
    if (!Heap::isMarked(m_structure.get()))
369
        m_parent->removeStructure();
370
}
371
372
} // namespace JSC
373
- Source/JavaScriptCore/runtime/InferredType.h +219 lines
Line 0 Source/JavaScriptCore/runtime/InferredType.h_sec1
1
/*
2
 * Copyright (C) 2015 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
#infdef InferredType_h
27
#define InferredType_h
28
29
#include "ConcurrentJITLock.h"
30
#include "JSCell.h"
31
32
namespace JSC {
33
34
// This is an object used for the inference of the types of object properties.
35
36
class InferredType : public JSCell {
37
public:
38
    typedef JSCell Base;
39
40
    static InferredType* create(VM&);
41
42
    static const bool needsDestruction = true;
43
    static void destroy(JSCell*);
44
45
    static Structure* createStructure(VM&, JSGlobalObject*, JSValue prototype);
46
47
    static void visitChildren(JSCell*, SlotVisitor&);
48
49
    DECLARE_INFO;
50
51
    enum Kind : uint8_t {
52
        Bottom,
53
        Boolean,
54
        Other,
55
        Int32,
56
        Double,
57
        Number,
58
        String,
59
        ObjectWithStructure,
60
        ObjectWithStructureOrOther,
61
        Object,
62
        ObjectOrOther,
63
        Top
64
    };
65
66
    class Descriptor {
67
    public:
68
        Descriptor()
69
            : m_kind(Bottom)
70
            , m_structure(nullptr)
71
        {
72
        }
73
74
        Descriptor(Kind kind, Structure* structure = nullptr)
75
            : m_kind(kind)
76
            , m_structure(structure)
77
        {
78
        }
79
80
        static Descriptor forValue(JSValue);
81
82
        Kind kind() const { return m_kind; }
83
        Structure* structure() const { return m_structure; }
84
85
        ALWAYS_INLINE bool includesValue(JSValue value)
86
        {
87
            switch (m_kind) {
88
            case Bottom:
89
                return false;
90
            case Boolean:
91
                return value.isBoolean();
92
            case Other:
93
                return value.isUndefinedOrNull();
94
            case Int32:
95
                return value.isInt32();
96
            case Double:
97
                return value.isDouble();
98
            case Number:
99
                return value.isNumber();
100
            case String:
101
                return value.isString();
102
            case ObjectWithStructure:
103
                return value.isCell() && value.asCell()->structure() == m_structure;
104
            case ObjectWithStructureOrOther:
105
                return value.isUndefinedOrNull()
106
                    || (value.isCell() && value.asCell()->structure() == m_structure);
107
            case Object:
108
                return value.isObject();
109
            case ObjectOrOther:
110
                return value.isUndefinedOrNull() || value.isObject();
111
            case Top:
112
                return true;
113
            }
114
115
            RELEASE_ASSERT_NOT_REACHED();
116
        }
117
118
        bool operator==(const Descriptor& other)
119
        {
120
            return m_kind == other.m_kind
121
                && m_structure == other.m_structure;
122
        }
123
124
        bool operator!=(const Descriptor& other)
125
        {
126
            return !(*this == other);
127
        }
128
    
129
        void merge(const Descriptor&);
130
        void removeStructure();
131
132
        // Returns true if this descriptor is more general than the other one.
133
        bool subsumes(const Descriptor&) const;
134
135
        void dump(PrintStream&) const;
136
137
    private:
138
        Kind m_kind;
139
        Structure* m_structure;
140
    };
141
142
    ConcurrentJITLock& lock() const { return m_lock; }
143
144
    Descriptor descriptor(const ConcurrentJITLocker&) const
145
    {
146
        return Descriptor(m_kind, m_structure ? m_structure->structure() : nullptr);
147
    }
148
    Descriptor descriptor() const
149
    {
150
        ConcurrentJITLocker locker(m_lock);
151
        return descriptor(locker);
152
    }
153
    
154
    Kind kind(const ConcurrentJITLocker& locker) const { return descriptor().kind(); }
155
    Structure* structure(const ConcurrentJITLocker& locker) const { return descriptor().structure(); }
156
157
    ALWAYS_INLINE void willStoreValue(VM& vm, JSValue value)
158
    {
159
        ConcurrentJITLocker locker(m_lock);
160
        if (descriptor(locker).includesValue(locker, value))
161
            return;
162
        willStoreValueSlow(locker, vm, value);
163
    }
164
165
    // Returns true if it currently makes sense to watch this InferredType for this descriptor. Note that
166
    // this will always return false for Top.
167
    bool canWatch(const ConcurrentJITLocker& locker, const Descriptor&);
168
    bool canWatch(const Descriptor&);
169
    
170
    void addWatchpoint(const ConcurrentJITLocker& locker, Watchpoint*);
171
    void addWatchpoint(Watchpoint*);
172
173
    void dump(PrintStream&) const;
174
175
private:
176
    InferredType(VM&);
177
    ~InferredType();
178
179
    void willStoreValueSlow(const ConcurrentJITLocker&, VM&, JSValue);
180
    void set(const ConcurrentJITLocker&, VM&, Descriptor);
181
    void removeStructure();
182
183
    mutable ConcurrentJITLock m_lock;
184
    
185
    Kind m_kind { Bottom };
186
187
    class InferredStructure : public Watchpoint, public UnconditionalFinalizer {
188
    public:
189
        InferredStructure(InferredType* parent, Structure*);
190
191
        Structure* structure() const { return m_structure.get(); };
192
193
    protected:
194
        void fireInternal(const FireDetail&) override;
195
        void finalizeUnconditionally() override;
196
197
    private:
198
        InferredType* m_parent;
199
        WriteBarrier<Structure> m_structure;
200
    };
201
202
    std::unique_ptr<InferredStructure> m_structure;
203
204
    // NOTE: If this is being watched, we transform to Top because that implies that it wouldn't be
205
    // profitable to watch it again. Also, this set is initialized clear, and is never exposed to the DFG
206
    // thread. The DFG will use the InferredType as the thing that it watches.
207
    InlineWatchpointSet m_watchpointSet;
208
};
209
210
} // namespace JSC
211
212
namespace WTF {
213
214
void printInternal(PrintStream&, JSC::InferredType::Kind);
215
216
} // namespace WTF
217
218
#endif // InferredType_h
219

Return to Bug 148610