| Differences between
and this patch
- Source/JavaScriptCore/ChangeLog +118 lines
Lines 1-3 Source/JavaScriptCore/ChangeLog_sec1
1
2014-02-23  Filip Pizlo  <fpizlo@apple.com>
2
3
        FTL should do polymorphic PutById inlining
4
        https://bugs.webkit.org/show_bug.cgi?id=129210
5
6
        Reviewed by NOBODY (OOPS!).
7
        
8
        This makes PutByIdStatus inform us about polymorphic cases by returning an array of
9
        PutByIdVariants. The DFG now has a node called MultiPutByOffset that indicates a
10
        selection of multiple inlined PutByIdVariants.
11
        
12
        MultiPutByOffset is almost identical to MultiGetByOffset, which we added in
13
        http://trac.webkit.org/changeset/164207.
14
        
15
        This also does some FTL refactoring to make MultiPutByOffset share code with some nodes
16
        that generate similar code.
17
        
18
        1% speed-up on V8v7 due to splay improving by 6.8%. Splay does the thing where it
19
        sometimes swaps field insertion order, creating fake polymorphism.
20
21
        * CMakeLists.txt:
22
        * GNUmakefile.list.am:
23
        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
24
        * JavaScriptCore.xcodeproj/project.pbxproj:
25
        * bytecode/PutByIdStatus.cpp:
26
        (JSC::PutByIdStatus::computeFromLLInt):
27
        (JSC::PutByIdStatus::computeFor):
28
        (JSC::PutByIdStatus::computeForStubInfo):
29
        (JSC::PutByIdStatus::dump):
30
        * bytecode/PutByIdStatus.h:
31
        (JSC::PutByIdStatus::PutByIdStatus):
32
        (JSC::PutByIdStatus::isSimple):
33
        (JSC::PutByIdStatus::numVariants):
34
        (JSC::PutByIdStatus::variants):
35
        (JSC::PutByIdStatus::at):
36
        (JSC::PutByIdStatus::operator[]):
37
        * bytecode/PutByIdVariant.cpp: Added.
38
        (JSC::PutByIdVariant::dump):
39
        (JSC::PutByIdVariant::dumpInContext):
40
        * bytecode/PutByIdVariant.h: Added.
41
        (JSC::PutByIdVariant::PutByIdVariant):
42
        (JSC::PutByIdVariant::replace):
43
        (JSC::PutByIdVariant::transition):
44
        (JSC::PutByIdVariant::kind):
45
        (JSC::PutByIdVariant::isSet):
46
        (JSC::PutByIdVariant::operator!):
47
        (JSC::PutByIdVariant::structure):
48
        (JSC::PutByIdVariant::oldStructure):
49
        (JSC::PutByIdVariant::newStructure):
50
        (JSC::PutByIdVariant::structureChain):
51
        (JSC::PutByIdVariant::offset):
52
        * dfg/DFGAbstractInterpreterInlines.h:
53
        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
54
        * dfg/DFGByteCodeParser.cpp:
55
        (JSC::DFG::ByteCodeParser::emitPrototypeChecks):
56
        (JSC::DFG::ByteCodeParser::handleGetById):
57
        (JSC::DFG::ByteCodeParser::emitPutById):
58
        (JSC::DFG::ByteCodeParser::handlePutById):
59
        (JSC::DFG::ByteCodeParser::parseBlock):
60
        * dfg/DFGCSEPhase.cpp:
61
        (JSC::DFG::CSEPhase::checkStructureElimination):
62
        (JSC::DFG::CSEPhase::structureTransitionWatchpointElimination):
63
        (JSC::DFG::CSEPhase::putStructureStoreElimination):
64
        (JSC::DFG::CSEPhase::getByOffsetLoadElimination):
65
        (JSC::DFG::CSEPhase::putByOffsetStoreElimination):
66
        * dfg/DFGClobberize.h:
67
        (JSC::DFG::clobberize):
68
        * dfg/DFGConstantFoldingPhase.cpp:
69
        (JSC::DFG::ConstantFoldingPhase::foldConstants):
70
        (JSC::DFG::ConstantFoldingPhase::emitPutByOffset):
71
        * dfg/DFGFixupPhase.cpp:
72
        (JSC::DFG::FixupPhase::fixupNode):
73
        * dfg/DFGGraph.cpp:
74
        (JSC::DFG::Graph::dump):
75
        * dfg/DFGGraph.h:
76
        * dfg/DFGNode.cpp:
77
        (JSC::DFG::MultiPutByOffsetData::writesStructures):
78
        (JSC::DFG::MultiPutByOffsetData::reallocatesStorage):
79
        * dfg/DFGNode.h:
80
        (JSC::DFG::Node::convertToPutByOffset):
81
        (JSC::DFG::Node::hasMultiPutByOffsetData):
82
        (JSC::DFG::Node::multiPutByOffsetData):
83
        * dfg/DFGNodeType.h:
84
        * dfg/DFGPredictionPropagationPhase.cpp:
85
        (JSC::DFG::PredictionPropagationPhase::propagate):
86
        * dfg/DFGSafeToExecute.h:
87
        (JSC::DFG::safeToExecute):
88
        * dfg/DFGSpeculativeJIT32_64.cpp:
89
        (JSC::DFG::SpeculativeJIT::compile):
90
        * dfg/DFGSpeculativeJIT64.cpp:
91
        (JSC::DFG::SpeculativeJIT::compile):
92
        * dfg/DFGTypeCheckHoistingPhase.cpp:
93
        (JSC::DFG::TypeCheckHoistingPhase::identifyRedundantStructureChecks):
94
        (JSC::DFG::TypeCheckHoistingPhase::identifyRedundantArrayChecks):
95
        * ftl/FTLCapabilities.cpp:
96
        (JSC::FTL::canCompile):
97
        * ftl/FTLLowerDFGToLLVM.cpp:
98
        (JSC::FTL::LowerDFGToLLVM::compileNode):
99
        (JSC::FTL::LowerDFGToLLVM::compilePutStructure):
100
        (JSC::FTL::LowerDFGToLLVM::compileAllocatePropertyStorage):
101
        (JSC::FTL::LowerDFGToLLVM::compileReallocatePropertyStorage):
102
        (JSC::FTL::LowerDFGToLLVM::compileGetByOffset):
103
        (JSC::FTL::LowerDFGToLLVM::compileMultiGetByOffset):
104
        (JSC::FTL::LowerDFGToLLVM::compilePutByOffset):
105
        (JSC::FTL::LowerDFGToLLVM::compileMultiPutByOffset):
106
        (JSC::FTL::LowerDFGToLLVM::loadProperty):
107
        (JSC::FTL::LowerDFGToLLVM::storeProperty):
108
        (JSC::FTL::LowerDFGToLLVM::addressOfProperty):
109
        (JSC::FTL::LowerDFGToLLVM::storageForTransition):
110
        (JSC::FTL::LowerDFGToLLVM::allocatePropertyStorage):
111
        (JSC::FTL::LowerDFGToLLVM::reallocatePropertyStorage):
112
        (JSC::FTL::LowerDFGToLLVM::emitStoreBarrier):
113
        * tests/stress/multi-put-by-offset-reallocation-cases.js: Added.
114
        (foos):
115
        (bar):
116
        (baz):
117
        (.o):
118
1
2014-02-23  Sam Weinig  <sam@webkit.org>
119
2014-02-23  Sam Weinig  <sam@webkit.org>
2
120
3
        Update FeatureDefines.xcconfig
121
        Update FeatureDefines.xcconfig
- Source/JavaScriptCore/CMakeLists.txt +1 lines
Lines 82-87 set(JavaScriptCore_SOURCES Source/JavaScriptCore/CMakeLists.txt_sec1
82
    bytecode/PreciseJumpTargets.cpp
82
    bytecode/PreciseJumpTargets.cpp
83
    bytecode/ProfiledCodeBlockJettisoningWatchpoint.cpp
83
    bytecode/ProfiledCodeBlockJettisoningWatchpoint.cpp
84
    bytecode/PutByIdStatus.cpp
84
    bytecode/PutByIdStatus.cpp
85
    bytecode/PutByIdVariant.cpp
85
    bytecode/ReduceWhitespace.cpp
86
    bytecode/ReduceWhitespace.cpp
86
    bytecode/SamplingTool.cpp
87
    bytecode/SamplingTool.cpp
87
    bytecode/SpecialPointer.cpp
88
    bytecode/SpecialPointer.cpp
- Source/JavaScriptCore/GNUmakefile.list.am +2 lines
Lines 182-187 javascriptcore_sources += \ Source/JavaScriptCore/GNUmakefile.list.am_sec1
182
	Source/JavaScriptCore/bytecode/SpeculatedType.h \
182
	Source/JavaScriptCore/bytecode/SpeculatedType.h \
183
	Source/JavaScriptCore/bytecode/PutByIdStatus.cpp \
183
	Source/JavaScriptCore/bytecode/PutByIdStatus.cpp \
184
	Source/JavaScriptCore/bytecode/PutByIdStatus.h \
184
	Source/JavaScriptCore/bytecode/PutByIdStatus.h \
185
	Source/JavaScriptCore/bytecode/PutByIdVariant.cpp \
186
	Source/JavaScriptCore/bytecode/PutByIdVariant.h \
185
	Source/JavaScriptCore/bytecode/PutKind.h \
187
	Source/JavaScriptCore/bytecode/PutKind.h \
186
	Source/JavaScriptCore/bytecode/ReduceWhitespace.cpp \
188
	Source/JavaScriptCore/bytecode/ReduceWhitespace.cpp \
187
	Source/JavaScriptCore/bytecode/ReduceWhitespace.h \
189
	Source/JavaScriptCore/bytecode/ReduceWhitespace.h \
- Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj +2 lines
Lines 337-342 Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj_sec1
337
    <ClCompile Include="..\bytecode\ProfiledCodeBlockJettisoningWatchpoint.cpp" />
337
    <ClCompile Include="..\bytecode\ProfiledCodeBlockJettisoningWatchpoint.cpp" />
338
    <ClCompile Include="..\bytecode\PreciseJumpTargets.cpp" />
338
    <ClCompile Include="..\bytecode\PreciseJumpTargets.cpp" />
339
    <ClCompile Include="..\bytecode\PutByIdStatus.cpp" />
339
    <ClCompile Include="..\bytecode\PutByIdStatus.cpp" />
340
    <ClCompile Include="..\bytecode\PutByIdVariant.cpp" />
340
    <ClCompile Include="..\bytecode\ReduceWhitespace.cpp" />
341
    <ClCompile Include="..\bytecode\ReduceWhitespace.cpp" />
341
    <ClCompile Include="..\bytecode\SamplingTool.cpp" />
342
    <ClCompile Include="..\bytecode\SamplingTool.cpp" />
342
    <ClCompile Include="..\bytecode\SpecialPointer.cpp" />
343
    <ClCompile Include="..\bytecode\SpecialPointer.cpp" />
Lines 858-863 Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj_sec2
858
    <ClInclude Include="..\bytecode\ProfiledCodeBlockJettisoningWatchpoint.h" />
859
    <ClInclude Include="..\bytecode\ProfiledCodeBlockJettisoningWatchpoint.h" />
859
    <ClInclude Include="..\bytecode\PreciseJumpTargets.h" />
860
    <ClInclude Include="..\bytecode\PreciseJumpTargets.h" />
860
    <ClInclude Include="..\bytecode\PutByIdStatus.h" />
861
    <ClInclude Include="..\bytecode\PutByIdStatus.h" />
862
    <ClInclude Include="..\bytecode\PutByIdVariant.h" />
861
    <ClInclude Include="..\bytecode\PutKind.h" />
863
    <ClInclude Include="..\bytecode\PutKind.h" />
862
    <ClInclude Include="..\bytecode\ReduceWhitespace.h" />
864
    <ClInclude Include="..\bytecode\ReduceWhitespace.h" />
863
    <ClInclude Include="..\bytecode\SamplingTool.h" />
865
    <ClInclude Include="..\bytecode\SamplingTool.h" />
- Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj +8 lines
Lines 357-362 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec1
357
		0F9332A314CA7DD70085F3C6 /* PutByIdStatus.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F93329914CA7DC10085F3C6 /* PutByIdStatus.cpp */; };
357
		0F9332A314CA7DD70085F3C6 /* PutByIdStatus.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F93329914CA7DC10085F3C6 /* PutByIdStatus.cpp */; };
358
		0F9332A414CA7DD90085F3C6 /* PutByIdStatus.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F93329A14CA7DC10085F3C6 /* PutByIdStatus.h */; settings = {ATTRIBUTES = (Private, ); }; };
358
		0F9332A414CA7DD90085F3C6 /* PutByIdStatus.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F93329A14CA7DC10085F3C6 /* PutByIdStatus.h */; settings = {ATTRIBUTES = (Private, ); }; };
359
		0F9332A514CA7DDD0085F3C6 /* StructureSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F93329B14CA7DC10085F3C6 /* StructureSet.h */; settings = {ATTRIBUTES = (Private, ); }; };
359
		0F9332A514CA7DDD0085F3C6 /* StructureSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F93329B14CA7DC10085F3C6 /* StructureSet.h */; settings = {ATTRIBUTES = (Private, ); }; };
360
		0F93B4A918B92C4D00178A3F /* PutByIdVariant.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F93B4A718B92C4D00178A3F /* PutByIdVariant.cpp */; };
361
		0F93B4AA18B92C4D00178A3F /* PutByIdVariant.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F93B4A818B92C4D00178A3F /* PutByIdVariant.h */; settings = {ATTRIBUTES = (Private, ); }; };
360
		0F963B3813FC6FE90002D9B2 /* ValueProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F963B3613FC6FDE0002D9B2 /* ValueProfile.h */; settings = {ATTRIBUTES = (Private, ); }; };
362
		0F963B3813FC6FE90002D9B2 /* ValueProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F963B3613FC6FDE0002D9B2 /* ValueProfile.h */; settings = {ATTRIBUTES = (Private, ); }; };
361
		0F96EBB316676EF6008BADE3 /* CodeBlockWithJITType.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F96EBB116676EF4008BADE3 /* CodeBlockWithJITType.h */; settings = {ATTRIBUTES = (Private, ); }; };
363
		0F96EBB316676EF6008BADE3 /* CodeBlockWithJITType.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F96EBB116676EF4008BADE3 /* CodeBlockWithJITType.h */; settings = {ATTRIBUTES = (Private, ); }; };
