| Differences between
and this patch
- Source/JavaScriptCore/ChangeLog +115 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
        * CMakeLists.txt:
19
        * GNUmakefile.list.am:
20
        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
21
        * JavaScriptCore.xcodeproj/project.pbxproj:
22
        * bytecode/PutByIdStatus.cpp:
23
        (JSC::PutByIdStatus::computeFromLLInt):
24
        (JSC::PutByIdStatus::computeFor):
25
        (JSC::PutByIdStatus::computeForStubInfo):
26
        (JSC::PutByIdStatus::dump):
27
        * bytecode/PutByIdStatus.h:
28
        (JSC::PutByIdStatus::PutByIdStatus):
29
        (JSC::PutByIdStatus::isSimple):
30
        (JSC::PutByIdStatus::numVariants):
31
        (JSC::PutByIdStatus::variants):
32
        (JSC::PutByIdStatus::at):
33
        (JSC::PutByIdStatus::operator[]):
34
        * bytecode/PutByIdVariant.cpp: Added.
35
        (JSC::PutByIdVariant::dump):
36
        (JSC::PutByIdVariant::dumpInContext):
37
        * bytecode/PutByIdVariant.h: Added.
38
        (JSC::PutByIdVariant::PutByIdVariant):
39
        (JSC::PutByIdVariant::replace):
40
        (JSC::PutByIdVariant::transition):
41
        (JSC::PutByIdVariant::kind):
42
        (JSC::PutByIdVariant::isSet):
43
        (JSC::PutByIdVariant::operator!):
44
        (JSC::PutByIdVariant::structure):
45
        (JSC::PutByIdVariant::oldStructure):
46
        (JSC::PutByIdVariant::newStructure):
47
        (JSC::PutByIdVariant::structureChain):
48
        (JSC::PutByIdVariant::offset):
49
        * dfg/DFGAbstractInterpreterInlines.h:
50
        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
51
        * dfg/DFGByteCodeParser.cpp:
52
        (JSC::DFG::ByteCodeParser::emitPrototypeChecks):
53
        (JSC::DFG::ByteCodeParser::handleGetById):
54
        (JSC::DFG::ByteCodeParser::emitPutById):
55
        (JSC::DFG::ByteCodeParser::handlePutById):
56
        (JSC::DFG::ByteCodeParser::parseBlock):
57
        * dfg/DFGCSEPhase.cpp:
58
        (JSC::DFG::CSEPhase::checkStructureElimination):
59
        (JSC::DFG::CSEPhase::structureTransitionWatchpointElimination):
60
        (JSC::DFG::CSEPhase::putStructureStoreElimination):
61
        (JSC::DFG::CSEPhase::getByOffsetLoadElimination):
62
        (JSC::DFG::CSEPhase::putByOffsetStoreElimination):
63
        * dfg/DFGClobberize.h:
64
        (JSC::DFG::clobberize):
65
        * dfg/DFGConstantFoldingPhase.cpp:
66
        (JSC::DFG::ConstantFoldingPhase::foldConstants):
67
        (JSC::DFG::ConstantFoldingPhase::emitPutByOffset):
68
        * dfg/DFGFixupPhase.cpp:
69
        (JSC::DFG::FixupPhase::fixupNode):
70
        * dfg/DFGGraph.cpp:
71
        (JSC::DFG::Graph::dump):
72
        * dfg/DFGGraph.h:
73
        * dfg/DFGNode.cpp:
74
        (JSC::DFG::MultiPutByOffsetData::writesStructures):
75
        (JSC::DFG::MultiPutByOffsetData::reallocatesStorage):
76
        * dfg/DFGNode.h:
77
        (JSC::DFG::Node::convertToPutByOffset):
78
        (JSC::DFG::Node::hasMultiPutByOffsetData):
79
        (JSC::DFG::Node::multiPutByOffsetData):
80
        * dfg/DFGNodeType.h:
81
        * dfg/DFGPredictionPropagationPhase.cpp:
82
        (JSC::DFG::PredictionPropagationPhase::propagate):
83
        * dfg/DFGSafeToExecute.h:
84
        (JSC::DFG::safeToExecute):
85
        * dfg/DFGSpeculativeJIT32_64.cpp:
86
        (JSC::DFG::SpeculativeJIT::compile):
87
        * dfg/DFGSpeculativeJIT64.cpp:
88
        (JSC::DFG::SpeculativeJIT::compile):
89
        * dfg/DFGTypeCheckHoistingPhase.cpp:
