Switch int8_t to GPRReg in StructureStubInfo because sizeof(GPRReg) == sizeof(int8_t)
[WebKit-https.git] / Source / JavaScriptCore / jit / JITInlineCacheGenerator.cpp
1 /*
2  * Copyright (C) 2013-2018 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 "JITInlineCacheGenerator.h"
28
29 #if ENABLE(JIT)
30
31 #include "CodeBlock.h"
32 #include "InlineAccess.h"
33 #include "JSCInlines.h"
34 #include "LinkBuffer.h"
35 #include "StructureStubInfo.h"
36
37 namespace JSC {
38
39 static StructureStubInfo* garbageStubInfo()
40 {
41     static StructureStubInfo* stubInfo = new StructureStubInfo(AccessType::Get);
42     return stubInfo;
43 }
44
45 JITInlineCacheGenerator::JITInlineCacheGenerator(
46     CodeBlock* codeBlock, CodeOrigin codeOrigin, CallSiteIndex callSite, AccessType accessType,
47     const RegisterSet& usedRegisters)
48     : m_codeBlock(codeBlock)
49 {
50     m_stubInfo = m_codeBlock ? m_codeBlock->addStubInfo(accessType) : garbageStubInfo();
51     m_stubInfo->codeOrigin = codeOrigin;
52     m_stubInfo->callSiteIndex = callSite;
53
54     m_stubInfo->patch.usedRegisters = usedRegisters;
55 }
56
57 void JITInlineCacheGenerator::finalize(
58     LinkBuffer& fastPath, LinkBuffer& slowPath, CodeLocationLabel<JITStubRoutinePtrTag> start)
59 {
60     m_stubInfo->patch.start = start;
61
62     int32_t inlineSize = MacroAssembler::differenceBetweenCodePtr(
63         start, fastPath.locationOf<NoPtrTag>(m_done));
64     m_stubInfo->patch.inlineSize = inlineSize;
65
66     m_stubInfo->patch.deltaFromStartToSlowPathCallLocation = MacroAssembler::differenceBetweenCodePtr(
67         start, slowPath.locationOf<NoPtrTag>(m_slowPathCall));
68     m_stubInfo->patch.deltaFromStartToSlowPathStart = MacroAssembler::differenceBetweenCodePtr(
69         start, slowPath.locationOf<NoPtrTag>(m_slowPathBegin));
70 }
71
72 JITByIdGenerator::JITByIdGenerator(
73     CodeBlock* codeBlock, CodeOrigin codeOrigin, CallSiteIndex callSite, AccessType accessType,
74     const RegisterSet& usedRegisters, JSValueRegs base, JSValueRegs value)
75     : JITInlineCacheGenerator(codeBlock, codeOrigin, callSite, accessType, usedRegisters)
76     , m_base(base)
77     , m_value(value)
78 {
79     m_stubInfo->patch.baseGPR = base.payloadGPR();
80     m_stubInfo->patch.valueGPR = value.payloadGPR();
81     m_stubInfo->patch.thisGPR = InvalidGPRReg;
82 #if USE(JSVALUE32_64)
83     m_stubInfo->patch.baseTagGPR = base.tagGPR();
84     m_stubInfo->patch.valueTagGPR = value.tagGPR();
85     m_stubInfo->patch.thisTagGPR = InvalidGPRReg;
86 #endif
87 }
88
89 void JITByIdGenerator::finalize(LinkBuffer& fastPath, LinkBuffer& slowPath)
90 {
91     ASSERT(m_start.isSet());
92     JITInlineCacheGenerator::finalize(
93         fastPath, slowPath, fastPath.locationOf<JITStubRoutinePtrTag>(m_start));
94 }
95
96 void JITByIdGenerator::generateFastCommon(MacroAssembler& jit, size_t inlineICSize)
97 {
98     m_start = jit.label();
99     size_t startSize = jit.m_assembler.buffer().codeSize();
100     m_slowPathJump = jit.jump();
101     size_t jumpSize = jit.m_assembler.buffer().codeSize() - startSize;
102     size_t nopsToEmitInBytes = inlineICSize - jumpSize;
103     jit.emitNops(nopsToEmitInBytes);
104     ASSERT(jit.m_assembler.buffer().codeSize() - startSize == inlineICSize);
105     m_done = jit.label();
106 }
107
108 JITGetByIdGenerator::JITGetByIdGenerator(
109     CodeBlock* codeBlock, CodeOrigin codeOrigin, CallSiteIndex callSite, const RegisterSet& usedRegisters,
110     UniquedStringImpl* propertyName, JSValueRegs base, JSValueRegs value, AccessType accessType)
111     : JITByIdGenerator(codeBlock, codeOrigin, callSite, accessType, usedRegisters, base, value)
112     , m_isLengthAccess(propertyName == codeBlock->vm()->propertyNames->length.impl())
113 {
114     RELEASE_ASSERT(base.payloadGPR() != value.tagGPR());
115 }
116
117 void JITGetByIdGenerator::generateFastPath(MacroAssembler& jit)
118 {
119     generateFastCommon(jit, m_isLengthAccess ? InlineAccess::sizeForLengthAccess() : InlineAccess::sizeForPropertyAccess());
120 }
121
122 JITGetByIdWithThisGenerator::JITGetByIdWithThisGenerator(
123     CodeBlock* codeBlock, CodeOrigin codeOrigin, CallSiteIndex callSite, const RegisterSet& usedRegisters,
124     UniquedStringImpl*, JSValueRegs value, JSValueRegs base, JSValueRegs thisRegs, AccessType accessType)
125     : JITByIdGenerator(codeBlock, codeOrigin, callSite, accessType, usedRegisters, base, value)
126 {
127     RELEASE_ASSERT(thisRegs.payloadGPR() != thisRegs.tagGPR());
128
129     m_stubInfo->patch.thisGPR = thisRegs.payloadGPR();
130 #if USE(JSVALUE32_64)
131     m_stubInfo->patch.thisTagGPR = thisRegs.tagGPR();
132 #endif
133 }
134
135 void JITGetByIdWithThisGenerator::generateFastPath(MacroAssembler& jit)
136 {
137     generateFastCommon(jit, InlineAccess::sizeForPropertyAccess());
138 }
139
140 JITPutByIdGenerator::JITPutByIdGenerator(
141     CodeBlock* codeBlock, CodeOrigin codeOrigin, CallSiteIndex callSite, const RegisterSet& usedRegisters,
142     JSValueRegs base, JSValueRegs value, GPRReg scratch, 
143     ECMAMode ecmaMode, PutKind putKind)
144     : JITByIdGenerator(
145         codeBlock, codeOrigin, callSite, AccessType::Put, usedRegisters, base, value)
146     , m_ecmaMode(ecmaMode)
147     , m_putKind(putKind)
148 {
149     m_stubInfo->patch.usedRegisters.clear(scratch);
150 }
151
152 void JITPutByIdGenerator::generateFastPath(MacroAssembler& jit)
153 {
154     generateFastCommon(jit, InlineAccess::sizeForPropertyReplace());
155 }
156
157 V_JITOperation_ESsiJJI JITPutByIdGenerator::slowPathFunction()
158 {
159     if (m_ecmaMode == StrictMode) {
160         if (m_putKind == Direct)
161             return operationPutByIdDirectStrictOptimize;
162         return operationPutByIdStrictOptimize;
163     }
164     if (m_putKind == Direct)
165         return operationPutByIdDirectNonStrictOptimize;
166     return operationPutByIdNonStrictOptimize;
167 }
168
169 JITInByIdGenerator::JITInByIdGenerator(
170     CodeBlock* codeBlock, CodeOrigin codeOrigin, CallSiteIndex callSite, const RegisterSet& usedRegisters,
171     UniquedStringImpl* propertyName, JSValueRegs base, JSValueRegs value)
172     : JITByIdGenerator(codeBlock, codeOrigin, callSite, AccessType::In, usedRegisters, base, value)
173 {
174     // FIXME: We are not supporting fast path for "length" property.
175     UNUSED_PARAM(propertyName);
176     RELEASE_ASSERT(base.payloadGPR() != value.tagGPR());
177 }
178
179 void JITInByIdGenerator::generateFastPath(MacroAssembler& jit)
180 {
181     generateFastCommon(jit, InlineAccess::sizeForPropertyAccess());
182 }
183
184 JITInstanceOfGenerator::JITInstanceOfGenerator(
185     CodeBlock* codeBlock, CodeOrigin codeOrigin, CallSiteIndex callSiteIndex,
186     const RegisterSet& usedRegisters, GPRReg result, GPRReg value, GPRReg prototype,
187     GPRReg scratch1, GPRReg scratch2, bool prototypeIsKnownObject)
188     : JITInlineCacheGenerator(
189         codeBlock, codeOrigin, callSiteIndex, AccessType::InstanceOf, usedRegisters)
190 {
191     m_stubInfo->patch.baseGPR = value;
192     m_stubInfo->patch.valueGPR = result;
193     m_stubInfo->patch.thisGPR = prototype;
194 #if USE(JSVALUE32_64)
195     m_stubInfo->patch.baseTagGPR = InvalidGPRReg;
196     m_stubInfo->patch.valueTagGPR = InvalidGPRReg;
197     m_stubInfo->patch.thisTagGPR = InvalidGPRReg;
198 #endif
199
200     m_stubInfo->patch.usedRegisters.clear(result);
201     if (scratch1 != InvalidGPRReg)
202         m_stubInfo->patch.usedRegisters.clear(scratch1);
203     if (scratch2 != InvalidGPRReg)
204         m_stubInfo->patch.usedRegisters.clear(scratch2);
205
206     m_stubInfo->prototypeIsKnownObject = prototypeIsKnownObject;
207 }
208
209 void JITInstanceOfGenerator::generateFastPath(MacroAssembler& jit)
210 {
211     m_jump = jit.patchableJump();
212     m_done = jit.label();
213 }
214
215 void JITInstanceOfGenerator::finalize(LinkBuffer& fastPath, LinkBuffer& slowPath)
216 {
217     JITInlineCacheGenerator::finalize(
218         fastPath, slowPath,
219         fastPath.locationOf<JITStubRoutinePtrTag>(m_jump));
220     
221     fastPath.link(m_jump.m_jump, slowPath.locationOf<NoPtrTag>(m_slowPathBegin));
222 }
223
224 } // namespace JSC
225
226 #endif // ENABLE(JIT)
227