362
		0F9749711687ADE400A4FF6A /* JSCellInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F97496F1687ADE200A4FF6A /* JSCellInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
364
		0F9749711687ADE400A4FF6A /* JSCellInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F97496F1687ADE200A4FF6A /* JSCellInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
Lines 1832-1837 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec2
1832
		0F93329914CA7DC10085F3C6 /* PutByIdStatus.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PutByIdStatus.cpp; sourceTree = "<group>"; };
1834
		0F93329914CA7DC10085F3C6 /* PutByIdStatus.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PutByIdStatus.cpp; sourceTree = "<group>"; };
1833
		0F93329A14CA7DC10085F3C6 /* PutByIdStatus.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PutByIdStatus.h; sourceTree = "<group>"; };
1835
		0F93329A14CA7DC10085F3C6 /* PutByIdStatus.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PutByIdStatus.h; sourceTree = "<group>"; };
1834
		0F93329B14CA7DC10085F3C6 /* StructureSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StructureSet.h; sourceTree = "<group>"; };
1836
		0F93329B14CA7DC10085F3C6 /* StructureSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StructureSet.h; sourceTree = "<group>"; };
1837
		0F93B4A718B92C4D00178A3F /* PutByIdVariant.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PutByIdVariant.cpp; sourceTree = "<group>"; };
1838
		0F93B4A818B92C4D00178A3F /* PutByIdVariant.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PutByIdVariant.h; sourceTree = "<group>"; };
1835
		0F963B3613FC6FDE0002D9B2 /* ValueProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ValueProfile.h; sourceTree = "<group>"; };
1839
		0F963B3613FC6FDE0002D9B2 /* ValueProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ValueProfile.h; sourceTree = "<group>"; };
1836
		0F96EBB116676EF4008BADE3 /* CodeBlockWithJITType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeBlockWithJITType.h; sourceTree = "<group>"; };
1840
		0F96EBB116676EF4008BADE3 /* CodeBlockWithJITType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeBlockWithJITType.h; sourceTree = "<group>"; };
1837
		0F97496F1687ADE200A4FF6A /* JSCellInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSCellInlines.h; sourceTree = "<group>"; };
1841
		0F97496F1687ADE200A4FF6A /* JSCellInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSCellInlines.h; sourceTree = "<group>"; };
Lines 4585-4590 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec3
4585
				0FC97F32182020D7002C9B26 /* ProfiledCodeBlockJettisoningWatchpoint.h */,
4589
				0FC97F32182020D7002C9B26 /* ProfiledCodeBlockJettisoningWatchpoint.h */,
4586
				0F93329914CA7DC10085F3C6 /* PutByIdStatus.cpp */,
4590
				0F93329914CA7DC10085F3C6 /* PutByIdStatus.cpp */,
4587
				0F93329A14CA7DC10085F3C6 /* PutByIdStatus.h */,
4591
				0F93329A14CA7DC10085F3C6 /* PutByIdStatus.h */,
4592
				0F93B4A718B92C4D00178A3F /* PutByIdVariant.cpp */,
4593
				0F93B4A818B92C4D00178A3F /* PutByIdVariant.h */,
4588
				0F9FC8C114E1B5FB00D52AE0 /* PutKind.h */,
4594
				0F9FC8C114E1B5FB00D52AE0 /* PutKind.h */,
4589
				0FF60ABF16740F8100029779 /* ReduceWhitespace.cpp */,
4595
				0FF60ABF16740F8100029779 /* ReduceWhitespace.cpp */,
4590
				0FF60AC016740F8100029779 /* ReduceWhitespace.h */,
4596
				0FF60AC016740F8100029779 /* ReduceWhitespace.h */,
Lines 5387-5392 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec4
5387
				860161E40F3A83C100F84710 /* MacroAssemblerX86.h in Headers */,
5393
				860161E40F3A83C100F84710 /* MacroAssemblerX86.h in Headers */,
5388
				860161E50F3A83C100F84710 /* MacroAssemblerX86_64.h in Headers */,
5394
				860161E50F3A83C100F84710 /* MacroAssemblerX86_64.h in Headers */,
5389
				860161E60F3A83C100F84710 /* MacroAssemblerX86Common.h in Headers */,
5395
				860161E60F3A83C100F84710 /* MacroAssemblerX86Common.h in Headers */,
5396
				0F93B4AA18B92C4D00178A3F /* PutByIdVariant.h in Headers */,
5390
				A700873A17CBE85300C3E643 /* MapConstructor.h in Headers */,
5397
				A700873A17CBE85300C3E643 /* MapConstructor.h in Headers */,
5391
				A78507D717CBC6FD0011F6E7 /* MapData.h in Headers */,
5398
				A78507D717CBC6FD0011F6E7 /* MapData.h in Headers */,
5392
				A74DEF92182D991400522C22 /* MapIteratorConstructor.h in Headers */,
5399
				A74DEF92182D991400522C22 /* MapIteratorConstructor.h in Headers */,
Lines 6174-6179 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec5
6174
				0FC20CB51852E2C600C9E954 /* DFGStrengthReductionPhase.cpp in Sources */,
6181
				0FC20CB51852E2C600C9E954 /* DFGStrengthReductionPhase.cpp in Sources */,
6175
				0F2FCCFE18A60070001A27F8 /* DFGThreadData.cpp in Sources */,
6182
				0F2FCCFE18A60070001A27F8 /* DFGThreadData.cpp in Sources */,
6176
				0FC097A1146B28CA00CF2442 /* DFGThunks.cpp in Sources */,
6183
				0FC097A1146B28CA00CF2442 /* DFGThunks.cpp in Sources */,
6184
				0F93B4A918B92C4D00178A3F /* PutByIdVariant.cpp in Sources */,
6177
				0FD8A32717D51F5700CA2C40 /* DFGTierUpCheckInjectionPhase.cpp in Sources */,
6185
				0FD8A32717D51F5700CA2C40 /* DFGTierUpCheckInjectionPhase.cpp in Sources */,
6178
				0FD8A32917D51F5700CA2C40 /* DFGToFTLDeferredCompilationCallback.cpp in Sources */,
6186
				0FD8A32917D51F5700CA2C40 /* DFGToFTLDeferredCompilationCallback.cpp in Sources */,
6179
				0FD8A32B17D51F5700CA2C40 /* DFGToFTLForOSREntryDeferredCompilationCallback.cpp in Sources */,
6187
				0FD8A32B17D51F5700CA2C40 /* DFGToFTLForOSREntryDeferredCompilationCallback.cpp in Sources */,
- Source/JavaScriptCore/bytecode/PutByIdStatus.cpp -25 / +80 lines
Lines 30-37 Source/JavaScriptCore/bytecode/PutByIdStatus.cpp_sec1
30
#include "LLIntData.h"
30
#include "LLIntData.h"
31
#include "LowLevelInterpreter.h"
31
#include "LowLevelInterpreter.h"
32
#include "JSCInlines.h"
32
#include "JSCInlines.h"
33
#include "PolymorphicPutByIdList.h"
33
#include "Structure.h"
34
#include "Structure.h"
34
#include "StructureChain.h"
35
#include "StructureChain.h"
36
#include <wtf/ListDump.h>
35
37
36
namespace JSC {
38
namespace JSC {
37
39
Lines 56-70 PutByIdStatus PutByIdStatus::computeFrom Source/JavaScriptCore/bytecode/PutByIdStatus.cpp_sec2
56
58
57
    Structure* structure = instruction[4].u.structure.get();
59
    Structure* structure = instruction[4].u.structure.get();
58
    if (!structure)
60
    if (!structure)
59
        return PutByIdStatus(NoInformation, 0, 0, 0, invalidOffset);
61
        return PutByIdStatus(NoInformation);
60
    
62
    
61
    if (instruction[0].u.opcode == LLInt::getOpcode(llint_op_put_by_id)
63
    if (instruction[0].u.opcode == LLInt::getOpcode(llint_op_put_by_id)
62
        || instruction[0].u.opcode == LLInt::getOpcode(llint_op_put_by_id_out_of_line)) {
64
        || instruction[0].u.opcode == LLInt::getOpcode(llint_op_put_by_id_out_of_line)) {
63
        PropertyOffset offset = structure->getConcurrently(*profiledBlock->vm(), uid);
65
        PropertyOffset offset = structure->getConcurrently(*profiledBlock->vm(), uid);
64
        if (!isValidOffset(offset))
66
        if (!isValidOffset(offset))
65
            return PutByIdStatus(NoInformation, 0, 0, 0, invalidOffset);
67
            return PutByIdStatus(NoInformation);
66
        
68
        
67
        return PutByIdStatus(SimpleReplace, structure, 0, 0, offset);
69
        return PutByIdVariant::replace(structure, offset);
68
    }
70
    }
69
    
71
    
70
    ASSERT(structure->transitionWatchpointSetHasBeenInvalidated());
72
    ASSERT(structure->transitionWatchpointSetHasBeenInvalidated());
Lines 81-94 PutByIdStatus PutByIdStatus::computeFrom Source/JavaScriptCore/bytecode/PutByIdStatus.cpp_sec3
81
    
83
    
82
    PropertyOffset offset = newStructure->getConcurrently(*profiledBlock->vm(), uid);
84
    PropertyOffset offset = newStructure->getConcurrently(*profiledBlock->vm(), uid);
83
    if (!isValidOffset(offset))
85
    if (!isValidOffset(offset))
84
        return PutByIdStatus(NoInformation, 0, 0, 0, invalidOffset);
86
        return PutByIdStatus(NoInformation);
85
    
87
    
86
    return PutByIdStatus(
88
    return PutByIdVariant::transition(
87
        SimpleTransition, structure, newStructure,
89
        structure, newStructure,
88
        chain ? adoptRef(new IntendedStructureChain(profiledBlock, structure, chain)) : 0,
90
        chain ? adoptRef(new IntendedStructureChain(profiledBlock, structure, chain)) : 0,
89
        offset);
91
        offset);
90
#else
92
#else
91
    return PutByIdStatus(NoInformation, 0, 0, 0, invalidOffset);
93
    return PutByIdStatus(NoInformation);
92
#endif
94
#endif
93
}
95
}
94
96
Lines 102-108 PutByIdStatus PutByIdStatus::computeFor( Source/JavaScriptCore/bytecode/PutByIdStatus.cpp_sec4
102
#if ENABLE(DFG_JIT)
104
#if ENABLE(DFG_JIT)
103
    if (profiledBlock->likelyToTakeSlowCase(bytecodeIndex)
105
    if (profiledBlock->likelyToTakeSlowCase(bytecodeIndex)
104
        || hasExitSite(locker, profiledBlock, bytecodeIndex))
106
        || hasExitSite(locker, profiledBlock, bytecodeIndex))
105
        return PutByIdStatus(TakesSlowPath, 0, 0, 0, invalidOffset);
107
        return PutByIdStatus(TakesSlowPath);
106
    
108
    
107
    StructureStubInfo* stubInfo = map.get(CodeOrigin(bytecodeIndex));
109
    StructureStubInfo* stubInfo = map.get(CodeOrigin(bytecodeIndex));
108
    PutByIdStatus result = computeForStubInfo(locker, profiledBlock, stubInfo, uid);
110
    PutByIdStatus result = computeForStubInfo(locker, profiledBlock, stubInfo, uid);
Lines 112-118 PutByIdStatus PutByIdStatus::computeFor( Source/JavaScriptCore/bytecode/PutByIdStatus.cpp_sec5
112
    return result;
114
    return result;
113
#else // ENABLE(JIT)
115
#else // ENABLE(JIT)
114
    UNUSED_PARAM(map);
116
    UNUSED_PARAM(map);
115
    return PutByIdStatus(NoInformation, 0, 0, 0, invalidOffset);
117
    return PutByIdStatus(NoInformation);
116
#endif // ENABLE(JIT)
118
#endif // ENABLE(JIT)
117
}
119
}
118
120
Lines 123-147 PutByIdStatus PutByIdStatus::computeForS Source/JavaScriptCore/bytecode/PutByIdStatus.cpp_sec6
123
        return PutByIdStatus();
125
        return PutByIdStatus();
124
    
126
    
125
    if (stubInfo->resetByGC)
127
    if (stubInfo->resetByGC)
126
        return PutByIdStatus(TakesSlowPath, 0, 0, 0, invalidOffset);
128
        return PutByIdStatus(TakesSlowPath);
127
129
128
    switch (stubInfo->accessType) {
130
    switch (stubInfo->accessType) {
129
    case access_unset:
131
    case access_unset:
130
        // If the JIT saw it but didn't optimize it, then assume that this takes slow path.
132
        // If the JIT saw it but didn't optimize it, then assume that this takes slow path.
131
        return PutByIdStatus(TakesSlowPath, 0, 0, 0, invalidOffset);
133
        return PutByIdStatus(TakesSlowPath);
132
        
134
        
133
    case access_put_by_id_replace: {
135
    case access_put_by_id_replace: {
134
        PropertyOffset offset =
136
        PropertyOffset offset =
135
            stubInfo->u.putByIdReplace.baseObjectStructure->getConcurrently(
137
            stubInfo->u.putByIdReplace.baseObjectStructure->getConcurrently(
136
                *profiledBlock->vm(), uid);
138
                *profiledBlock->vm(), uid);
137
        if (isValidOffset(offset)) {
139
        if (isValidOffset(offset)) {
138
            return PutByIdStatus(
140
            return PutByIdVariant::replace(
139
                SimpleReplace,
141
                stubInfo->u.putByIdReplace.baseObjectStructure.get(), offset);
140
                stubInfo->u.putByIdReplace.baseObjectStructure.get(),
141
                0, 0,
142
                offset);
143
        }
142
        }
144
        return PutByIdStatus(TakesSlowPath, 0, 0, 0, invalidOffset);
143
        return PutByIdStatus(TakesSlowPath);
145
    }
144
    }
146
        
145
        
147
    case access_put_by_id_transition_normal:
146
    case access_put_by_id_transition_normal:
Lines 151-158 PutByIdStatus PutByIdStatus::computeForS Source/JavaScriptCore/bytecode/PutByIdStatus.cpp_sec7
151
            stubInfo->u.putByIdTransition.structure->getConcurrently(
150
            stubInfo->u.putByIdTransition.structure->getConcurrently(
152
                *profiledBlock->vm(), uid);
151
                *profiledBlock->vm(), uid);
153
        if (isValidOffset(offset)) {
152
        if (isValidOffset(offset)) {
154
            return PutByIdStatus(
153
            return PutByIdVariant::transition(
155
                SimpleTransition,
156
                stubInfo->u.putByIdTransition.previousStructure.get(),
154
                stubInfo->u.putByIdTransition.previousStructure.get(),
157
                stubInfo->u.putByIdTransition.structure.get(),
155
                stubInfo->u.putByIdTransition.structure.get(),
158
                stubInfo->u.putByIdTransition.chain ? adoptRef(new IntendedStructureChain(
156
                stubInfo->u.putByIdTransition.chain ? adoptRef(new IntendedStructureChain(
Lines 160-172 PutByIdStatus PutByIdStatus::computeForS Source/JavaScriptCore/bytecode/PutByIdStatus.cpp_sec8
160
                    stubInfo->u.putByIdTransition.chain.get())) : 0,
158
                    stubInfo->u.putByIdTransition.chain.get())) : 0,
161
                offset);
159
                offset);
162
        }
160
        }
163
        return PutByIdStatus(TakesSlowPath, 0, 0, 0, invalidOffset);
161
        return PutByIdStatus(TakesSlowPath);
162
    }
163
        
164
    case access_put_by_id_list: {
165
        PolymorphicPutByIdList* list = stubInfo->u.putByIdList.list;
166
        
167
        PutByIdStatus result;
168
        result.m_state = Simple;
169
        
170
        for (unsigned i = 0; i < list->size(); ++i) {
171
            const PutByIdAccess& access = list->at(i);
172
            
173
            switch (access.type()) {
174
            case PutByIdAccess::Replace: {
175
                Structure* structure = access.structure();
176
                PropertyOffset offset = structure->getConcurrently(*profiledBlock->vm(), uid);
177
                if (!isValidOffset(offset))
178
                    return PutByIdStatus(TakesSlowPath);
179
                result.m_variants.append(PutByIdVariant::replace(structure, offset));
180
                break;
181
            }
182
                
183
            case PutByIdAccess::Transition: {
184
                PropertyOffset offset =
185
                    access.newStructure()->getConcurrently(*profiledBlock->vm(), uid);
186
                if (!isValidOffset(offset))
187
                    return PutByIdStatus(TakesSlowPath);
188
                result.m_variants.append(PutByIdVariant::transition(
189
                    access.oldStructure(), access.newStructure(),
190
                    access.chain() ? adoptRef(new IntendedStructureChain(
191
                        profiledBlock, access.oldStructure(), access.chain())) : 0,
192
                    offset));
193
                break;
194
            }
195
196
            default:
197
                return PutByIdStatus(TakesSlowPath);
198
            }
199
        }
200
        
201
        return result;
164
    }
202
    }