90
        (JSC::DFG::TypeCheckHoistingPhase::identifyRedundantStructureChecks):
91
        (JSC::DFG::TypeCheckHoistingPhase::identifyRedundantArrayChecks):
92
        * ftl/FTLCapabilities.cpp:
93
        (JSC::FTL::canCompile):
94
        * ftl/FTLLowerDFGToLLVM.cpp:
95
        (JSC::FTL::LowerDFGToLLVM::compileNode):
96
        (JSC::FTL::LowerDFGToLLVM::compilePutStructure):
97
        (JSC::FTL::LowerDFGToLLVM::compileAllocatePropertyStorage):
98
        (JSC::FTL::LowerDFGToLLVM::compileReallocatePropertyStorage):
99
        (JSC::FTL::LowerDFGToLLVM::compileGetByOffset):
100
        (JSC::FTL::LowerDFGToLLVM::compileMultiGetByOffset):
101
        (JSC::FTL::LowerDFGToLLVM::compilePutByOffset):
102
        (JSC::FTL::LowerDFGToLLVM::compileMultiPutByOffset):
103
        (JSC::FTL::LowerDFGToLLVM::loadProperty):
104
        (JSC::FTL::LowerDFGToLLVM::storeProperty):
105
        (JSC::FTL::LowerDFGToLLVM::addressOfProperty):
106
        (JSC::FTL::LowerDFGToLLVM::storageForTransition):
107
        (JSC::FTL::LowerDFGToLLVM::allocatePropertyStorage):
108
        (JSC::FTL::LowerDFGToLLVM::reallocatePropertyStorage):
109
        (JSC::FTL::LowerDFGToLLVM::emitStoreBarrier):
110
        * tests/stress/multi-put-by-offset-reallocation-cases.js: Added.
111
        (foos):
112
        (bar):
113
        (baz):
114
        (.o):
115
1
2014-02-23  Sam Weinig  <sam@webkit.org>
116
2014-02-23  Sam Weinig  <sam@webkit.org>
2
117
3
        Update FeatureDefines.xcconfig
118
        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 5383-5388 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec4
5383
				0F2FCCFC18A60070001A27F8 /* DFGSafepoint.h in Headers */,
5389
				0F2FCCFC18A60070001A27F8 /* DFGSafepoint.h in Headers */,
5384
				860161E50F3A83C100F84710 /* MacroAssemblerX86_64.h in Headers */,
5390
				860161E50F3A83C100F84710 /* MacroAssemblerX86_64.h in Headers */,
5385
				860161E60F3A83C100F84710 /* MacroAssemblerX86Common.h in Headers */,
5391
				860161E60F3A83C100F84710 /* MacroAssemblerX86Common.h in Headers */,
5392
				0F93B4AA18B92C4D00178A3F /* PutByIdVariant.h in Headers */,
5386
				A700873A17CBE85300C3E643 /* MapConstructor.h in Headers */,
5393
				A700873A17CBE85300C3E643 /* MapConstructor.h in Headers */,
5387
				A78507D717CBC6FD0011F6E7 /* MapData.h in Headers */,
5394
				A78507D717CBC6FD0011F6E7 /* MapData.h in Headers */,
5388
				A700873E17CBE8D300C3E643 /* MapPrototype.h in Headers */,
5395
				A700873E17CBE8D300C3E643 /* MapPrototype.h in Headers */,
Lines 6176-6181 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec5
6176
				0F9FB4F417FCB91700CB67F8 /* DFGStackLayoutPhase.cpp in Sources */,
6183
				0F9FB4F417FCB91700CB67F8 /* DFGStackLayoutPhase.cpp in Sources */,
6177
				0F6B1CBD1861246A00845D97 /* RegisterPreservationWrapperGenerator.cpp in Sources */,
6184
				0F6B1CBD1861246A00845D97 /* RegisterPreservationWrapperGenerator.cpp in Sources */,
6178
				0FC097A1146B28CA00CF2442 /* DFGThunks.cpp in Sources */,
6185
				0FC097A1146B28CA00CF2442 /* DFGThunks.cpp in Sources */,
6186
				0F93B4A918B92C4D00178A3F /* PutByIdVariant.cpp in Sources */,
6179
				0FD8A32717D51F5700CA2C40 /* DFGTierUpCheckInjectionPhase.cpp in Sources */,
6187
				0FD8A32717D51F5700CA2C40 /* DFGTierUpCheckInjectionPhase.cpp in Sources */,
6180
				0FD8A32917D51F5700CA2C40 /* DFGToFTLDeferredCompilationCallback.cpp in Sources */,