165
        
203
        
166
    default:
204
    default:
167
        // FIXME: We should handle polymorphic PutById. We probably have some interesting things
205
        return PutByIdStatus(TakesSlowPath);
168
        // we could do about it.
169
        return PutByIdStatus(TakesSlowPath, 0, 0, 0, invalidOffset);
170
    }
206
    }
171
}
207
}
172
#endif
208
#endif
Lines 223-229 PutByIdStatus PutByIdStatus::computeFor( Source/JavaScriptCore/bytecode/PutByIdStatus.cpp_sec9
223
            // the specialized slot.
259
            // the specialized slot.
224
            return PutByIdStatus(TakesSlowPath);
260
            return PutByIdStatus(TakesSlowPath);
225
        }
261
        }
226
        return PutByIdStatus(SimpleReplace, structure, 0, 0, offset);
262
        return PutByIdVariant::replace(structure, offset);
227
    }
263
    }
228
    
264
    
229
    // Our hypothesis is that we're doing a transition. Before we prove that this is really
265
    // Our hypothesis is that we're doing a transition. Before we prove that this is really
Lines 276-282 PutByIdStatus PutByIdStatus::computeFor( Source/JavaScriptCore/bytecode/PutByIdStatus.cpp_sec10
276
    ASSERT(!transition->transitionDidInvolveSpecificValue());
312
    ASSERT(!transition->transitionDidInvolveSpecificValue());
277
    ASSERT(isValidOffset(offset));
313
    ASSERT(isValidOffset(offset));
278
    
314
    
279
    return PutByIdStatus(SimpleTransition, structure, transition, chain.release(), offset);
315
    return PutByIdVariant::transition(structure, transition, chain.release(), offset);
316
}
317
318
void PutByIdStatus::dump(PrintStream& out) const
319
{
320
    switch (m_state) {
321
    case NoInformation:
322
        out.print("(NoInformation)");
323
        return;
324
        
325
    case Simple:
326
        out.print("(", listDump(m_variants), ")");
327
        return;
328
        
329
    case TakesSlowPath:
330
        out.print("(TakesSlowPath)");
331
        return;
332
    }
333
    
334
    RELEASE_ASSERT_NOT_REACHED();
280
}
335
}
281
336
282
} // namespace JSC
337
} // namespace JSC
- Source/JavaScriptCore/bytecode/PutByIdStatus.h -42 / +15 lines
Lines 1-5 Source/JavaScriptCore/bytecode/PutByIdStatus.h_sec1
1
/*
1
/*
2
 * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
2
 * Copyright (C) 2012, 2013, 2014 Apple Inc. All rights reserved.
3
 *
3
 *
4
 * Redistribution and use in source and binary forms, with or without
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
5
 * modification, are permitted provided that the following conditions
Lines 27-34 Source/JavaScriptCore/bytecode/PutByIdStatus.h_sec2
27
#define PutByIdStatus_h
27
#define PutByIdStatus_h
28
28
29
#include "ExitingJITType.h"
29
#include "ExitingJITType.h"
30
#include "IntendedStructureChain.h"
30
#include "PutByIdVariant.h"
31
#include "PropertyOffset.h"
32
#include "StructureStubInfo.h"
31
#include "StructureStubInfo.h"
33
#include <wtf/text/StringImpl.h>
32
#include <wtf/text/StringImpl.h>
34
33
Lines 45-95 public: Source/JavaScriptCore/bytecode/PutByIdStatus.h_sec3
45
    enum State {
44
    enum State {
46
        // It's uncached so we have no information.
45
        // It's uncached so we have no information.
47
        NoInformation,
46
        NoInformation,
48
        // It's cached as a direct store into an object property for cases where the object
47
        // It's cached as a simple store of some kind.
49
        // already has the property.
48
        Simple,
50
        SimpleReplace,
51
        // It's cached as a transition from one structure that lacks the property to one that
52
        // includes the property, and a direct store to this new property.
53
        SimpleTransition,
54
        // It's known to often take slow path.
49
        // It's known to often take slow path.
55
        TakesSlowPath
50
        TakesSlowPath
56
    };
51
    };
57
    
52
    
58
    PutByIdStatus()
53
    PutByIdStatus()
59
        : m_state(NoInformation)
54
        : m_state(NoInformation)
60
        , m_oldStructure(0)
61
        , m_newStructure(0)
62
        , m_structureChain(0)
63
        , m_offset(invalidOffset)
64
    {
55
    {
65
    }
56
    }
66
    
57
    
67
    explicit PutByIdStatus(State state)
58
    explicit PutByIdStatus(State state)
68
        : m_state(state)
59
        : m_state(state)
69
        , m_oldStructure(0)
70
        , m_newStructure(0)
71
        , m_structureChain(0)
72
        , m_offset(invalidOffset)
73
    {
60
    {
74
        ASSERT(m_state == NoInformation || m_state == TakesSlowPath);
61
        ASSERT(m_state == NoInformation || m_state == TakesSlowPath);
75
    }
62
    }
76
    
63
    
77
    PutByIdStatus(
64
    PutByIdStatus(const PutByIdVariant& variant)
78
        State state,
65
        : m_state(Simple)
79
        Structure* oldStructure,
80
        Structure* newStructure,
81
        PassRefPtr<IntendedStructureChain> structureChain,
82
        PropertyOffset offset)
83
        : m_state(state)
84
        , m_oldStructure(oldStructure)
85
        , m_newStructure(newStructure)
86
        , m_structureChain(structureChain)
87
        , m_offset(offset)
88
    {
66
    {
89
        ASSERT((m_state == NoInformation || m_state == TakesSlowPath) == !m_oldStructure);
67
        m_variants.append(variant);
90
        ASSERT((m_state != SimpleTransition) == !m_newStructure);
91
        ASSERT(!((m_state != SimpleTransition) && m_structureChain));
92
        ASSERT((m_state == NoInformation || m_state == TakesSlowPath) == (m_offset == invalidOffset));
93
    }
68
    }
94
    
69
    
95
    static PutByIdStatus computeFor(CodeBlock*, StubInfoMap&, unsigned bytecodeIndex, StringImpl* uid);
70
    static PutByIdStatus computeFor(CodeBlock*, StubInfoMap&, unsigned bytecodeIndex, StringImpl* uid);
Lines 101-114 public: Source/JavaScriptCore/bytecode/PutByIdStatus.h_sec4
101
    
76
    
102
    bool isSet() const { return m_state != NoInformation; }
77
    bool isSet() const { return m_state != NoInformation; }
103
    bool operator!() const { return m_state == NoInformation; }
78
    bool operator!() const { return m_state == NoInformation; }
104
    bool isSimpleReplace() const { return m_state == SimpleReplace; }
79
    bool isSimple() const { return m_state == Simple; }
105
    bool isSimpleTransition() const { return m_state == SimpleTransition; }
106
    bool takesSlowPath() const { return m_state == TakesSlowPath; }
80
    bool takesSlowPath() const { return m_state == TakesSlowPath; }
107
    
81
    
108
    Structure* oldStructure() const { return m_oldStructure; }
82
    size_t numVariants() const { return m_variants.size(); }
109
    Structure* newStructure() const { return m_newStructure; }
83
    const Vector<PutByIdVariant, 1>& variants() const { return m_variants; }
110
    IntendedStructureChain* structureChain() const { return m_structureChain.get(); }
84
    const PutByIdVariant& at(size_t index) const { return m_variants[index]; }
111
    PropertyOffset offset() const { return m_offset; }
85
    const PutByIdVariant& operator[](size_t index) const { return at(index); }
86
    
87
    void dump(PrintStream&) const;
112
    
88
    
113
private:
89
private:
114
#if ENABLE(DFG_JIT)
90
#if ENABLE(DFG_JIT)
Lines 120-129 private: Source/JavaScriptCore/bytecode/PutByIdStatus.h_sec5
120
    static PutByIdStatus computeFromLLInt(CodeBlock*, unsigned bytecodeIndex, StringImpl* uid);
96
    static PutByIdStatus computeFromLLInt(CodeBlock*, unsigned bytecodeIndex, StringImpl* uid);
121
    
97
    
122
    State m_state;
98
    State m_state;
123
    Structure* m_oldStructure;
99
    Vector<PutByIdVariant, 1> m_variants;
124
    Structure* m_newStructure;
125
    RefPtr<IntendedStructureChain> m_structureChain;
126
    PropertyOffset m_offset;
127
};
100
};
128
101
129
} // namespace JSC
102
} // namespace JSC
- Source/JavaScriptCore/bytecode/PutByIdVariant.cpp +60 lines
Line 0 Source/JavaScriptCore/bytecode/PutByIdVariant.cpp_sec1
1
/*
2
 * Copyright (C) 2014 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 "PutByIdVariant.h"
28
29
namespace JSC {
30
31
void PutByIdVariant::dump(PrintStream& out) const
32
{
33
    dumpInContext(out, 0);
34
}
35
36
void PutByIdVariant::dumpInContext(PrintStream& out, DumpContext* context) const
37
{
38
    switch (kind()) {
39
    case NotSet:
40
        out.print("<empty>");
41
        return;
42
        
43
    case Replace:
44
        out.print(
45
            "<Replace: ", pointerDumpInContext(structure(), context), ", ", offset(), ">");
46
        return;
47
        
48
    case Transition:
49
        out.print(
50
            "<Transition: ", pointerDumpInContext(oldStructure(), context), " -> ",
51
            pointerDumpInContext(newStructure(), context), ", ",
52
            pointerDumpInContext(structureChain(), context), ", ", offset(), ">");
53
        return;
54
    }
55
    
56
    RELEASE_ASSERT_NOT_REACHED();
57
}
58
59
} // namespace JSC
60
- Source/JavaScriptCore/bytecode/PutByIdVariant.h +121 lines
Line 0 Source/JavaScriptCore/bytecode/PutByIdVariant.h_sec1
1
/*
2
 * Copyright (C) 2014 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 PutByIdVariant_h
27
#define PutByIdVariant_h
28
29
#include "IntendedStructureChain.h"
30
#include "PropertyOffset.h"
31
32
namespace JSC {
33
34
class PutByIdVariant {
35
public:
36
    enum Kind {
37
        NotSet,
38
        Replace,
39
        Transition
40
    };
41
    
42
    PutByIdVariant()
43
        : m_kind(NotSet)
44
        , m_oldStructure(0)
45
        , m_newStructure(0)
46
        , m_offset(invalidOffset)
47
    {
48
    }
49
    
50
    static PutByIdVariant replace(Structure* structure, PropertyOffset offset)
51
    {
52
        PutByIdVariant result;
53
        result.m_kind = Replace;
54
        result.m_oldStructure = structure;
55
        result.m_offset = offset;
56
        return result;
57
    }
58
    
59
    static PutByIdVariant transition(
60
        Structure* oldStructure, Structure* newStructure,
61
        PassRefPtr<IntendedStructureChain> structureChain, PropertyOffset offset)
62
    {
63
        PutByIdVariant result;
64
        result.m_kind = Transition;
65
        result.m_oldStructure = oldStructure;
66
        result.m_newStructure = newStructure;
67
        result.m_structureChain = structureChain;
68
        result.m_offset = offset;
69
        return result;
70
    }
71
    
72
    Kind kind() const { return m_kind; }
73
    
74
    bool isSet() const { return kind() != NotSet; }
75
    bool operator!() const { return !isSet(); }
76
    
77
    Structure* structure() const
78
    {
79
        ASSERT(kind() == Replace);
80
        return m_oldStructure;
81
    }
82
    
83
    Structure* oldStructure() const
84
    {
85
        ASSERT(kind() == Transition || kind() == Replace);
86
        return m_oldStructure;
87
    }
88
    
89
    Structure* newStructure() const
90
    {
91
        ASSERT(kind() == Transition);
92
        return m_newStructure;
93
    }
94
    
95
    IntendedStructureChain* structureChain() const
96
    {
97
        ASSERT(kind() == Transition);
98
        return m_structureChain.get();
99
    }
100
    
101
    PropertyOffset offset() const
102
    {
103
        ASSERT(isSet());
104
        return m_offset;
105
    }
106
    
107
    void dump(PrintStream&) const;
108
    void dumpInContext(PrintStream&, DumpContext*) const;
109
110
private:
111
    Kind m_kind;
112
    Structure* m_oldStructure;
113
    Structure* m_newStructure;
114
    RefPtr<IntendedStructureChain> m_structureChain;
115
    PropertyOffset m_offset;
116
};
117
118
} // namespace JSC
119
120
#endif // PutByIdVariant_h
121
- Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h -14 / +69 lines
Lines 1640-1646 bool AbstractInterpreter<AbstractStateTy Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h_sec1
1640
        for (unsigned i = node->multiGetByOffsetData().variants.size(); i--;)
1640
        for (unsigned i = node->multiGetByOffsetData().variants.size(); i--;)
1641
            set.addAll(node->multiGetByOffsetData().variants[i].structureSet());
1641
            set.addAll(node->multiGetByOffsetData().variants[i].structureSet());
1642
        
1642
        
1643
        filter(value, set);
1643
        filter(node->child1(), set);
1644
        forNode(node).makeHeapTop();
1644
        forNode(node).makeHeapTop();
1645
        break;
1645
        break;
1646
    }
1646
    }
Lines 1648-1654 bool AbstractInterpreter<AbstractStateTy Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h_sec2
1648
    case PutByOffset: {
1648
    case PutByOffset: {
1649
        break;
1649
        break;
1650
    }
1650
    }
1651
            
1651
        
1652
    case MultiPutByOffset: {
1653
        AbstractValue& value = forNode(node->child1());
1654
        ASSERT(!(value.m_type & ~SpecCell)); // Edge filtering should have already ensured this.
1655
1656
        if (Structure* structure = value.bestProvenStructure()) {
1657
            bool done = false;
1658
            for (unsigned i = node->multiPutByOffsetData().variants.size(); i--;) {
1659
                const PutByIdVariant& variant = node->multiPutByOffsetData().variants[i];
1660
                if (variant.oldStructure() != structure)
1661
                    continue;
1662
                
1663
                if (variant.kind() == PutByIdVariant::Replace) {
1664
                    filter(node->child1(), structure);
1665
                    m_state.setFoundConstants(true);
1666
                    m_state.setHaveStructures(true);
1667
                    done = true;
1668
                    break;
1669
                }
1670
                
1671
                ASSERT(variant.kind() == PutByIdVariant::Transition);
1672
                clobberStructures(clobberLimit);
1673
                forNode(node->child1()).set(m_graph, variant.newStructure());
1674
                m_state.setFoundConstants(true);
1675
                m_state.setHaveStructures(true);
1676
                done = true;
1677
                break;
1678
            }
1679
            if (done)
1680
                break;
1681
        }
1682
        
1683
        clobberStructures(clobberLimit);
1684
        
1685
        StructureSet newSet;
1686
        for (unsigned i = node->multiPutByOffsetData().variants.size(); i--;) {
1687
            const PutByIdVariant& variant = node->multiPutByOffsetData().variants[i];
1688
            if (variant.kind() == PutByIdVariant::Replace) {
1689
                if (value.m_currentKnownStructure.contains(variant.structure()))
1690
                    newSet.addAll(variant.structure());
1691
                continue;
1692
            }
1693
            ASSERT(variant.kind() == PutByIdVariant::Transition);
1694
            if (value.m_currentKnownStructure.contains(variant.oldStructure()))
1695
                newSet.addAll(variant.newStructure());
1696
        }
1697
        
1698
        // Use filter(value, set) as a way of setting the structure set. This works because
1699
        // we would have already made the set be TOP before this. Filtering top is another 
1700
        // way of setting.
1701
        filter(node->child1(), newSet);
1702
        break;
1703
    }
1704
    
1652
    case CheckFunction: {
1705
    case CheckFunction: {
1653
        JSValue value = forNode(node->child1()).value();
1706
        JSValue value = forNode(node->child1()).value();
1654
        if (value == node->function()) {
1707
        if (value == node->function()) {
Lines 1685-1702 bool AbstractInterpreter<AbstractStateTy Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h_sec3
1685
                structure,
1738
                structure,
1686
                m_graph.identifiers()[node->identifierNumber()],
1739
                m_graph.identifiers()[node->identifierNumber()],
1687
                node->op() == PutByIdDirect);
1740
                node->op() == PutByIdDirect);
1688
            if (status.isSimpleReplace()) {
1741
            if (status.isSimple() && status.numVariants() == 1) {
1689
                filter(node->child1(), structure);
1742
                if (status[0].kind() == PutByIdVariant::Replace) {
1690
                m_state.setFoundConstants(true);
1743
                    filter(node->child1(), structure);
1691
                m_state.setHaveStructures(true);
1744
                    m_state.setFoundConstants(true);
1692
                break;
1745
                    m_state.setHaveStructures(true);
1693
            }
1746
                    break;
1694
            if (status.isSimpleTransition()) {
1747
                }
1695
                clobberStructures(clobberLimit);
1748
                if (status[0].kind() == PutByIdVariant::Transition) {
1696
                forNode(node->child1()).set(m_graph, status.newStructure());
1749
                    clobberStructures(clobberLimit);
1697
                m_state.setHaveStructures(true);
1750
                    forNode(node->child1()).set(m_graph, status[0].newStructure());
1698
                m_state.setFoundConstants(true);
1751
                    m_state.setHaveStructures(true);
1699
                break;
1752
                    m_state.setFoundConstants(true);
1753
                    break;
1754
                }
1700
            }
1755
            }
1701
        }
1756
        }
1702
        clobberWorld(node->origin.semantic, clobberLimit);
1757
        clobberWorld(node->origin.semantic, clobberLimit);
- Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp -96 / +144 lines
Lines 179-185 private: Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp_sec1
179
    void handleGetById(
179
    void handleGetById(
180
        int destinationOperand, SpeculatedType, Node* base, unsigned identifierNumber,
180
        int destinationOperand, SpeculatedType, Node* base, unsigned identifierNumber,
181
        const GetByIdStatus&);
181
        const GetByIdStatus&);
182
    Node* emitPrototypeChecks(const GetByIdVariant&);
182
    void emitPutById(
183
        Node* base, unsigned identifierNumber, Node* value, bool isDirect);
184
    void handlePutById(
185
        Node* base, unsigned identifierNumber, Node* value, const PutByIdStatus&,
186
        bool isDirect);
187
    Node* emitPrototypeChecks(Structure*, IntendedStructureChain*);
183
188
184
    Node* getScope(bool skipTop, unsigned skipCount);
189
    Node* getScope(bool skipTop, unsigned skipCount);
185
    
190
    
Lines 1844-1858 Node* ByteCodeParser::handlePutByOffset( Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp_sec2
1844
    return result;
1849
    return result;
1845
}
1850
}
1846
1851
1847
Node* ByteCodeParser::emitPrototypeChecks(const GetByIdVariant& variant)
1852
Node* ByteCodeParser::emitPrototypeChecks(
1853
    Structure* structure, IntendedStructureChain* chain)
1848
{
1854
{
1849
    Node* base = 0;
1855
    Node* base = 0;
1850
    m_graph.chains().addLazily(variant.chain());
1856
    m_graph.chains().addLazily(chain);
1851
    Structure* currentStructure = variant.structureSet().singletonStructure();
1857
    Structure* currentStructure = structure;
1852
    JSObject* currentObject = 0;
1858
    JSObject* currentObject = 0;
1853
    for (unsigned i = 0; i < variant.chain()->size(); ++i) {
1859
    for (unsigned i = 0; i < chain->size(); ++i) {
1854
        currentObject = asObject(currentStructure->prototypeForLookup(m_inlineStackTop->m_codeBlock));
1860
        currentObject = asObject(currentStructure->prototypeForLookup(m_inlineStackTop->m_codeBlock));
1855
        currentStructure = variant.chain()->at(i);
1861
        currentStructure = chain->at(i);
1856
        base = cellConstantWithStructureCheck(currentObject, currentStructure);
1862
        base = cellConstantWithStructureCheck(currentObject, currentStructure);
1857
    }
1863
    }
1858
    RELEASE_ASSERT(base);
1864
    RELEASE_ASSERT(base);
Lines 1878-1889 void ByteCodeParser::handleGetById( Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp_sec3
1878
            return;
1884
            return;
1879
        }
1885
        }
1880
        
1886
        
1887
        if (m_graph.compilation())
1888
            m_graph.compilation()->noticeInlinedGetById();
1889
    
1881
        // 1) Emit prototype structure checks for all chains. This could sort of maybe not be
1890
        // 1) Emit prototype structure checks for all chains. This could sort of maybe not be
1882
        //    optimal, if there is some rarely executed case in the chain that requires a lot
1891
        //    optimal, if there is some rarely executed case in the chain that requires a lot
1883
        //    of checks and those checks are not watchpointable.
1892
        //    of checks and those checks are not watchpointable.
1884
        for (unsigned variantIndex = getByIdStatus.numVariants(); variantIndex--;) {
1893
        for (unsigned variantIndex = getByIdStatus.numVariants(); variantIndex--;) {
1885
            if (getByIdStatus[variantIndex].chain())
1894
            if (getByIdStatus[variantIndex].chain()) {
1886
                emitPrototypeChecks(getByIdStatus[variantIndex]);
1895
                emitPrototypeChecks(
1896
                    getByIdStatus[variantIndex].structureSet().singletonStructure(),
1897
                    getByIdStatus[variantIndex].chain());
1898
            }
1887
        }
1899
        }
1888
        
1900
        
1889
        // 2) Emit a MultiGetByOffset
1901
        // 2) Emit a MultiGetByOffset
Lines 1905-1912 void ByteCodeParser::handleGetById( Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp_sec4
1905
                
1917
                
1906
    addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(variant.structureSet())), base);
1918
    addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(variant.structureSet())), base);
1907
    
1919
    
1908
    if (variant.chain())
1920
    if (variant.chain()) {
1909
        base = emitPrototypeChecks(variant);
1921
        base = emitPrototypeChecks(
1922
            variant.structureSet().singletonStructure(), variant.chain());
1923
    }
1910
    
1924
    
1911
    // Unless we want bugs like https://bugs.webkit.org/show_bug.cgi?id=88783, we need to
1925
    // Unless we want bugs like https://bugs.webkit.org/show_bug.cgi?id=88783, we need to
1912
    // ensure that the base of the original get_by_id is kept alive until we're done with
1926
    // ensure that the base of the original get_by_id is kept alive until we're done with
Lines 1928-1933 void ByteCodeParser::handleGetById( Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp_sec5
1928
        destinationOperand, prediction, base, identifierNumber, variant.offset());
1942
        destinationOperand, prediction, base, identifierNumber, variant.offset());
1929
}
1943
}
1930
1944
1945
void ByteCodeParser::emitPutById(
1946
    Node* base, unsigned identifierNumber, Node* value, bool isDirect)
1947
{
1948
    if (isDirect)
1949
        addToGraph(PutByIdDirect, OpInfo(identifierNumber), base, value);
1950
    else
1951
        addToGraph(PutById, OpInfo(identifierNumber), base, value);
1952
}
1953
1954
void ByteCodeParser::handlePutById(
1955
    Node* base, unsigned identifierNumber, Node* value,
1956
    const PutByIdStatus& putByIdStatus, bool isDirect)
1957
{
1958
    if (!putByIdStatus.isSimple()) {
1959
        if (!putByIdStatus.isSet())
1960
            addToGraph(ForceOSRExit);
1961
        emitPutById(base, identifierNumber, value, isDirect);
1962
        return;
1963
    }
1964
    
1965
    if (putByIdStatus.numVariants() > 1) {
1966
        if (!isFTL(m_graph.m_plan.mode)) {
1967
            emitPutById(base, identifierNumber, value, isDirect);
1968
            return;
1969
        }
1970
        
1971
        if (m_graph.compilation())
1972
            m_graph.compilation()->noticeInlinedPutById();
1973
        
1974
        if (!isDirect) {
1975
            for (unsigned variantIndex = putByIdStatus.numVariants(); variantIndex--;) {
1976
                if (putByIdStatus[variantIndex].kind() != PutByIdVariant::Transition)
1977
                    continue;
1978
                if (!putByIdStatus[variantIndex].structureChain())
1979
                    continue;
1980
                emitPrototypeChecks(
1981
                    putByIdStatus[variantIndex].oldStructure(),
1982
                    putByIdStatus[variantIndex].structureChain());
1983
            }
1984
        }
1985
        
1986
        MultiPutByOffsetData* data = m_graph.m_multiPutByOffsetData.add();
1987
        data->variants = putByIdStatus.variants();
1988
        data->identifierNumber = identifierNumber;
1989
        addToGraph(MultiPutByOffset, OpInfo(data), base, value);
1990
        return;
1991
    }
1992
    
1993
    ASSERT(putByIdStatus.numVariants() == 1);
1994
    const PutByIdVariant& variant = putByIdStatus[0];
1995
    
1996
    if (variant.kind() == PutByIdVariant::Replace) {
1997
        addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(variant.structure())), base);
1998
        handlePutByOffset(base, identifierNumber, variant.offset(), value);
1999
        if (m_graph.compilation())
2000
            m_graph.compilation()->noticeInlinedPutById();
2001
        return;
2002
    }
2003
    
2004
    ASSERT(variant.kind() == PutByIdVariant::Transition);
2005
    if (variant.structureChain() && !variant.structureChain()->isStillValid()) {
2006
        emitPutById(base, identifierNumber, value, isDirect);
2007
        return;
2008
    }
2009
    
2010
    m_graph.chains().addLazily(variant.structureChain());
2011
                
2012
    addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(variant.oldStructure())), base);
2013
    if (!isDirect)
2014
        emitPrototypeChecks(variant.oldStructure(), variant.structureChain());
2015
2016
    ASSERT(variant.oldStructure()->transitionWatchpointSetHasBeenInvalidated());
2017
    
2018
    Node* propertyStorage;
2019
    StructureTransitionData* transitionData = m_graph.addStructureTransitionData(
2020
        StructureTransitionData(variant.oldStructure(), variant.newStructure()));
2021
2022
    if (variant.oldStructure()->outOfLineCapacity()
2023
        != variant.newStructure()->outOfLineCapacity()) {
2024
2025
        // If we're growing the property storage then it must be because we're
2026
        // storing into the out-of-line storage.
2027
        ASSERT(!isInlineOffset(variant.offset()));
2028
2029
        if (!variant.oldStructure()->outOfLineCapacity()) {
2030
            propertyStorage = addToGraph(
2031
                AllocatePropertyStorage, OpInfo(transitionData), base);
2032
        } else {
2033
            propertyStorage = addToGraph(
2034
                ReallocatePropertyStorage, OpInfo(transitionData),
2035
                base, addToGraph(GetButterfly, base));
2036
        }
2037
    } else {
2038
        if (isInlineOffset(variant.offset()))
2039
            propertyStorage = base;
2040
        else
2041
            propertyStorage = addToGraph(GetButterfly, base);
2042
    }
2043
2044
    addToGraph(PutStructure, OpInfo(transitionData), base);
2045
2046
    addToGraph(
2047
        PutByOffset,
2048
        OpInfo(m_graph.m_storageAccessData.size()),
2049
        propertyStorage,
2050
        base,
2051
        value);
2052
2053
    StorageAccessData storageAccessData;
2054
    storageAccessData.offset = variant.offset();
2055
    storageAccessData.identifierNumber = identifierNumber;
2056
    m_graph.m_storageAccessData.append(storageAccessData);
2057
2058
    if (m_graph.compilation())
2059
        m_graph.compilation()->noticeInlinedPutById();
2060
}
2061
1931
void ByteCodeParser::prepareToParseBlock()
2062
void ByteCodeParser::prepareToParseBlock()
1932
{
2063
{
1933
    for (unsigned i = 0; i < m_constants.size(); ++i)
2064
    for (unsigned i = 0; i < m_constants.size(); ++i)
Lines 2590-2680 bool ByteCodeParser::parseBlock(unsigned Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp_sec6
2590
                m_inlineStackTop->m_profiledBlock, m_dfgCodeBlock,
2721
                m_inlineStackTop->m_profiledBlock, m_dfgCodeBlock,
2591
                m_inlineStackTop->m_stubInfos, m_dfgStubInfos,
2722
                m_inlineStackTop->m_stubInfos, m_dfgStubInfos,
2592
                currentCodeOrigin(), m_graph.identifiers()[identifierNumber]);
2723
                currentCodeOrigin(), m_graph.identifiers()[identifierNumber]);
2593
            bool canCountAsInlined = true;
2594
            if (!putByIdStatus.isSet()) {
2595
                addToGraph(ForceOSRExit);
2596
                canCountAsInlined = false;
2597
            }
2598
            
2724
            
2599
            if (putByIdStatus.isSimpleReplace()) {
2725
            handlePutById(base, identifierNumber, value, putByIdStatus, direct);
2600
                addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(putByIdStatus.oldStructure())), base);
2601
                handlePutByOffset(base, identifierNumber, putByIdStatus.offset(), value);
2602
            } else if (
2603
                putByIdStatus.isSimpleTransition()
2604
                && (!putByIdStatus.structureChain()
2605
                    || putByIdStatus.structureChain()->isStillValid())) {
2606
                
2607
                m_graph.chains().addLazily(putByIdStatus.structureChain());
2608
                
2609
                addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(putByIdStatus.oldStructure())), base);
2610
                if (!direct) {
2611
                    if (!putByIdStatus.oldStructure()->storedPrototype().isNull()) {
2612
                        cellConstantWithStructureCheck(
2613
                            putByIdStatus.oldStructure()->storedPrototype().asCell());
2614
                    }
2615
                    
2616
                    for (unsigned i = 0; i < putByIdStatus.structureChain()->size(); ++i) {
2617
                        JSValue prototype = putByIdStatus.structureChain()->at(i)->storedPrototype();
2618
                        if (prototype.isNull())
2619
                            continue;
2620
                        cellConstantWithStructureCheck(prototype.asCell());
2621
                    }
2622
                }
2623
                ASSERT(putByIdStatus.oldStructure()->transitionWatchpointSetHasBeenInvalidated());
2624
                
2625
                Node* propertyStorage;
2626
                StructureTransitionData* transitionData =
2627
                    m_graph.addStructureTransitionData(
2628
                        StructureTransitionData(
2629
                            putByIdStatus.oldStructure(),
2630
                            putByIdStatus.newStructure()));
2631
2632
                if (putByIdStatus.oldStructure()->outOfLineCapacity()
2633
                    != putByIdStatus.newStructure()->outOfLineCapacity()) {
2634
                    
2635
                    // If we're growing the property storage then it must be because we're
2636
                    // storing into the out-of-line storage.
2637
                    ASSERT(!isInlineOffset(putByIdStatus.offset()));
2638
                    
2639
                    if (!putByIdStatus.oldStructure()->outOfLineCapacity()) {
2640
                        propertyStorage = addToGraph(
2641
                            AllocatePropertyStorage, OpInfo(transitionData), base);
2642
                    } else {
2643
                        propertyStorage = addToGraph(
2644
                            ReallocatePropertyStorage, OpInfo(transitionData),
2645
                            base, addToGraph(GetButterfly, base));
2646
                    }
2647
                } else {
2648
                    if (isInlineOffset(putByIdStatus.offset()))
2649
                        propertyStorage = base;
2650
                    else
2651
                        propertyStorage = addToGraph(GetButterfly, base);
2652
                }
2653
                
2654
                addToGraph(PutStructure, OpInfo(transitionData), base);
2655
                
2656
                addToGraph(
2657
                    PutByOffset,
2658
                    OpInfo(m_graph.m_storageAccessData.size()),
2659
                    propertyStorage,
2660
                    base,
2661
                    value);
2662
                
2663
                StorageAccessData storageAccessData;
2664
                storageAccessData.offset = putByIdStatus.offset();
2665
                storageAccessData.identifierNumber = identifierNumber;
2666
                m_graph.m_storageAccessData.append(storageAccessData);
2667
            } else {
2668
                if (direct)
2669
                    addToGraph(PutByIdDirect, OpInfo(identifierNumber), base, value);
2670
                else
2671
                    addToGraph(PutById, OpInfo(identifierNumber), base, value);
2672
                canCountAsInlined = false;
2673
            }
2674
            
2675
            if (canCountAsInlined && m_graph.compilation())
2676
                m_graph.compilation()->noticeInlinedPutById();
2677
2678
            NEXT_OPCODE(op_put_by_id);
2726
            NEXT_OPCODE(op_put_by_id);
2679
        }
2727
        }
2680
2728
Lines 3269-3279 bool ByteCodeParser::parseBlock(unsigned Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp_sec7
3269
            case GlobalProperty:
3317
            case GlobalProperty:
3270
            case GlobalPropertyWithVarInjectionChecks: {
3318
            case GlobalPropertyWithVarInjectionChecks: {
3271
                PutByIdStatus status = PutByIdStatus::computeFor(*m_vm, globalObject, structure, uid, false);
3319
                PutByIdStatus status = PutByIdStatus::computeFor(*m_vm, globalObject, structure, uid, false);
3272
                if (!status.isSimpleReplace()) {
3320
                if (status.numVariants() != 1 || status[0].kind() != PutByIdVariant::Replace) {
3273
                    addToGraph(PutById, OpInfo(identifierNumber), get(VirtualRegister(scope)), get(VirtualRegister(value)));
3321
                    addToGraph(PutById, OpInfo(identifierNumber), get(VirtualRegister(scope)), get(VirtualRegister(value)));
3274
                    break;
3322
                    break;
3275
                }
3323
                }
3276
                Node* base = cellConstantWithStructureCheck(globalObject, status.oldStructure());
3324
                Node* base = cellConstantWithStructureCheck(globalObject, status[0].structure());
3277
                addToGraph(Phantom, get(VirtualRegister(scope)));
3325
                addToGraph(Phantom, get(VirtualRegister(scope)));
3278
                handlePutByOffset(base, identifierNumber, static_cast<PropertyOffset>(operand), get(VirtualRegister(value)));
3326
                handlePutByOffset(base, identifierNumber, static_cast<PropertyOffset>(operand), get(VirtualRegister(value)));
3279
                // Keep scope alive until after put.
3327
                // Keep scope alive until after put.
- Source/JavaScriptCore/dfg/DFGCSEPhase.cpp -2 / +26 lines
Lines 495-501 private: Source/JavaScriptCore/dfg/DFGCSEPhase.cpp_sec1
495
            case PutByOffset:
495
            case PutByOffset:
496
                // Setting a property cannot change the structure.
496
                // Setting a property cannot change the structure.
497
                break;
497
                break;
498
                    
498
                
499
            case MultiPutByOffset:
500
                if (node->multiPutByOffsetData().writesStructures())
501
                    return false;
502
                break;
503
                
499
            case PutByValDirect:
504
            case PutByValDirect:
500
            case PutByVal:
505
            case PutByVal:
501
            case PutByValAlias:
506
            case PutByValAlias:
Lines 544-549 private: Source/JavaScriptCore/dfg/DFGCSEPhase.cpp_sec2
544
                // Setting a property cannot change the structure.
549
                // Setting a property cannot change the structure.
545
                break;
550
                break;
546
                    
551
                    
552
            case MultiPutByOffset:
553
                if (node->multiPutByOffsetData().writesStructures())
554
                    return false;
555
                break;
556
                
547
            case PutByValDirect:
557
            case PutByValDirect:
548
            case PutByVal:
558
            case PutByVal:
549
            case PutByValAlias:
559
            case PutByValAlias:
Lines 617-622 private: Source/JavaScriptCore/dfg/DFGCSEPhase.cpp_sec3
617
            case NewStringObject:
627
            case NewStringObject:
618
            case MakeRope:
628
            case MakeRope:
619
            case NewTypedArray:
629
            case NewTypedArray:
630
            case MultiPutByOffset:
620
                return 0;
631
                return 0;
621
                
632
                
622
            // This either exits, causes a GC (lazy string allocation), or clobbers
633
            // This either exits, causes a GC (lazy string allocation), or clobbers
Lines 668-673 private: Source/JavaScriptCore/dfg/DFGCSEPhase.cpp_sec4
668
                    return 0;
679
                    return 0;
669
                }
680
                }
670
                break;
681
                break;
682
                
683
            case MultiPutByOffset:
684
                if (node->multiPutByOffsetData().identifierNumber == identifierNumber) {
685
                    if (node->child1() == base)
686
                        return node->child2().node();
687
                    return 0;
688
                }
689
                break;
671
                    
690
                    
672
            case PutByValDirect:
691
            case PutByValDirect:
673
            case PutByVal:
692
            case PutByVal:
Lines 709-715 private: Source/JavaScriptCore/dfg/DFGCSEPhase.cpp_sec5
709
                    return 0;
728
                    return 0;
710
                }
729
                }
711
                break;
730
                break;
712
                    
731
                
732
            case MultiPutByOffset:
733
                if (node->multiPutByOffsetData().identifierNumber == identifierNumber)
734
                    return 0;
735
                break;
736
                
713
            case PutByValDirect:
737
            case PutByValDirect:
714
            case PutByVal:
738
            case PutByVal:
715
            case PutByValAlias:
739
            case PutByValAlias:
- Source/JavaScriptCore/dfg/DFGClobberize.h +14 lines
Lines 469-477 void clobberize(Graph& graph, Node* node Source/JavaScriptCore/dfg/DFGClobberize.h_sec1
469
        return;
469
        return;
470
        
470
        
471
    case MultiGetByOffset:
471
    case MultiGetByOffset:
472
        read(JSCell_structure);
473
        read(JSObject_butterfly);
472
        read(AbstractHeap(NamedProperties, node->multiGetByOffsetData().identifierNumber));
474
        read(AbstractHeap(NamedProperties, node->multiGetByOffsetData().identifierNumber));
473
        return;
475
        return;
474
        
476
        
477
    case MultiPutByOffset:
478
        read(JSCell_structure);
479
        read(JSObject_butterfly);
480
        write(AbstractHeap(NamedProperties, node->multiPutByOffsetData().identifierNumber));
481
        if (node->multiPutByOffsetData().writesStructures())
482
            write(JSCell_structure);
483
        if (node->multiPutByOffsetData().reallocatesStorage()) {
484
            write(JSObject_butterfly);
485
            clobberizeForAllocation(read, write);
486
        }
487
        return;
488
        
475
    case PutByOffset:
489
    case PutByOffset:
476
        write(AbstractHeap(NamedProperties, graph.m_storageAccessData[node->storageAccessDataIndex()].identifierNumber));
490
        write(AbstractHeap(NamedProperties, graph.m_storageAccessData[node->storageAccessDataIndex()].identifierNumber));
477
        return;
491
        return;
- Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp -91 / +127 lines
Lines 1-5 Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp_sec1
1
/*
1
/*
2
 * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
2
 * Copyright (C) 2012, 2013, 2014 Apple Inc. All rights reserved.
3
 *
3
 *
4
 * Redistribution and use in source and binary forms, with or without
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
5
 * modification, are permitted provided that the following conditions
Lines 174-179 private: Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp_sec2
174
                }
174
                }
175
                break;
175
                break;
176
            }
176
            }
177
                
178
            case MultiPutByOffset: {
179
                Edge childEdge = node->child1();
180
                Node* child = childEdge.node();
181
                MultiPutByOffsetData& data = node->multiPutByOffsetData();
182
183
                Structure* structure = m_state.forNode(child).bestProvenStructure();
184
                if (!structure)
185
                    break;
186
                
187
                for (unsigned i = data.variants.size(); i--;) {
188
                    const PutByIdVariant& variant = data.variants[i];
189
                    if (variant.oldStructure() != structure)
190
                        continue;
191
                    
192
                    emitPutByOffset(indexInBlock, node, structure, variant, data.identifierNumber);
193
                    eliminated = true;
194
                    break;
195
                }
196
                break;
197
            }
177
        
198
        
178
            case GetById:
199
            case GetById:
179
            case GetByIdFlush: {
200
            case GetByIdFlush: {
Lines 215-223 private: Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp_sec3
215
                if (!structure)
236
                if (!structure)
216
                    break;
237
                    break;
217
                
238
                
218
                bool needsWatchpoint = !m_state.forNode(child).m_currentKnownStructure.hasSingleton();
219
                bool needsCellCheck = m_state.forNode(child).m_type & ~SpecCell;
220
                
221
                PutByIdStatus status = PutByIdStatus::computeFor(
239
                PutByIdStatus status = PutByIdStatus::computeFor(
222
                    vm(),
240
                    vm(),
223
                    m_graph.globalObjectFor(origin.semantic),
241
                    m_graph.globalObjectFor(origin.semantic),
Lines 225-320 private: Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp_sec4
225
                    m_graph.identifiers()[identifierNumber],
243
                    m_graph.identifiers()[identifierNumber],
226
                    node->op() == PutByIdDirect);
244
                    node->op() == PutByIdDirect);
227
                
245
                
228
                if (!status.isSimpleReplace() && !status.isSimpleTransition())
246
                if (!status.isSimple())
247
                    break;
248
                if (status.numVariants() != 1)
229
                    break;
249
                    break;
230
                
250
                
231
                ASSERT(status.oldStructure() == structure);
251
                emitPutByOffset(indexInBlock, node, structure, status[0], identifierNumber);
232
                
233
                // Now before we do anything else, push the CFA forward over the PutById
234
                // and make sure we signal to the loop that it should continue and not
235
                // do any eliminations.
236
                m_interpreter.execute(indexInBlock);
237
                eliminated = true;
252
                eliminated = true;
238
                
239
                if (needsWatchpoint) {
240
                    m_insertionSet.insertNode(
241
                        indexInBlock, SpecNone, StructureTransitionWatchpoint, origin,
242
                        OpInfo(structure), childEdge);
243
                } else if (needsCellCheck) {
244
                    m_insertionSet.insertNode(
245
                        indexInBlock, SpecNone, Phantom, origin, childEdge);
246
                }
247
                
248
                childEdge.setUseKind(KnownCellUse);
249
                
250
                StructureTransitionData* transitionData = 0;
251
                if (status.isSimpleTransition()) {
252
                    transitionData = m_graph.addStructureTransitionData(
253
                        StructureTransitionData(structure, status.newStructure()));
254
                    
255
                    if (node->op() == PutById) {
256
                        if (!structure->storedPrototype().isNull()) {
257
                            addStructureTransitionCheck(
258
                                origin, indexInBlock,
259
                                structure->storedPrototype().asCell());
260
                        }
261
                        
262
                        m_graph.chains().addLazily(status.structureChain());
263
                        
264
                        for (unsigned i = 0; i < status.structureChain()->size(); ++i) {
265
                            JSValue prototype = status.structureChain()->at(i)->storedPrototype();
266
                            if (prototype.isNull())
267
                                continue;
268
                            ASSERT(prototype.isCell());
269
                            addStructureTransitionCheck(
270
                                origin, indexInBlock, prototype.asCell());
271
                        }
272
                    }
273
                }
274
                
275
                Edge propertyStorage;
276
                
277
                if (isInlineOffset(status.offset()))
278
                    propertyStorage = childEdge;
279
                else if (status.isSimpleReplace() || structure->outOfLineCapacity() == status.newStructure()->outOfLineCapacity()) {
280
                    propertyStorage = Edge(m_insertionSet.insertNode(
281
                        indexInBlock, SpecNone, GetButterfly, origin, childEdge));
282
                } else if (!structure->outOfLineCapacity()) {
283
                    ASSERT(status.newStructure()->outOfLineCapacity());
284
                    ASSERT(!isInlineOffset(status.offset()));
285
                    Node* allocatePropertyStorage = m_insertionSet.insertNode(
286
                        indexInBlock, SpecNone, AllocatePropertyStorage,
287
                        origin, OpInfo(transitionData), childEdge);
288
                    m_insertionSet.insertNode(indexInBlock, SpecNone, StoreBarrier, origin, Edge(node->child1().node(), KnownCellUse));
289
                    propertyStorage = Edge(allocatePropertyStorage);
290
                } else {
291
                    ASSERT(structure->outOfLineCapacity());
292
                    ASSERT(status.newStructure()->outOfLineCapacity() > structure->outOfLineCapacity());
293
                    ASSERT(!isInlineOffset(status.offset()));
294
                    
295
                    Node* reallocatePropertyStorage = m_insertionSet.insertNode(
296
                        indexInBlock, SpecNone, ReallocatePropertyStorage, origin,
297
                        OpInfo(transitionData), childEdge,
298
                        Edge(m_insertionSet.insertNode(
299
                            indexInBlock, SpecNone, GetButterfly, origin, childEdge)));
300
                    m_insertionSet.insertNode(indexInBlock, SpecNone, StoreBarrier, origin, Edge(node->child1().node(), KnownCellUse));
301
                    propertyStorage = Edge(reallocatePropertyStorage);
302
                }
303
                
304
                if (status.isSimpleTransition()) {
305
                    Node* putStructure = m_graph.addNode(SpecNone, PutStructure, origin, OpInfo(transitionData), childEdge);
306
                    m_insertionSet.insertNode(indexInBlock, SpecNone, StoreBarrier, origin, Edge(node->child1().node(), KnownCellUse));
307
                    m_insertionSet.insert(indexInBlock, putStructure);
308
                }
309
310
                node->convertToPutByOffset(m_graph.m_storageAccessData.size(), propertyStorage);
311
                m_insertionSet.insertNode(indexInBlock, SpecNone, ConditionalStoreBarrier, origin, 
312
                    Edge(node->child2().node(), KnownCellUse), Edge(node->child3().node(), UntypedUse));
313
                
314
                StorageAccessData storageAccessData;
315
                storageAccessData.offset = status.offset();
316
                storageAccessData.identifierNumber = identifierNumber;
317
                m_graph.m_storageAccessData.append(storageAccessData);
318
                break;
253
                break;
319
            }
254
            }
320
255
Lines 445-450 private: Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp_sec5
445
        m_graph.m_storageAccessData.append(storageAccessData);
380
        m_graph.m_storageAccessData.append(storageAccessData);
446
    }
381
    }
447
382
383
    void emitPutByOffset(unsigned indexInBlock, Node* node, Structure* structure, const PutByIdVariant& variant, unsigned identifierNumber)
384
    {
385
        NodeOrigin origin = node->origin;
386
        Edge childEdge = node->child1();
387
        Node* child = childEdge.node();
388
389
        ASSERT(variant.oldStructure() == structure);
390
        
391
        bool needsWatchpoint = !m_state.forNode(child).m_currentKnownStructure.hasSingleton();
392
        bool needsCellCheck = m_state.forNode(child).m_type & ~SpecCell;
393
        
394
        // Now before we do anything else, push the CFA forward over the PutById
395
        // and make sure we signal to the loop that it should continue and not
396
        // do any eliminations.
397
        m_interpreter.execute(indexInBlock);
398
399
        if (needsWatchpoint) {
400
            m_insertionSet.insertNode(
401
                indexInBlock, SpecNone, StructureTransitionWatchpoint, origin,
402
                OpInfo(structure), childEdge);
403
        } else if (needsCellCheck) {
404
            m_insertionSet.insertNode(
405
                indexInBlock, SpecNone, Phantom, origin, childEdge);
406
        }
407
408
        childEdge.setUseKind(KnownCellUse);
409
410
        StructureTransitionData* transitionData = 0;
411
        if (variant.kind() == PutByIdVariant::Transition) {
412
            transitionData = m_graph.addStructureTransitionData(
413
                StructureTransitionData(structure, variant.newStructure()));
414
415
            if (node->op() == PutById) {
416
                if (!structure->storedPrototype().isNull()) {
417
                    addStructureTransitionCheck(
418
                        origin, indexInBlock,
419
                        structure->storedPrototype().asCell());
420
                }
421
422
                m_graph.chains().addLazily(variant.structureChain());
423
424
                for (unsigned i = 0; i < variant.structureChain()->size(); ++i) {
425
                    JSValue prototype = variant.structureChain()->at(i)->storedPrototype();
426
                    if (prototype.isNull())
427
                        continue;
428
                    ASSERT(prototype.isCell());
429
                    addStructureTransitionCheck(
430
                        origin, indexInBlock, prototype.asCell());
431
                }
432
            }
433
        }
434
435
        Edge propertyStorage;
436
437
        if (isInlineOffset(variant.offset()))
438
            propertyStorage = childEdge;
439
        else if (
440
            variant.kind() == PutByIdVariant::Replace
441
            || structure->outOfLineCapacity() == variant.newStructure()->outOfLineCapacity()) {
442
            propertyStorage = Edge(m_insertionSet.insertNode(
443
                indexInBlock, SpecNone, GetButterfly, origin, childEdge));
444
        } else if (!structure->outOfLineCapacity()) {
445
            ASSERT(variant.newStructure()->outOfLineCapacity());
446
            ASSERT(!isInlineOffset(variant.offset()));
447
            Node* allocatePropertyStorage = m_insertionSet.insertNode(
448
                indexInBlock, SpecNone, AllocatePropertyStorage,
449
                origin, OpInfo(transitionData), childEdge);
450
            m_insertionSet.insertNode(indexInBlock, SpecNone, StoreBarrier, origin, Edge(node->child1().node(), KnownCellUse));
451
            propertyStorage = Edge(allocatePropertyStorage);
452
        } else {
453
            ASSERT(structure->outOfLineCapacity());
454
            ASSERT(variant.newStructure()->outOfLineCapacity() > structure->outOfLineCapacity());
455
            ASSERT(!isInlineOffset(variant.offset()));
456
457
            Node* reallocatePropertyStorage = m_insertionSet.insertNode(
458
                indexInBlock, SpecNone, ReallocatePropertyStorage, origin,
459
                OpInfo(transitionData), childEdge,
460
                Edge(m_insertionSet.insertNode(
461
                    indexInBlock, SpecNone, GetButterfly, origin, childEdge)));
462
            m_insertionSet.insertNode(indexInBlock, SpecNone, StoreBarrier, origin, Edge(node->child1().node(), KnownCellUse));
463
            propertyStorage = Edge(reallocatePropertyStorage);
464
        }
465
466
        if (variant.kind() == PutByIdVariant::Transition) {
467
            Node* putStructure = m_graph.addNode(SpecNone, PutStructure, origin, OpInfo(transitionData), childEdge);
468
            m_insertionSet.insertNode(indexInBlock, SpecNone, StoreBarrier, origin, Edge(node->child1().node(), KnownCellUse));
469
            m_insertionSet.insert(indexInBlock, putStructure);
470
        }
471
472
        node->convertToPutByOffset(m_graph.m_storageAccessData.size(), propertyStorage);
473
        m_insertionSet.insertNode(
474
            indexInBlock, SpecNone, ConditionalStoreBarrier, origin, 
475
            Edge(node->child2().node(), KnownCellUse),
476
            Edge(node->child3().node(), UntypedUse));
477
478
        StorageAccessData storageAccessData;
479
        storageAccessData.offset = variant.offset();
480
        storageAccessData.identifierNumber = identifierNumber;
481
        m_graph.m_storageAccessData.append(storageAccessData);
482
    }
483
448
    void addStructureTransitionCheck(NodeOrigin origin, unsigned indexInBlock, JSCell* cell)
484
    void addStructureTransitionCheck(NodeOrigin origin, unsigned indexInBlock, JSCell* cell)
449
    {
485
    {
450
        Node* weakConstant = m_insertionSet.insertNode(
486
        Node* weakConstant = m_insertionSet.insertNode(
- Source/JavaScriptCore/dfg/DFGFixupPhase.cpp +6 lines
Lines 891-896 private: Source/JavaScriptCore/dfg/DFGFixupPhase.cpp_sec1
891
            break;
891
            break;
892
        }
892
        }
893
            
893
            
894
        case MultiPutByOffset: {
895
            fixEdge<CellUse>(node->child1());
896
            insertStoreBarrier(m_indexInBlock, node->child1(), node->child2());
897
            break;
898
        }
899
            
894
        case InstanceOf: {
900
        case InstanceOf: {
895
            // FIXME: This appears broken: CheckHasInstance already does an unconditional cell
901
            // FIXME: This appears broken: CheckHasInstance already does an unconditional cell
896
            // check. https://bugs.webkit.org/show_bug.cgi?id=107479
902
            // check. https://bugs.webkit.org/show_bug.cgi?id=107479
- Source/JavaScriptCore/dfg/DFGGraph.cpp +6 lines
Lines 251-256 void Graph::dump(PrintStream& out, const Source/JavaScriptCore/dfg/DFGGraph.cpp_sec1
251
        for (unsigned i = 0; i < data.variants.size(); ++i)
251
        for (unsigned i = 0; i < data.variants.size(); ++i)
252
            out.print(comma, inContext(data.variants[i], context));
252
            out.print(comma, inContext(data.variants[i], context));
253
    }
253
    }
254
    if (node->hasMultiPutByOffsetData()) {
255
        MultiPutByOffsetData& data = node->multiPutByOffsetData();
256
        out.print(comma, "id", data.identifierNumber, "{", identifiers()[data.identifierNumber], "}");
257
        for (unsigned i = 0; i < data.variants.size(); ++i)
258
            out.print(comma, inContext(data.variants[i], context));
259
    }
254
    ASSERT(node->hasVariableAccessData(*this) == node->hasLocal(*this));
260
    ASSERT(node->hasVariableAccessData(*this) == node->hasLocal(*this));
255
    if (node->hasVariableAccessData(*this)) {
261
    if (node->hasVariableAccessData(*this)) {
256
        VariableAccessData* variableAccessData = node->tryGetVariableAccessData();
262
        VariableAccessData* variableAccessData = node->tryGetVariableAccessData();
- Source/JavaScriptCore/dfg/DFGGraph.h +1 lines
Lines 830-835 public: Source/JavaScriptCore/dfg/DFGGraph.h_sec1
830
    Bag<BranchData> m_branchData;
830
    Bag<BranchData> m_branchData;
831
    Bag<SwitchData> m_switchData;
831
    Bag<SwitchData> m_switchData;
832
    Bag<MultiGetByOffsetData> m_multiGetByOffsetData;
832
    Bag<MultiGetByOffsetData> m_multiGetByOffsetData;
833
    Bag<MultiPutByOffsetData> m_multiPutByOffsetData;
833
    Vector<InlineVariableData, 4> m_inlineVariableData;
834
    Vector<InlineVariableData, 4> m_inlineVariableData;
834
    OwnPtr<InlineCallFrameSet> m_inlineCallFrames;
835
    OwnPtr<InlineCallFrameSet> m_inlineCallFrames;
835
    HashMap<CodeBlock*, std::unique_ptr<FullBytecodeLiveness>> m_bytecodeLiveness;
836
    HashMap<CodeBlock*, std::unique_ptr<FullBytecodeLiveness>> m_bytecodeLiveness;
- Source/JavaScriptCore/dfg/DFGNode.cpp +24 lines
Lines 34-39 Source/JavaScriptCore/dfg/DFGNode.cpp_sec1
34
34
35
namespace JSC { namespace DFG {
35
namespace JSC { namespace DFG {
36
36
37
bool MultiPutByOffsetData::writesStructures() const
38
{
39
    for (unsigned i = variants.size(); i--;) {
40
        if (variants[i].kind() == PutByIdVariant::Transition)
41
            return true;
42
    }
43
    return false;
44
}
45
46
bool MultiPutByOffsetData::reallocatesStorage() const
47
{
48
    for (unsigned i = variants.size(); i--;) {
49
        if (variants[i].kind() != PutByIdVariant::Transition)
50
            continue;
51
        
52
        if (variants[i].oldStructure()->outOfLineCapacity() ==
53
            variants[i].newStructure()->outOfLineCapacity())
54
            continue;
55
        
56
        return true;
57
    }
58
    return false;
59
}
60
37
void BranchTarget::dump(PrintStream& out) const
61
void BranchTarget::dump(PrintStream& out) const
38
{
62
{
39
    if (!block)
63
    if (!block)
- Source/JavaScriptCore/dfg/DFGNode.h -1 / +20 lines
Lines 42-47 Source/JavaScriptCore/dfg/DFGNode.h_sec1
42
#include "GetByIdVariant.h"
42
#include "GetByIdVariant.h"
43
#include "JSCJSValue.h"
43
#include "JSCJSValue.h"
44
#include "Operands.h"
44
#include "Operands.h"
45
#include "PutByIdVariant.h"
45
#include "SpeculatedType.h"
46
#include "SpeculatedType.h"
46
#include "StructureSet.h"
47
#include "StructureSet.h"
47
#include "ValueProfile.h"
48
#include "ValueProfile.h"
Lines 57-62 struct MultiGetByOffsetData { Source/JavaScriptCore/dfg/DFGNode.h_sec2
57
    Vector<GetByIdVariant, 2> variants;
58
    Vector<GetByIdVariant, 2> variants;
58
};
59
};
59
60
61
struct MultiPutByOffsetData {
62
    unsigned identifierNumber;
63
    Vector<PutByIdVariant, 2> variants;
64
    
65
    bool writesStructures() const;
66
    bool reallocatesStorage() const;
67
};
68
60
struct StructureTransitionData {
69
struct StructureTransitionData {
61
    Structure* previousStructure;
70
    Structure* previousStructure;
62
    Structure* newStructure;
71
    Structure* newStructure;
Lines 460-466 struct Node { Source/JavaScriptCore/dfg/DFGNode.h_sec3
460
    
469
    
461
    void convertToPutByOffset(unsigned storageAccessDataIndex, Edge storage)
470
    void convertToPutByOffset(unsigned storageAccessDataIndex, Edge storage)
462
    {
471
    {
463
        ASSERT(m_op == PutById || m_op == PutByIdDirect);
472
        ASSERT(m_op == PutById || m_op == PutByIdDirect || m_op == MultiPutByOffset);
464
        m_opInfo = storageAccessDataIndex;
473
        m_opInfo = storageAccessDataIndex;
465
        children.setChild3(children.child2());
474
        children.setChild3(children.child2());
466
        children.setChild2(children.child1());
475
        children.setChild2(children.child1());
Lines 1091-1096 struct Node { Source/JavaScriptCore/dfg/DFGNode.h_sec4
1091
        return *reinterpret_cast<MultiGetByOffsetData*>(m_opInfo);
1100
        return *reinterpret_cast<MultiGetByOffsetData*>(m_opInfo);
1092
    }
1101
    }
1093
    
1102
    
1103
    bool hasMultiPutByOffsetData()
1104
    {
1105
        return op() == MultiPutByOffset;
1106
    }
1107
    
1108
    MultiPutByOffsetData& multiPutByOffsetData()
1109
    {
1110
        return *reinterpret_cast<MultiPutByOffsetData*>(m_opInfo);
1111
    }
1112
    
1094
    bool hasFunctionDeclIndex()
1113
    bool hasFunctionDeclIndex()
1095
    {
1114
    {
1096
        return op() == NewFunction
1115
        return op() == NewFunction
- Source/JavaScriptCore/dfg/DFGNodeType.h +1 lines
Lines 175-180 namespace JSC { namespace DFG { Source/JavaScriptCore/dfg/DFGNodeType.h_sec1
175
    macro(GetByOffset, NodeResultJS) \
175
    macro(GetByOffset, NodeResultJS) \
176
    macro(MultiGetByOffset, NodeResultJS) \
176
    macro(MultiGetByOffset, NodeResultJS) \
177
    macro(PutByOffset, NodeMustGenerate) \
177
    macro(PutByOffset, NodeMustGenerate) \
178
    macro(MultiPutByOffset, NodeMustGenerate) \
178
    macro(GetArrayLength, NodeResultInt32) \
179
    macro(GetArrayLength, NodeResultInt32) \
179
    macro(GetTypedArrayByteOffset, NodeResultInt32) \
180
    macro(GetTypedArrayByteOffset, NodeResultInt32) \
180
    macro(GetScope, NodeResultJS) \
181
    macro(GetScope, NodeResultJS) \
- Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp +1 lines
Lines 552-557 private: Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp_sec1
552
        case PutById:
552
        case PutById:
553
        case PutByIdDirect:
553
        case PutByIdDirect:
554
        case PutByOffset:
554
        case PutByOffset:
555
        case MultiPutByOffset:
555
        case DFG::Jump:
556
        case DFG::Jump:
556
        case Branch:
557
        case Branch:
557
        case Switch:
558
        case Switch:
- Source/JavaScriptCore/dfg/DFGSafeToExecute.h +1 lines
Lines 252-257 bool safeToExecute(AbstractStateType& st Source/JavaScriptCore/dfg/DFGSafeToExecute.h_sec1
252
    case ConstantStoragePointer:
252
    case ConstantStoragePointer:
253
    case Check:
253
    case Check:
254
    case MultiGetByOffset:
254
    case MultiGetByOffset:
255
    case MultiPutByOffset:
255
        return true;
256
        return true;
256
        
257
        
257
    case GetByVal:
258
    case GetByVal:
- Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp +1 lines
Lines 4689-4694 void SpeculativeJIT::compile(Node* node) Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp_sec1
4689
    case CheckInBounds:
4689
    case CheckInBounds:
4690
    case ArithIMul:
4690
    case ArithIMul:
4691
    case MultiGetByOffset:
4691
    case MultiGetByOffset:
4692
    case MultiPutByOffset:
4692
        RELEASE_ASSERT_NOT_REACHED();
4693
        RELEASE_ASSERT_NOT_REACHED();
4693
        break;
4694
        break;
4694
    }
4695
    }
- Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp +1 lines
Lines 5006-5011 void SpeculativeJIT::compile(Node* node) Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp_sec1
5006
    case CheckInBounds:
5006
    case CheckInBounds:
5007
    case ArithIMul:
5007
    case ArithIMul:
5008
    case MultiGetByOffset:
5008
    case MultiGetByOffset:
5009
    case MultiPutByOffset:
5009
        RELEASE_ASSERT_NOT_REACHED();
5010
        RELEASE_ASSERT_NOT_REACHED();
5010
        break;
5011
        break;
5011
    }
5012
    }
- Source/JavaScriptCore/dfg/DFGTypeCheckHoistingPhase.cpp +2 lines
Lines 246-251 private: Source/JavaScriptCore/dfg/DFGTypeCheckHoistingPhase.cpp_sec1
246
                case HardPhantom:
246
                case HardPhantom:
247
                case MovHint:
247
                case MovHint:
248
                case MultiGetByOffset:
248
                case MultiGetByOffset:
249
                case MultiPutByOffset:
249
                    // Don't count these uses.
250
                    // Don't count these uses.
250
                    break;
251
                    break;
251
                    
252
                    
Lines 346-351 private: Source/JavaScriptCore/dfg/DFGTypeCheckHoistingPhase.cpp_sec2
346
                case HardPhantom:
347
                case HardPhantom:
347
                case MovHint:
348
                case MovHint:
348
                case MultiGetByOffset:
349
                case MultiGetByOffset:
350
                case MultiPutByOffset:
349
                    // Don't count these uses.
351
                    // Don't count these uses.
350
                    break;
352
                    break;
351
                    
353
                    
- Source/JavaScriptCore/ftl/FTLCapabilities.cpp +1 lines
Lines 138-143 inline CapabilityLevel canCompile(Node* Source/JavaScriptCore/ftl/FTLCapabilities.cpp_sec1
138
    case GetById:
138
    case GetById:
139
    case ToThis:
139
    case ToThis:
140
    case MultiGetByOffset:
140
    case MultiGetByOffset:
141
    case MultiPutByOffset:
141
    case ToPrimitive:
142
    case ToPrimitive:
142
        // These are OK.
143
        // These are OK.
143
        break;
144
        break;
- Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp -107 / +204 lines
Lines 474-479 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec1
474
        case PutByOffset:
474
        case PutByOffset:
475
            compilePutByOffset();
475
            compilePutByOffset();
476
            break;
476
            break;
477
        case MultiPutByOffset:
478
            compileMultiPutByOffset();
479
            break;
477
        case GetGlobalVar:
480
        case GetGlobalVar:
478
            compileGetGlobalVar();
481
            compileGetGlobalVar();
479
            break;
482
            break;
Lines 1656-1663 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec2
1656
    {
1659
    {
1657
        m_ftlState.jitCode->common.notifyCompilingStructureTransition(m_graph.m_plan, codeBlock(), m_node);
1660
        m_ftlState.jitCode->common.notifyCompilingStructureTransition(m_graph.m_plan, codeBlock(), m_node);
1658
        
1661
        
1659
        m_out.store64(
1662
        m_out.storePtr(
1660
            m_out.constIntPtr(m_node->structureTransitionData().newStructure),
1663
            weakPointer(m_node->structureTransitionData().newStructure),
1661
            lowCell(m_node->child1()), m_heaps.JSCell_structure);
1664
            lowCell(m_node->child1()), m_heaps.JSCell_structure);
1662
    }
1665
    }
1663
    
1666
    
Lines 2708-2812 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec3
2708
    void compileAllocatePropertyStorage()
2711
    void compileAllocatePropertyStorage()
2709
    {
2712
    {
2710
        StructureTransitionData& data = m_node->structureTransitionData();
2713
        StructureTransitionData& data = m_node->structureTransitionData();
2711
        
2712
        LValue object = lowCell(m_node->child1());
2714
        LValue object = lowCell(m_node->child1());
2713
        
2715
        
2714
        if (data.previousStructure->couldHaveIndexingHeader()) {
2716
        setStorage(allocatePropertyStorage(object, data.previousStructure));
2715
            setStorage(vmCall(
2716
                m_out.operation(
2717
                    operationReallocateButterflyToHavePropertyStorageWithInitialCapacity),
2718
                m_callFrame, object));
2719
            return;
2720
        }
2721
        
2722
        LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, ("AllocatePropertyStorage slow path"));
2723
        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("AllocatePropertyStorage continuation"));
2724
        
2725
        LBasicBlock lastNext = m_out.insertNewBlocksBefore(slowPath);
2726
        
2727
        LValue endOfStorage = allocateBasicStorageAndGetEnd(
2728
            m_out.constIntPtr(initialOutOfLineCapacity * sizeof(JSValue)), slowPath);
2729
        
2730
        ValueFromBlock fastButterfly = m_out.anchor(
2731
            m_out.add(m_out.constIntPtr(sizeof(IndexingHeader)), endOfStorage));
2732
        
2733
        m_out.jump(continuation);
2734
        
2735
        m_out.appendTo(slowPath, continuation);
2736
        
2737
        ValueFromBlock slowButterfly = m_out.anchor(vmCall(
2738
            m_out.operation(operationAllocatePropertyStorageWithInitialCapacity), m_callFrame));
2739
        
2740
        m_out.jump(continuation);
2741
        
2742
        m_out.appendTo(continuation, lastNext);
2743
        
2744
        LValue result = m_out.phi(m_out.intPtr, fastButterfly, slowButterfly);
2745
        m_out.storePtr(result, object, m_heaps.JSObject_butterfly);
2746
        
2747
        setStorage(result);
2748
    }
2717
    }
2749
2718
2750
    void compileReallocatePropertyStorage()
2719
    void compileReallocatePropertyStorage()
2751
    {
2720
    {
2752
        StructureTransitionData& data = m_node->structureTransitionData();
2721
        StructureTransitionData& data = m_node->structureTransitionData();
2753
        
2754
        Structure* previous = data.previousStructure;
2755
        LValue object = lowCell(m_node->child1());
2722
        LValue object = lowCell(m_node->child1());
2756
2723
        LValue oldStorage = lowStorage(m_node->child2());
2757
        size_t oldSize = previous->outOfLineCapacity() * sizeof(JSValue);
2758
        size_t newSize = oldSize * outOfLineGrowthFactor; 
2759
2760
        ASSERT(newSize == data.newStructure->outOfLineCapacity() * sizeof(JSValue));
2761
        
2762
        if (previous->couldHaveIndexingHeader()) {
2763
            LValue newAllocSize = m_out.constInt64(newSize / sizeof(JSValue));                    
2764
            LValue result = vmCall(m_out.operation(operationReallocateButterflyToGrowPropertyStorage), m_callFrame, object, newAllocSize);
2765
            setStorage(result);
2766
            return;
2767
        }
2768
        
2724
        
2769
        LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, ("ReallocatePropertyStorage slow path"));
2725
        setStorage(
2770
        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ReallocatePropertyStorage continuation"));
2726
            reallocatePropertyStorage(
2771
        LBasicBlock lastNext = m_out.insertNewBlocksBefore(slowPath);
2727
                object, oldStorage, data.previousStructure, data.newStructure));
2772
        
2773
        LValue endOfStorage = 
2774
            allocateBasicStorageAndGetEnd(m_out.constIntPtr(newSize), slowPath);
2775
        
2776
        ValueFromBlock fastButterfly = m_out.anchor(m_out.add(m_out.constIntPtr(sizeof(IndexingHeader)), endOfStorage));
2777
        
2778
        m_out.jump(continuation);
2779
        
2780
        m_out.appendTo(slowPath, continuation);
2781
        
2782
        LValue newAllocSize = m_out.constInt64(newSize / sizeof(JSValue));       
2783
        
2784
        LValue storageLocation = vmCall(m_out.operation(operationAllocatePropertyStorage), m_callFrame, newAllocSize);
2785
        
2786
        ValueFromBlock slowButterfly = m_out.anchor(storageLocation);
2787
        
2788
        m_out.jump(continuation);
2789
        
2790
        m_out.appendTo(continuation, lastNext);
2791
        
2792
        LValue result = m_out.phi(m_out.intPtr, fastButterfly, slowButterfly);
2793
        LValue oldStorage = m_out.loadPtr(object, m_heaps.JSObject_butterfly);
2794
2795
        ptrdiff_t headerSize = -sizeof(JSValue) - sizeof(void *);
2796
        ptrdiff_t endStorage = headerSize - static_cast<ptrdiff_t>(oldSize);
2797
2798
        for (ptrdiff_t offset = headerSize; offset > endStorage; offset -= sizeof(void*)) {
2799
            LValue loaded = 
2800
                m_out.loadPtr(m_out.address(m_heaps.properties.atAnyNumber(), oldStorage, offset));
2801
            m_out.storePtr(loaded, m_out.address(m_heaps.properties.atAnyNumber(), result, offset));
2802
        } 
2803
        
2804
        m_out.storePtr(result, m_out.address(object, m_heaps.JSObject_butterfly));
2805
        
2806
        setStorage(result); 
2807
    }
2728
    }
2808
    
2729
    
2809
    
2810
    void compileToString()
2730
    void compileToString()
2811
    {
2731
    {
2812
        switch (m_node->child1().useKind()) {
2732
        switch (m_node->child1().useKind()) {
Lines 3140-3151 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec4
3140
        StorageAccessData& data =
3060
        StorageAccessData& data =
3141
            m_graph.m_storageAccessData[m_node->storageAccessDataIndex()];
3061
            m_graph.m_storageAccessData[m_node->storageAccessDataIndex()];
3142
        
3062
        
3143
        setJSValue(
3063
        setJSValue(loadProperty(
3144
            m_out.load64(
3064
            lowStorage(m_node->child1()), data.identifierNumber, data.offset));
3145
                m_out.address(
3146
                    m_heaps.properties[data.identifierNumber],
3147
                    lowStorage(m_node->child1()),
3148
                    offsetRelativeToBase(data.offset))));
3149
    }
3065
    }
3150
    
3066
    
3151
    void compileMultiGetByOffset()
3067
    void compileMultiGetByOffset()
Lines 3189-3199 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec5
3189
                    propertyBase = base;
3105
                    propertyBase = base;
3190
                if (!isInlineOffset(variant.offset()))
3106
                if (!isInlineOffset(variant.offset()))
3191
                    propertyBase = m_out.loadPtr(propertyBase, m_heaps.JSObject_butterfly);
3107
                    propertyBase = m_out.loadPtr(propertyBase, m_heaps.JSObject_butterfly);
3192
                result = m_out.load64(
3108
                result = loadProperty(propertyBase, data.identifierNumber, variant.offset());
3193
                    m_out.address(
3194
                        m_heaps.properties[data.identifierNumber],
3195
                        propertyBase,
3196
                        offsetRelativeToBase(variant.offset())));
3197
            }
3109
            }
3198
            
3110
            
3199
            results.append(m_out.anchor(result));
3111
            results.append(m_out.anchor(result));
Lines 3213-3224 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec6
3213
        StorageAccessData& data =
3125
        StorageAccessData& data =
3214
            m_graph.m_storageAccessData[m_node->storageAccessDataIndex()];
3126
            m_graph.m_storageAccessData[m_node->storageAccessDataIndex()];
3215
        
3127
        
3216
        m_out.store64(
3128
        storeProperty(
3217
            lowJSValue(m_node->child3()),
3129
            lowJSValue(m_node->child3()),
3218
            m_out.address(
3130
            lowStorage(m_node->child1()), data.identifierNumber, data.offset);
3219
                m_heaps.properties[data.identifierNumber],
3131
    }
3220
                lowStorage(m_node->child1()),
3132
    
3221
                offsetRelativeToBase(data.offset)));
3133
    void compileMultiPutByOffset()
3134
    {
3135
        LValue base = lowCell(m_node->child1());
3136
        LValue value = lowJSValue(m_node->child2());
3137
        
3138
        MultiPutByOffsetData& data = m_node->multiPutByOffsetData();
3139
        
3140
        Vector<LBasicBlock, 2> blocks(data.variants.size());
3141
        for (unsigned i = data.variants.size(); i--;)
3142
            blocks[i] = FTL_NEW_BLOCK(m_out, ("MultiPutByOffset case ", i));
3143
        LBasicBlock exit = FTL_NEW_BLOCK(m_out, ("MultiPutByOffset fail"));
3144
        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("MultiPutByOffset continuation"));
3145
        
3146
        Vector<SwitchCase, 2> cases;
3147
        for (unsigned i = data.variants.size(); i--;) {
3148
            PutByIdVariant variant = data.variants[i];
3149
            cases.append(
3150
                SwitchCase(weakPointer(variant.oldStructure()), blocks[i], Weight(1)));
3151
        }
3152
        m_out.switchInstruction(
3153
            m_out.loadPtr(base, m_heaps.JSCell_structure), cases, exit, Weight(0));
3154
        
3155
        LBasicBlock lastNext = m_out.m_nextBlock;
3156
        
3157
        for (unsigned i = data.variants.size(); i--;) {
3158
            m_out.appendTo(blocks[i], i  + 1 < data.variants.size() ? blocks[i + 1] : exit);
3159
            
3160
            PutByIdVariant variant = data.variants[i];
3161
            
3162
            LValue storage;
3163
            if (variant.kind() == PutByIdVariant::Replace) {
3164
                if (isInlineOffset(variant.offset()))
3165
                    storage = base;
3166
                else
3167
                    storage = m_out.loadPtr(base, m_heaps.JSObject_butterfly);
3168
            } else {
3169
                m_graph.m_plan.transitions.addLazily(
3170
                    codeBlock(), m_node->origin.semantic.codeOriginOwner(),
3171
                    variant.oldStructure(), variant.newStructure());
3172
                
3173
                storage = storageForTransition(
3174
                    base, variant.offset(), variant.oldStructure(), variant.newStructure());
3175
                m_out.storePtr(
3176
                    weakPointer(variant.newStructure()), base, m_heaps.JSCell_structure);
3177
            }
3178
            
3179
            storeProperty(value, storage, data.identifierNumber, variant.offset());
3180
            m_out.jump(continuation);
3181
        }
3182
        
3183
        m_out.appendTo(exit, continuation);
3184
        terminate(BadCache);
3185
        m_out.unreachable();
3186
        
3187
        m_out.appendTo(continuation, lastNext);
3222
    }
3188
    }
3223
    
3189
    
3224
    void compileGetGlobalVar()
3190
    void compileGetGlobalVar()
Lines 3748-3753 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec7
3748
        return m_out.booleanFalse;
3714
        return m_out.booleanFalse;
3749
    }
3715
    }
3750
    
3716
    
3717
    LValue loadProperty(LValue storage, unsigned identifierNumber, PropertyOffset offset)
3718
    {
3719
        return m_out.load64(addressOfProperty(storage, identifierNumber, offset));
3720
    }
3721
    
3722
    void storeProperty(
3723
        LValue value, LValue storage, unsigned identifierNumber, PropertyOffset offset)
3724
    {
3725
        m_out.store64(value, addressOfProperty(storage, identifierNumber, offset));
3726
    }
3727
    
3728
    TypedPointer addressOfProperty(
3729
        LValue storage, unsigned identifierNumber, PropertyOffset offset)
3730
    {
3731
        return m_out.address(
3732
            m_heaps.properties[identifierNumber], storage, offsetRelativeToBase(offset));
3733
    }
3734
    
3735
    LValue storageForTransition(
3736
        LValue object, PropertyOffset offset,
3737
        Structure* previousStructure, Structure* nextStructure)
3738
    {
3739
        if (isInlineOffset(offset))
3740
            return object;
3741
        
3742
        if (previousStructure->outOfLineCapacity() == nextStructure->outOfLineCapacity())
3743
            return m_out.loadPtr(object, m_heaps.JSObject_butterfly);
3744
        
3745
        LValue result;
3746
        if (!previousStructure->outOfLineCapacity())
3747
            result = allocatePropertyStorage(object, previousStructure);
3748
        else {
3749
            result = reallocatePropertyStorage(
3750
                object, m_out.loadPtr(object, m_heaps.JSObject_butterfly),
3751
                previousStructure, nextStructure);
3752
        }
3753
        
3754
        emitStoreBarrier(object);
3755
        
3756
        return result;
3757
    }
3758
    
3759
    LValue allocatePropertyStorage(LValue object, Structure* previousStructure)
3760
    {
3761
        if (previousStructure->couldHaveIndexingHeader()) {
3762
            return vmCall(
3763
                m_out.operation(
3764
                    operationReallocateButterflyToHavePropertyStorageWithInitialCapacity),
3765
                m_callFrame, object);
3766
        }
3767
        
3768
        LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, ("allocatePropertyStorage slow path"));
3769
        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("allocatePropertyStorage continuation"));
3770
        
3771
        LBasicBlock lastNext = m_out.insertNewBlocksBefore(slowPath);
3772
        
3773
        LValue endOfStorage = allocateBasicStorageAndGetEnd(
3774
            m_out.constIntPtr(initialOutOfLineCapacity * sizeof(JSValue)), slowPath);
3775
        
3776
        ValueFromBlock fastButterfly = m_out.anchor(
3777
            m_out.add(m_out.constIntPtr(sizeof(IndexingHeader)), endOfStorage));
3778
        
3779
        m_out.jump(continuation);
3780
        
3781
        m_out.appendTo(slowPath, continuation);
3782
        
3783
        ValueFromBlock slowButterfly = m_out.anchor(vmCall(
3784
            m_out.operation(operationAllocatePropertyStorageWithInitialCapacity), m_callFrame));
3785
        
3786
        m_out.jump(continuation);
3787
        
3788
        m_out.appendTo(continuation, lastNext);
3789
        
3790
        LValue result = m_out.phi(m_out.intPtr, fastButterfly, slowButterfly);
3791
        m_out.storePtr(result, object, m_heaps.JSObject_butterfly);
3792
        
3793
        return result;
3794
    }
3795
    
3796
    LValue reallocatePropertyStorage(
3797
        LValue object, LValue oldStorage, Structure* previous, Structure* next)
3798
    {
3799
        size_t oldSize = previous->outOfLineCapacity() * sizeof(JSValue);
3800
        size_t newSize = oldSize * outOfLineGrowthFactor; 
3801
3802
        ASSERT_UNUSED(next, newSize == next->outOfLineCapacity() * sizeof(JSValue));
3803
        
3804
        if (previous->couldHaveIndexingHeader()) {
3805
            LValue newAllocSize = m_out.constInt64(newSize / sizeof(JSValue));                    
3806
            return vmCall(m_out.operation(operationReallocateButterflyToGrowPropertyStorage), m_callFrame, object, newAllocSize);
3807
        }
3808
        
3809
        LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, ("reallocatePropertyStorage slow path"));
3810
        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("reallocatePropertyStorage continuation"));
3811
        LBasicBlock lastNext = m_out.insertNewBlocksBefore(slowPath);
3812
        
3813
        LValue endOfStorage = 
3814
            allocateBasicStorageAndGetEnd(m_out.constIntPtr(newSize), slowPath);
3815
        
3816
        ValueFromBlock fastButterfly = m_out.anchor(m_out.add(m_out.constIntPtr(sizeof(IndexingHeader)), endOfStorage));
3817
        
3818
        m_out.jump(continuation);
3819
        
3820
        m_out.appendTo(slowPath, continuation);
3821
        
3822
        LValue newAllocSize = m_out.constInt64(newSize / sizeof(JSValue));       
3823
        
3824
        LValue storageLocation = vmCall(m_out.operation(operationAllocatePropertyStorage), m_callFrame, newAllocSize);
3825
        
3826
        ValueFromBlock slowButterfly = m_out.anchor(storageLocation);
3827
        
3828
        m_out.jump(continuation);
3829
        
3830
        m_out.appendTo(continuation, lastNext);
3831
        
3832
        LValue result = m_out.phi(m_out.intPtr, fastButterfly, slowButterfly);
3833
3834
        ptrdiff_t headerSize = -sizeof(JSValue) - sizeof(void *);
3835
        ptrdiff_t endStorage = headerSize - static_cast<ptrdiff_t>(oldSize);
3836
3837
        for (ptrdiff_t offset = headerSize; offset > endStorage; offset -= sizeof(void*)) {
3838
            LValue loaded = 
3839
                m_out.loadPtr(m_out.address(m_heaps.properties.atAnyNumber(), oldStorage, offset));
3840
            m_out.storePtr(loaded, m_out.address(m_heaps.properties.atAnyNumber(), result, offset));
3841
        }
3842
        
3843
        m_out.storePtr(result, m_out.address(object, m_heaps.JSObject_butterfly));
3844
        
3845
        return result;
3846
    }
3847
    
3751
    LValue getById(LValue base)
3848
    LValue getById(LValue base)
3752
    {
3849
    {
3753
        StringImpl* uid = m_graph.identifiers()[m_node->identifierNumber()];
3850
        StringImpl* uid = m_graph.identifiers()[m_node->identifierNumber()];
Lines 5185-5191 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec8
5185
        return m_out.load8(m_out.baseIndex(m_heaps.MarkedBlock_markBits, markedBlock, markByteIndex, ScaleOne, MarkedBlock::offsetOfMarks()));
5282
        return m_out.load8(m_out.baseIndex(m_heaps.MarkedBlock_markBits, markedBlock, markByteIndex, ScaleOne, MarkedBlock::offsetOfMarks()));
5186
    }
5283
    }
5187
5284
5188
    void emitStoreBarrier(LValue base, LValue value, Edge& valueEdge)
5285
    void emitStoreBarrier(LValue base, LValue value, Edge valueEdge)
5189
    {
5286
    {
5190
#if ENABLE(GGC)
5287
#if ENABLE(GGC)
5191
        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("Store barrier continuation"));
5288
        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("Store barrier continuation"));
- Source/JavaScriptCore/tests/stress/multi-put-by-offset-reallocation-cases.js +100 lines
Line 0 Source/JavaScriptCore/tests/stress/multi-put-by-offset-reallocation-cases.js_sec1
1
var foos = [
2
    function(o) { o.ff = 42; },
3
    function(o) { o.ff = 42; },
4
    function(o) { o.ff = 42; },
5
    function(o) { o.ff = 42; },
6
    function(o) { o.ff = 42; },
7
    function(o) { o.ff = 42; },
8
    function(o) { o.ff = 42; },
9
    function(o) { o.ff = 42; }
10
];
11
12
if (foos.length != 8)
13
    throw "Error";
14
15
function bar(o, n) {
16
    if (n == 0)
17
        return;
18
    o.na = 1;
19
    if (n == 1)
20
        return;
21
    o.nb = 2;
22
    if (n == 2)
23
        return;
24
    o.nc = 3;
25
    if (n == 3)
26
        return;
27
    o.nd = 4;
28
    if (n == 4)
29
        return;
30
    o.ne = 5;
31
    if (n == 5)
32
        return;
33
    o.nf = 6;
34
    if (n == 6)
35
        return;
36
    o.ng = 7;
37
    if (n == 7)
38
        return;
39
    o.nh = 8;
40
}
41
42
function baz(o, n) {
43
    if (n == 0)
44
        return;
45
    if (o.na != 1)
46
        throw "Memory corruption";
47
    if (n == 1)
48
        return;
49
    if (o.nb != 2)
50
        throw "Memory corruption";
51
    if (n == 2)
52
        return;
53
    if (o.nc != 3)
54
        throw "Memory corruption";
55
    if (n == 3)
56
        return;
57
    if (o.nd != 4)
58
        throw "Memory corruption";
59
    if (n == 4)
60
        return;
61
    if (o.ne != 5)
62
        throw "Memory corruption";
63
    if (n == 5)
64
        return;
65
    if (o.nf != 6)
66
        throw "Memory corruption";
67
    if (n == 6)
68
        return;
69
    if (o.ng != 7)
70
        throw "Memory corruption";
71
    if (n == 7)
72
        return;
73
    if (o.nh != 8)
74
        throw "Memory corruption";
75
}
76
77
for (var i = 0; i < 8; ++i)
78
    noInline(foos[i]);
79
noInline(bar);
80
81
for (var i = 0; i < 100000; ++i) {
82
    var o = {};
83
    var p = {a:1, b:2, c:3, d:4, e:5, f:6};
84
    bar(o, i % 8);
85
    bar(p, i % 8);
86
    
87
    foos[i % 8](o);
88
    foos[i % 8](p);
89
    
90
    if (o.ff != 42)
91
        throw "Bad result in o: " + o.ff;
92
    if (p.ff != 42)
93
        throw "Bad result in o: " + p.ff;
94
    
95
    if (p.a != 1 || p.b != 2 || p.c != 3 || p.d != 4 || p.e != 5 || p.f != 6)
96
        throw "Memory corruption"
97
    baz(o, i % 8);
98
    baz(p, i % 8);
99
}
100

Return to Bug 129210