6188
				0FD8A32917D51F5700CA2C40 /* DFGToFTLDeferredCompilationCallback.cpp in Sources */,
6181
				0F485327187DFDEC0083B687 /* FTLAvailableRecovery.cpp in Sources */,
6189
				0F485327187DFDEC0083B687 /* FTLAvailableRecovery.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 1834-1848 Node* ByteCodeParser::handlePutByOffset( Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp_sec2
1834
    return result;
1839
    return result;
1835
}
1840
}
1836
1841
1837
Node* ByteCodeParser::emitPrototypeChecks(const GetByIdVariant& variant)
1842
Node* ByteCodeParser::emitPrototypeChecks(
1843
    Structure* structure, IntendedStructureChain* chain)
1838
{
1844
{
1839
    Node* base = 0;
1845
    Node* base = 0;
1840
    m_graph.chains().addLazily(variant.chain());
1846
    m_graph.chains().addLazily(chain);
1841
    Structure* currentStructure = variant.structureSet().singletonStructure();
1847
    Structure* currentStructure = structure;
1842
    JSObject* currentObject = 0;
1848
    JSObject* currentObject = 0;
1843
    for (unsigned i = 0; i < variant.chain()->size(); ++i) {
1849
    for (unsigned i = 0; i < chain->size(); ++i) {
1844
        currentObject = asObject(currentStructure->prototypeForLookup(m_inlineStackTop->m_codeBlock));
1850
        currentObject = asObject(currentStructure->prototypeForLookup(m_inlineStackTop->m_codeBlock));
1845
        currentStructure = variant.chain()->at(i);
1851
        currentStructure = chain->at(i);
1846
        base = cellConstantWithStructureCheck(currentObject, currentStructure);
1852
        base = cellConstantWithStructureCheck(currentObject, currentStructure);
1847
    }
1853
    }
1848
    RELEASE_ASSERT(base);
1854
    RELEASE_ASSERT(base);
Lines 1868-1879 void ByteCodeParser::handleGetById( Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp_sec3
1868
            return;
1874
            return;
1869
        }
1875
        }
1870
        
1876
        
1877
        if (m_graph.compilation())
1878
            m_graph.compilation()->noticeInlinedGetById();
1879
    
1871
        // 1) Emit prototype structure checks for all chains. This could sort of maybe not be
1880
        // 1) Emit prototype structure checks for all chains. This could sort of maybe not be
1872
        //    optimal, if there is some rarely executed case in the chain that requires a lot
1881
        //    optimal, if there is some rarely executed case in the chain that requires a lot
1873
        //    of checks and those checks are not watchpointable.
1882
        //    of checks and those checks are not watchpointable.
1874
        for (unsigned variantIndex = getByIdStatus.numVariants(); variantIndex--;) {
1883
        for (unsigned variantIndex = getByIdStatus.numVariants(); variantIndex--;) {
1875
            if (getByIdStatus[variantIndex].chain())
1884
            if (getByIdStatus[variantIndex].chain()) {
1876
                emitPrototypeChecks(getByIdStatus[variantIndex]);
1885
                emitPrototypeChecks(
1886
                    getByIdStatus[variantIndex].structureSet().singletonStructure(),
1887
                    getByIdStatus[variantIndex].chain());
1888
            }
1877
        }
1889
        }
1878
        
1890
        
1879
        // 2) Emit a MultiGetByOffset
1891
        // 2) Emit a MultiGetByOffset
Lines 1895-1902 void ByteCodeParser::handleGetById( Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp_sec4
1895
                
1907
                
1896
    addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(variant.structureSet())), base);
1908
    addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(variant.structureSet())), base);
1897
    
1909
    
1898
    if (variant.chain())
1910
    if (variant.chain()) {
1899
        base = emitPrototypeChecks(variant);
1911
        base = emitPrototypeChecks(
1912
            variant.structureSet().singletonStructure(), variant.chain());
1913
    }
1900
    
1914
    
1901
    // Unless we want bugs like https://bugs.webkit.org/show_bug.cgi?id=88783, we need to
1915
    // Unless we want bugs like https://bugs.webkit.org/show_bug.cgi?id=88783, we need to
1902
    // ensure that the base of the original get_by_id is kept alive until we're done with
1916
    // ensure that the base of the original get_by_id is kept alive until we're done with
Lines 1918-1923 void ByteCodeParser::handleGetById( Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp_sec5
1918
        destinationOperand, prediction, base, identifierNumber, variant.offset());
1932
        destinationOperand, prediction, base, identifierNumber, variant.offset());
1919
}
1933
}
1920
1934
1935
void ByteCodeParser::emitPutById(
1936
    Node* base, unsigned identifierNumber, Node* value, bool isDirect)
1937
{
1938
    if (isDirect)
1939
        addToGraph(PutByIdDirect, OpInfo(identifierNumber), base, value);
1940
    else
1941
        addToGraph(PutById, OpInfo(identifierNumber), base, value);
1942
}
1943
1944
void ByteCodeParser::handlePutById(
1945
    Node* base, unsigned identifierNumber, Node* value,
1946
    const PutByIdStatus& putByIdStatus, bool isDirect)
1947
{
1948
    if (!putByIdStatus.isSimple()) {
1949
        if (!putByIdStatus.isSet())
1950
            addToGraph(ForceOSRExit);
1951
        emitPutById(base, identifierNumber, value, isDirect);
1952
        return;
1953
    }
1954
    
1955
    if (putByIdStatus.numVariants() > 1) {
1956
        if (!isFTL(m_graph.m_plan.mode)) {
1957
            emitPutById(base, identifierNumber, value, isDirect);
1958
            return;
1959
        }
1960
        
1961
        if (m_graph.compilation())
1962
            m_graph.compilation()->noticeInlinedPutById();
1963
        
1964
        if (!isDirect) {
1965
            for (unsigned variantIndex = putByIdStatus.numVariants(); variantIndex--;) {
1966
                if (putByIdStatus[variantIndex].kind() != PutByIdVariant::Transition)
1967
                    continue;
1968
                if (!putByIdStatus[variantIndex].structureChain())
1969
                    continue;
1970
                emitPrototypeChecks(
1971
                    putByIdStatus[variantIndex].oldStructure(),
1972
                    putByIdStatus[variantIndex].structureChain());
1973
            }
1974
        }
1975
        
1976
        MultiPutByOffsetData* data = m_graph.m_multiPutByOffsetData.add();
1977
        data->variants = putByIdStatus.variants();
1978
        data->identifierNumber = identifierNumber;
1979
        addToGraph(MultiPutByOffset, OpInfo(data), base, value);
1980
        return;
1981
    }
1982
    
1983
    ASSERT(putByIdStatus.numVariants() == 1);
1984
    const PutByIdVariant& variant = putByIdStatus[0];
1985
    
1986
    if (variant.kind() == PutByIdVariant::Replace) {
1987
        addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(variant.structure())), base);
1988
        handlePutByOffset(base, identifierNumber, variant.offset(), value);
1989
        if (m_graph.compilation())
1990
            m_graph.compilation()->noticeInlinedPutById();
1991
        return;
1992
    }
1993
    
1994
    ASSERT(variant.kind() == PutByIdVariant::Transition);
1995
    if (variant.structureChain() && !variant.structureChain()->isStillValid()) {
1996
        emitPutById(base, identifierNumber, value, isDirect);
1997
        return;
1998
    }
1999
    
2000
    m_graph.chains().addLazily(variant.structureChain());
2001
                
2002
    addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(variant.oldStructure())), base);
2003
    if (!isDirect)
2004
        emitPrototypeChecks(variant.oldStructure(), variant.structureChain());
2005
2006
    ASSERT(variant.oldStructure()->transitionWatchpointSetHasBeenInvalidated());
2007
    
2008
    Node* propertyStorage;
2009
    StructureTransitionData* transitionData = m_graph.addStructureTransitionData(
2010
        StructureTransitionData(variant.oldStructure(), variant.newStructure()));
2011
2012
    if (variant.oldStructure()->outOfLineCapacity()
2013
        != variant.newStructure()->outOfLineCapacity()) {
2014
2015
        // If we're growing the property storage then it must be because we're
2016
        // storing into the out-of-line storage.
2017
        ASSERT(!isInlineOffset(variant.offset()));
2018
2019
        if (!variant.oldStructure()->outOfLineCapacity()) {
2020
            propertyStorage = addToGraph(
2021
                AllocatePropertyStorage, OpInfo(transitionData), base);
2022
        } else {
2023
            propertyStorage = addToGraph(
2024
                ReallocatePropertyStorage, OpInfo(transitionData),
2025
                base, addToGraph(GetButterfly, base));
2026
        }
2027
    } else {
2028
        if (isInlineOffset(variant.offset()))
2029
            propertyStorage = base;
2030
        else
2031
            propertyStorage = addToGraph(GetButterfly, base);
2032
    }
2033
2034
    addToGraph(PutStructure, OpInfo(transitionData), base);
2035
2036
    addToGraph(
2037
        PutByOffset,
2038
        OpInfo(m_graph.m_storageAccessData.size()),
2039
        propertyStorage,
2040
        base,
2041
        value);
2042
2043
    StorageAccessData storageAccessData;
2044
    storageAccessData.offset = variant.offset();
2045
    storageAccessData.identifierNumber = identifierNumber;
2046
    m_graph.m_storageAccessData.append(storageAccessData);
2047
2048
    if (m_graph.compilation())
2049
        m_graph.compilation()->noticeInlinedPutById();
2050
}
2051
1921
void ByteCodeParser::prepareToParseBlock()
2052
void ByteCodeParser::prepareToParseBlock()
1922
{
2053
{
1923
    for (unsigned i = 0; i < m_constants.size(); ++i)
2054
    for (unsigned i = 0; i < m_constants.size(); ++i)
Lines 2580-2670 bool ByteCodeParser::parseBlock(unsigned Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp_sec6
2580
                m_inlineStackTop->m_profiledBlock, m_dfgCodeBlock,
2711
                m_inlineStackTop->m_profiledBlock, m_dfgCodeBlock,
2581
                m_inlineStackTop->m_stubInfos, m_dfgStubInfos,
2712
                m_inlineStackTop->m_stubInfos, m_dfgStubInfos,
2582
                currentCodeOrigin(), m_graph.identifiers()[identifierNumber]);
2713
                currentCodeOrigin(), m_graph.identifiers()[identifierNumber]);
2583
            bool canCountAsInlined = true;
2584
            if (!putByIdStatus.isSet()) {
2585
                addToGraph(ForceOSRExit);
2586
                canCountAsInlined = false;
2587
            }
2588
            
2714
            
2589
            if (putByIdStatus.isSimpleReplace()) {
2715
            handlePutById(base, identifierNumber, value, putByIdStatus, direct);
2590
                addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(putByIdStatus.oldStructure())), base);
2591
                handlePutByOffset(base, identifierNumber, putByIdStatus.offset(), value);
2592
            } else if (
2593
                putByIdStatus.isSimpleTransition()
2594
                && (!putByIdStatus.structureChain()
2595
                    || putByIdStatus.structureChain()->isStillValid())) {
2596
                
2597
                m_graph.chains().addLazily(putByIdStatus.structureChain());
2598
                
2599
                addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(putByIdStatus.oldStructure())), base);
2600
                if (!direct) {
2601
                    if (!putByIdStatus.oldStructure()->storedPrototype().isNull()) {
2602
                        cellConstantWithStructureCheck(
2603
                            putByIdStatus.oldStructure()->storedPrototype().asCell());
2604
                    }
2605
                    
2606
                    for (unsigned i = 0; i < putByIdStatus.structureChain()->size(); ++i) {
2607
                        JSValue prototype = putByIdStatus.structureChain()->at(i)->storedPrototype();
2608
                        if (prototype.isNull())
2609
                            continue;
2610
                        cellConstantWithStructureCheck(prototype.asCell());
2611
                    }
2612
                }
2613
                ASSERT(putByIdStatus.oldStructure()->transitionWatchpointSetHasBeenInvalidated());
2614
                
2615
                Node* propertyStorage;
2616
                StructureTransitionData* transitionData =
2617
                    m_graph.addStructureTransitionData(
2618
                        StructureTransitionData(
2619
                            putByIdStatus.oldStructure(),
2620
                            putByIdStatus.newStructure()));
2621
2622
                if (putByIdStatus.oldStructure()->outOfLineCapacity()
2623
                    != putByIdStatus.newStructure()->outOfLineCapacity()) {
2624
                    
2625
                    // If we're growing the property storage then it must be because we're
2626
                    // storing into the out-of-line storage.
2627
                    ASSERT(!isInlineOffset(putByIdStatus.offset()));
2628
                    
2629
                    if (!putByIdStatus.oldStructure()->outOfLineCapacity()) {
2630
                        propertyStorage = addToGraph(
2631
                            AllocatePropertyStorage, OpInfo(transitionData), base);
2632
                    } else {
2633
                        propertyStorage = addToGraph(
2634
                            ReallocatePropertyStorage, OpInfo(transitionData),
2635
                            base, addToGraph(GetButterfly, base));
2636
                    }
2637
                } else {
2638
                    if (isInlineOffset(putByIdStatus.offset()))
2639
                        propertyStorage = base;
2640
                    else
2641
                        propertyStorage = addToGraph(GetButterfly, base);
2642
                }
2643
                
2644
                addToGraph(PutStructure, OpInfo(transitionData), base);
2645
                
2646
                addToGraph(
2647
                    PutByOffset,
2648
                    OpInfo(m_graph.m_storageAccessData.size()),
2649
                    propertyStorage,
2650
                    base,
2651
                    value);
2652
                
2653
                StorageAccessData storageAccessData;
2654
                storageAccessData.offset = putByIdStatus.offset();
2655
                storageAccessData.identifierNumber = identifierNumber;
2656
                m_graph.m_storageAccessData.append(storageAccessData);
2657
            } else {
2658
                if (direct)
2659
                    addToGraph(PutByIdDirect, OpInfo(identifierNumber), base, value);
2660
                else
2661
                    addToGraph(PutById, OpInfo(identifierNumber), base, value);
2662
                canCountAsInlined = false;
2663
            }
2664
            
2665
            if (canCountAsInlined && m_graph.compilation())
2666
                m_graph.compilation()->noticeInlinedPutById();
2667
2668
            NEXT_OPCODE(op_put_by_id);
2716
            NEXT_OPCODE(op_put_by_id);
2669
        }
2717
        }
2670
2718
Lines 3259-3269 bool ByteCodeParser::parseBlock(unsigned Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp_sec7
3259
            case GlobalProperty:
3307
            case GlobalProperty:
3260
            case GlobalPropertyWithVarInjectionChecks: {
3308
            case GlobalPropertyWithVarInjectionChecks: {
3261
                PutByIdStatus status = PutByIdStatus::computeFor(*m_vm, globalObject, structure, uid, false);
3309
                PutByIdStatus status = PutByIdStatus::computeFor(*m_vm, globalObject, structure, uid, false);
3262
                if (!status.isSimpleReplace()) {
3310
                if (status.numVariants() != 1 || status[0].kind() != PutByIdVariant::Replace) {
3263
                    addToGraph(PutById, OpInfo(identifierNumber), get(VirtualRegister(scope)), get(VirtualRegister(value)));
3311
                    addToGraph(PutById, OpInfo(identifierNumber), get(VirtualRegister(scope)), get(VirtualRegister(value)));
3264
                    break;
3312
                    break;
3265
                }
3313
                }
3266
                Node* base = cellConstantWithStructureCheck(globalObject, status.oldStructure());
3314
                Node* base = cellConstantWithStructureCheck(globalObject, status[0].structure());
3267
                addToGraph(Phantom, get(VirtualRegister(scope)));
3315
                addToGraph(Phantom, get(VirtualRegister(scope)));
3268
                handlePutByOffset(base, identifierNumber, static_cast<PropertyOffset>(operand), get(VirtualRegister(value)));
3316
                handlePutByOffset(base, identifierNumber, static_cast<PropertyOffset>(operand), get(VirtualRegister(value)));
3269
                // Keep scope alive until after put.
3317
                // 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 / +200 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
                storage = storageForTransition(
3170
                    base, variant.offset(), variant.oldStructure(), variant.newStructure());
3171
                m_out.storePtr(
3172
                    weakPointer(variant.newStructure()), base, m_heaps.JSCell_structure);
3173
            }
3174
            
3175
            storeProperty(value, storage, data.identifierNumber, variant.offset());
3176
            m_out.jump(continuation);
3177
        }
3178
        
3179
        m_out.appendTo(exit, continuation);
3180
        terminate(BadCache);
3181
        m_out.unreachable();
3182
        
3183
        m_out.appendTo(continuation, lastNext);
3222
    }
3184
    }
3223
    
3185
    
3224
    void compileGetGlobalVar()
3186
    void compileGetGlobalVar()
Lines 3748-3753 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec7
3748
        return m_out.booleanFalse;
3710
        return m_out.booleanFalse;
3749
    }
3711
    }
3750
    
3712
    
3713
    LValue loadProperty(LValue storage, unsigned identifierNumber, PropertyOffset offset)
3714
    {
3715
        return m_out.load64(addressOfProperty(storage, identifierNumber, offset));
3716
    }
3717
    
3718
    void storeProperty(
3719
        LValue value, LValue storage, unsigned identifierNumber, PropertyOffset offset)
3720
    {
3721
        m_out.store64(value, addressOfProperty(storage, identifierNumber, offset));
3722
    }
3723
    
3724
    TypedPointer addressOfProperty(
3725
        LValue storage, unsigned identifierNumber, PropertyOffset offset)
3726
    {
3727
        return m_out.address(
3728
            m_heaps.properties[identifierNumber], storage, offsetRelativeToBase(offset));
3729
    }
3730
    
3731
    LValue storageForTransition(
3732
        LValue object, PropertyOffset offset,
3733
        Structure* previousStructure, Structure* nextStructure)
3734
    {
3735
        if (isInlineOffset(offset))
3736
            return object;
3737
        
3738
        if (previousStructure->outOfLineCapacity() == nextStructure->outOfLineCapacity())
3739
            return m_out.loadPtr(object, m_heaps.JSObject_butterfly);
3740
        
3741
        LValue result;
3742
        if (!previousStructure->outOfLineCapacity())
3743
            result = allocatePropertyStorage(object, previousStructure);
3744
        else {
3745
            result = reallocatePropertyStorage(
3746
                object, m_out.loadPtr(object, m_heaps.JSObject_butterfly),
3747
                previousStructure, nextStructure);
3748
        }
3749
        
3750
        emitStoreBarrier(object);
3751
        
3752
        return result;
3753
    }
3754
    
3755
    LValue allocatePropertyStorage(LValue object, Structure* previousStructure)
3756
    {
3757
        if (previousStructure->couldHaveIndexingHeader()) {
3758
            return vmCall(
3759
                m_out.operation(
3760
                    operationReallocateButterflyToHavePropertyStorageWithInitialCapacity),
3761
                m_callFrame, object);
3762
        }
3763
        
3764
        LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, ("allocatePropertyStorage slow path"));
3765
        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("allocatePropertyStorage continuation"));
3766
        
3767
        LBasicBlock lastNext = m_out.insertNewBlocksBefore(slowPath);
3768
        
3769
        LValue endOfStorage = allocateBasicStorageAndGetEnd(
3770
            m_out.constIntPtr(initialOutOfLineCapacity * sizeof(JSValue)), slowPath);
3771
        
3772
        ValueFromBlock fastButterfly = m_out.anchor(
3773
            m_out.add(m_out.constIntPtr(sizeof(IndexingHeader)), endOfStorage));
3774
        
3775
        m_out.jump(continuation);
3776
        
3777
        m_out.appendTo(slowPath, continuation);
3778
        
3779
        ValueFromBlock slowButterfly = m_out.anchor(vmCall(
3780
            m_out.operation(operationAllocatePropertyStorageWithInitialCapacity), m_callFrame));
3781
        
3782
        m_out.jump(continuation);
3783
        
3784
        m_out.appendTo(continuation, lastNext);
3785
        
3786
        LValue result = m_out.phi(m_out.intPtr, fastButterfly, slowButterfly);
3787
        m_out.storePtr(result, object, m_heaps.JSObject_butterfly);
3788
        
3789
        return result;
3790
    }
3791
    
3792
    LValue reallocatePropertyStorage(
3793
        LValue object, LValue oldStorage, Structure* previous, Structure* next)
3794
    {
3795
        size_t oldSize = previous->outOfLineCapacity() * sizeof(JSValue);
3796
        size_t newSize = oldSize * outOfLineGrowthFactor; 
3797
3798
        ASSERT_UNUSED(next, newSize == next->outOfLineCapacity() * sizeof(JSValue));
3799
        
3800
        if (previous->couldHaveIndexingHeader()) {
3801
            LValue newAllocSize = m_out.constInt64(newSize / sizeof(JSValue));                    
3802
            return vmCall(m_out.operation(operationReallocateButterflyToGrowPropertyStorage), m_callFrame, object, newAllocSize);
3803
        }
3804
        
3805
        LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, ("reallocatePropertyStorage slow path"));
3806
        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("reallocatePropertyStorage continuation"));
3807
        LBasicBlock lastNext = m_out.insertNewBlocksBefore(slowPath);
3808
        
3809
        LValue endOfStorage = 
3810
            allocateBasicStorageAndGetEnd(m_out.constIntPtr(newSize), slowPath);
3811
        
3812
        ValueFromBlock fastButterfly = m_out.anchor(m_out.add(m_out.constIntPtr(sizeof(IndexingHeader)), endOfStorage));
3813
        
3814
        m_out.jump(continuation);
3815
        
3816
        m_out.appendTo(slowPath, continuation);
3817
        
3818
        LValue newAllocSize = m_out.constInt64(newSize / sizeof(JSValue));       
3819
        
3820
        LValue storageLocation = vmCall(m_out.operation(operationAllocatePropertyStorage), m_callFrame, newAllocSize);
3821
        
3822
        ValueFromBlock slowButterfly = m_out.anchor(storageLocation);
3823
        
3824
        m_out.jump(continuation);
3825
        
3826
        m_out.appendTo(continuation, lastNext);
3827
        
3828
        LValue result = m_out.phi(m_out.intPtr, fastButterfly, slowButterfly);
3829
3830
        ptrdiff_t headerSize = -sizeof(JSValue) - sizeof(void *);
3831
        ptrdiff_t endStorage = headerSize - static_cast<ptrdiff_t>(oldSize);
3832
3833
        for (ptrdiff_t offset = headerSize; offset > endStorage; offset -= sizeof(void*)) {
3834
            LValue loaded = 
3835
                m_out.loadPtr(m_out.address(m_heaps.properties.atAnyNumber(), oldStorage, offset));
3836
            m_out.storePtr(loaded, m_out.address(m_heaps.properties.atAnyNumber(), result, offset));
3837
        }
3838
        
3839
        m_out.storePtr(result, m_out.address(object, m_heaps.JSObject_butterfly));
3840
        
3841
        return result;
3842
    }
3843
    
3751
    LValue getById(LValue base)
3844
    LValue getById(LValue base)
3752
    {
3845
    {
3753
        StringImpl* uid = m_graph.identifiers()[m_node->identifierNumber()];
3846
        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()));
5278
        return m_out.load8(m_out.baseIndex(m_heaps.MarkedBlock_markBits, markedBlock, markByteIndex, ScaleOne, MarkedBlock::offsetOfMarks()));
5186
    }
5279
    }
5187
5280
5188
    void emitStoreBarrier(LValue base, LValue value, Edge& valueEdge)
5281
    void emitStoreBarrier(LValue base, LValue value, Edge valueEdge)
5189
    {
5282
    {
5190
#if ENABLE(GGC)
5283
#if ENABLE(GGC)
5191
        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("Store barrier continuation"));
5284
        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
- LayoutTests/ChangeLog +14 lines
Lines 1-3 LayoutTests/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
        Add a microbenchmark for polymorphic PutById.
9
10
        * js/regress/polymorphic-put-by-id-expected.txt: Added.
11
        * js/regress/polymorphic-put-by-id.html: Added.
12
        * js/regress/script-tests/polymorphic-put-by-id.js: Added.
13
        (foo):
14
1
2014-02-23  Dean Jackson  <dino@apple.com>
15
2014-02-23  Dean Jackson  <dino@apple.com>
2
16
3
        [WebGL] Allow ANGLE to initialize unused varyings
17
        [WebGL] Allow ANGLE to initialize unused varyings
- LayoutTests/js/regress/polymorphic-put-by-id-expected.txt +10 lines
Line 0 LayoutTests/js/regress/polymorphic-put-by-id-expected.txt_sec1
1
JSRegress/polymorphic-put-by-id
2
3
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
4
5
6
PASS no exception thrown
7
PASS successfullyParsed is true
8
9
TEST COMPLETE
10
- LayoutTests/js/regress/polymorphic-put-by-id.html +12 lines
Line 0 LayoutTests/js/regress/polymorphic-put-by-id.html_sec1
1
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
2
<html>
3
<head>
4
<script src="../../resources/js-test-pre.js"></script>
5
</head>
6
<body>
7
<script src="resources/regress-pre.js"></script>
8
<script src="script-tests/polymorphic-put-by-id.js"></script>
9
<script src="resources/regress-post.js"></script>
10
<script src="../../resources/js-test-post.js"></script>
11
</body>
12
</html>
- LayoutTests/js/regress/script-tests/polymorphic-put-by-id.js +24 lines
Line 0 LayoutTests/js/regress/script-tests/polymorphic-put-by-id.js_sec1
1
function foo(o) {
2
    for (var i = 0; i < 100; ++i)
3
        o.f = (o.f | 0) + 42;
4
}
5
6
noInline(foo);
7
8
for (var i = 0; i < 10000; ++i) {
9
    var object;
10
    if ((i % 3) == 0)
11
        object = {g:3};
12
    else if ((i % 3) == 1)
13
        object = {f:1, g:2};
14
    else if ((i % 3) == 2)
15
        object = {g:1, f:2};
16
    foo(object);
17
    if (object.f != 42 * 100 + (i % 3))
18
        throw "Error: bad result for i = " + i + ": " + object.f;
19
}
20
21
var r = {g:3, h:4, f:5};
22
foo(r);
23
if (r.f != 5 + 42 * 100)
24
    throw "Error: bad result at end: " + r.f;

Return to Bug 129210