blob: 2d2b4e13d4803bd061082781d8a3b8ce1cecd6bf [file] [log] [blame]
fpizlo@apple.com62fcee02011-11-08 05:48:09 +00001/*
fpizlo@apple.comf75c0a962016-04-07 18:38:15 +00002 * Copyright (C) 2011, 2013-2016 Apple Inc. All rights reserved.
fpizlo@apple.com62fcee02011-11-08 05:48:09 +00003 *
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"
fpizlo@apple.comcd8eb2c2013-09-20 18:42:41 +000027#include "AssemblyHelpers.h"
fpizlo@apple.com62fcee02011-11-08 05:48:09 +000028
fpizlo@apple.comcd8eb2c2013-09-20 18:42:41 +000029#if ENABLE(JIT)
fpizlo@apple.com62fcee02011-11-08 05:48:09 +000030
fpizlo@apple.com9f1dad42014-07-18 04:34:16 +000031#include "JITOperations.h"
fpizlo@apple.comfb7eff22014-02-11 01:45:50 +000032#include "JSCInlines.h"
fpizlo@apple.comb426f862014-02-10 02:51:13 +000033
fpizlo@apple.comcd8eb2c2013-09-20 18:42:41 +000034namespace JSC {
fpizlo@apple.com62fcee02011-11-08 05:48:09 +000035
fpizlo@apple.com9b928722012-05-24 00:18:55 +000036ExecutableBase* AssemblyHelpers::executableFor(const CodeOrigin& codeOrigin)
37{
38 if (!codeOrigin.inlineCallFrame)
39 return m_codeBlock->ownerExecutable();
40
ggaren@apple.com81def5f2015-10-09 23:10:16 +000041 return codeOrigin.inlineCallFrame->baselineCodeBlock->ownerExecutable();
fpizlo@apple.com9b928722012-05-24 00:18:55 +000042}
43
fpizlo@apple.com62fcee02011-11-08 05:48:09 +000044Vector<BytecodeAndMachineOffset>& AssemblyHelpers::decodedCodeMapFor(CodeBlock* codeBlock)
45{
46 ASSERT(codeBlock == codeBlock->baselineVersion());
oliver@apple.com5a24fdd2013-07-25 04:00:54 +000047 ASSERT(codeBlock->jitType() == JITCode::BaselineJIT);
fpizlo@apple.com62fcee02011-11-08 05:48:09 +000048 ASSERT(codeBlock->jitCodeMap());
49
andersca@apple.comc3523f82013-10-18 23:41:24 +000050 HashMap<CodeBlock*, Vector<BytecodeAndMachineOffset>>::AddResult result = m_decodedCodeMaps.add(codeBlock, Vector<BytecodeAndMachineOffset>());
fpizlo@apple.com62fcee02011-11-08 05:48:09 +000051
caio.oliveira@openbossa.org4c11ee02012-03-29 18:48:23 +000052 if (result.isNewEntry)
benjamin@webkit.orgee554052012-10-07 23:12:07 +000053 codeBlock->jitCodeMap()->decode(result.iterator->value);
fpizlo@apple.com62fcee02011-11-08 05:48:09 +000054
benjamin@webkit.orgee554052012-10-07 23:12:07 +000055 return result.iterator->value;
fpizlo@apple.com62fcee02011-11-08 05:48:09 +000056}
57
fpizlo@apple.com12835772015-09-21 20:49:04 +000058AssemblyHelpers::JumpList AssemblyHelpers::branchIfNotType(
59 JSValueRegs regs, GPRReg tempGPR, const InferredType::Descriptor& descriptor, TagRegistersMode mode)
60{
61 AssemblyHelpers::JumpList result;
62
63 switch (descriptor.kind()) {
64 case InferredType::Bottom:
65 result.append(jump());
66 break;
67
68 case InferredType::Boolean:
69 result.append(branchIfNotBoolean(regs, tempGPR));
70 break;
71
72 case InferredType::Other:
73 result.append(branchIfNotOther(regs, tempGPR));
74 break;
75
76 case InferredType::Int32:
77 result.append(branchIfNotInt32(regs, mode));
78 break;
79
80 case InferredType::Number:
81 result.append(branchIfNotNumber(regs, tempGPR, mode));
82 break;
83
84 case InferredType::String:
85 result.append(branchIfNotCell(regs, mode));
86 result.append(branchIfNotString(regs.payloadGPR()));
87 break;
88
utatane.tea@gmail.com618381f2015-10-13 02:09:34 +000089 case InferredType::Symbol:
90 result.append(branchIfNotCell(regs, mode));
91 result.append(branchIfNotSymbol(regs.payloadGPR()));
92 break;
93
fpizlo@apple.com12835772015-09-21 20:49:04 +000094 case InferredType::ObjectWithStructure:
95 result.append(branchIfNotCell(regs, mode));
96 result.append(
97 branchStructure(
98 NotEqual,
99 Address(regs.payloadGPR(), JSCell::structureIDOffset()),
100 descriptor.structure()));
101 break;
102
103 case InferredType::ObjectWithStructureOrOther: {
104 Jump ok = branchIfOther(regs, tempGPR);
105 result.append(branchIfNotCell(regs, mode));
106 result.append(
107 branchStructure(
108 NotEqual,
109 Address(regs.payloadGPR(), JSCell::structureIDOffset()),
110 descriptor.structure()));
111 ok.link(this);
112 break;
113 }
114
115 case InferredType::Object:
116 result.append(branchIfNotCell(regs, mode));
117 result.append(branchIfNotObject(regs.payloadGPR()));
118 break;
119
120 case InferredType::ObjectOrOther: {
121 Jump ok = branchIfOther(regs, tempGPR);
122 result.append(branchIfNotCell(regs, mode));
123 result.append(branchIfNotObject(regs.payloadGPR()));
124 ok.link(this);
125 break;
126 }
127
128 case InferredType::Top:
129 break;
130 }
131
132 return result;
133}
134
fpizlo@apple.com1e158382015-10-16 22:53:11 +0000135AssemblyHelpers::Jump AssemblyHelpers::branchIfFastTypedArray(GPRReg baseGPR)
136{
137 return branch32(
138 Equal,
139 Address(baseGPR, JSArrayBufferView::offsetOfMode()),
140 TrustedImm32(FastTypedArray));
141}
142
143AssemblyHelpers::Jump AssemblyHelpers::branchIfNotFastTypedArray(GPRReg baseGPR)
144{
145 return branch32(
146 NotEqual,
147 Address(baseGPR, JSArrayBufferView::offsetOfMode()),
148 TrustedImm32(FastTypedArray));
149}
150
fpizlo@apple.com5e29b762016-03-18 00:53:24 +0000151void AssemblyHelpers::incrementSuperSamplerCount()
152{
153 add32(TrustedImm32(1), AbsoluteAddress(bitwise_cast<const void*>(&g_superSamplerCount)));
154}
155
156void AssemblyHelpers::decrementSuperSamplerCount()
157{
158 sub32(TrustedImm32(1), AbsoluteAddress(bitwise_cast<const void*>(&g_superSamplerCount)));
159}
160
fpizlo@apple.combeef4522014-04-16 22:44:00 +0000161void AssemblyHelpers::purifyNaN(FPRReg fpr)
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000162{
163 MacroAssembler::Jump notNaN = branchDouble(DoubleEqual, fpr, fpr);
fpizlo@apple.combeef4522014-04-16 22:44:00 +0000164 static const double NaN = PNaN;
commit-queue@webkit.org918d9852014-05-13 20:57:07 +0000165 loadDouble(TrustedImmPtr(&NaN), fpr);
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000166 notNaN.link(this);
167}
168
fpizlo@apple.com62fcee02011-11-08 05:48:09 +0000169#if ENABLE(SAMPLING_FLAGS)
170void AssemblyHelpers::setSamplingFlag(int32_t flag)
171{
172 ASSERT(flag >= 1);
173 ASSERT(flag <= 32);
174 or32(TrustedImm32(1u << (flag - 1)), AbsoluteAddress(SamplingFlags::addressOfFlags()));
175}
176
177void AssemblyHelpers::clearSamplingFlag(int32_t flag)
178{
179 ASSERT(flag >= 1);
180 ASSERT(flag <= 32);
181 and32(TrustedImm32(~(1u << (flag - 1))), AbsoluteAddress(SamplingFlags::addressOfFlags()));
182}
183#endif
184
fpizlo@apple.comcd8eb2c2013-09-20 18:42:41 +0000185#if !ASSERT_DISABLED
fpizlo@apple.com62fcee02011-11-08 05:48:09 +0000186#if USE(JSVALUE64)
187void AssemblyHelpers::jitAssertIsInt32(GPRReg gpr)
188{
189#if CPU(X86_64)
yuqiang.xian@intel.com5b1cb732012-10-19 05:46:10 +0000190 Jump checkInt32 = branch64(BelowOrEqual, gpr, TrustedImm64(static_cast<uintptr_t>(0xFFFFFFFFu)));
fpizlo@apple.comfac5bed2014-05-14 03:57:18 +0000191 abortWithReason(AHIsNotInt32);
fpizlo@apple.com62fcee02011-11-08 05:48:09 +0000192 checkInt32.link(this);
193#else
194 UNUSED_PARAM(gpr);
195#endif
196}
197
198void AssemblyHelpers::jitAssertIsJSInt32(GPRReg gpr)
199{
yuqiang.xian@intel.com5b1cb732012-10-19 05:46:10 +0000200 Jump checkJSInt32 = branch64(AboveOrEqual, gpr, GPRInfo::tagTypeNumberRegister);
fpizlo@apple.comfac5bed2014-05-14 03:57:18 +0000201 abortWithReason(AHIsNotJSInt32);
fpizlo@apple.com62fcee02011-11-08 05:48:09 +0000202 checkJSInt32.link(this);
203}
204
205void AssemblyHelpers::jitAssertIsJSNumber(GPRReg gpr)
206{
yuqiang.xian@intel.com5b1cb732012-10-19 05:46:10 +0000207 Jump checkJSNumber = branchTest64(MacroAssembler::NonZero, gpr, GPRInfo::tagTypeNumberRegister);
fpizlo@apple.comfac5bed2014-05-14 03:57:18 +0000208 abortWithReason(AHIsNotJSNumber);
fpizlo@apple.com62fcee02011-11-08 05:48:09 +0000209 checkJSNumber.link(this);
210}
211
212void AssemblyHelpers::jitAssertIsJSDouble(GPRReg gpr)
213{
yuqiang.xian@intel.com5b1cb732012-10-19 05:46:10 +0000214 Jump checkJSInt32 = branch64(AboveOrEqual, gpr, GPRInfo::tagTypeNumberRegister);
215 Jump checkJSNumber = branchTest64(MacroAssembler::NonZero, gpr, GPRInfo::tagTypeNumberRegister);
fpizlo@apple.com62fcee02011-11-08 05:48:09 +0000216 checkJSInt32.link(this);
fpizlo@apple.comfac5bed2014-05-14 03:57:18 +0000217 abortWithReason(AHIsNotJSDouble);
fpizlo@apple.com62fcee02011-11-08 05:48:09 +0000218 checkJSNumber.link(this);
219}
220
221void AssemblyHelpers::jitAssertIsCell(GPRReg gpr)
222{
yuqiang.xian@intel.com5b1cb732012-10-19 05:46:10 +0000223 Jump checkCell = branchTest64(MacroAssembler::Zero, gpr, GPRInfo::tagMaskRegister);
fpizlo@apple.comfac5bed2014-05-14 03:57:18 +0000224 abortWithReason(AHIsNotCell);
fpizlo@apple.com62fcee02011-11-08 05:48:09 +0000225 checkCell.link(this);
226}
msaboff@apple.com95894332014-01-29 19:18:54 +0000227
228void AssemblyHelpers::jitAssertTagsInPlace()
229{
230 Jump ok = branch64(Equal, GPRInfo::tagTypeNumberRegister, TrustedImm64(TagTypeNumber));
fpizlo@apple.comfac5bed2014-05-14 03:57:18 +0000231 abortWithReason(AHTagTypeNumberNotInPlace);
msaboff@apple.com95894332014-01-29 19:18:54 +0000232 breakpoint();
233 ok.link(this);
234
235 ok = branch64(Equal, GPRInfo::tagMaskRegister, TrustedImm64(TagMask));
fpizlo@apple.comfac5bed2014-05-14 03:57:18 +0000236 abortWithReason(AHTagMaskNotInPlace);
msaboff@apple.com95894332014-01-29 19:18:54 +0000237 ok.link(this);
238}
fpizlo@apple.com62fcee02011-11-08 05:48:09 +0000239#elif USE(JSVALUE32_64)
240void AssemblyHelpers::jitAssertIsInt32(GPRReg gpr)
241{
242 UNUSED_PARAM(gpr);
243}
244
245void AssemblyHelpers::jitAssertIsJSInt32(GPRReg gpr)
246{
247 Jump checkJSInt32 = branch32(Equal, gpr, TrustedImm32(JSValue::Int32Tag));
fpizlo@apple.comfac5bed2014-05-14 03:57:18 +0000248 abortWithReason(AHIsNotJSInt32);
fpizlo@apple.com62fcee02011-11-08 05:48:09 +0000249 checkJSInt32.link(this);
250}
251
252void AssemblyHelpers::jitAssertIsJSNumber(GPRReg gpr)
253{
254 Jump checkJSInt32 = branch32(Equal, gpr, TrustedImm32(JSValue::Int32Tag));
255 Jump checkJSDouble = branch32(Below, gpr, TrustedImm32(JSValue::LowestTag));
fpizlo@apple.comfac5bed2014-05-14 03:57:18 +0000256 abortWithReason(AHIsNotJSNumber);
fpizlo@apple.com62fcee02011-11-08 05:48:09 +0000257 checkJSInt32.link(this);
258 checkJSDouble.link(this);
259}
260
261void AssemblyHelpers::jitAssertIsJSDouble(GPRReg gpr)
262{
263 Jump checkJSDouble = branch32(Below, gpr, TrustedImm32(JSValue::LowestTag));
fpizlo@apple.comfac5bed2014-05-14 03:57:18 +0000264 abortWithReason(AHIsNotJSDouble);
fpizlo@apple.com62fcee02011-11-08 05:48:09 +0000265 checkJSDouble.link(this);
266}
267
268void AssemblyHelpers::jitAssertIsCell(GPRReg gpr)
269{
270 Jump checkCell = branch32(Equal, gpr, TrustedImm32(JSValue::CellTag));
fpizlo@apple.comfac5bed2014-05-14 03:57:18 +0000271 abortWithReason(AHIsNotCell);
fpizlo@apple.com62fcee02011-11-08 05:48:09 +0000272 checkCell.link(this);
273}
msaboff@apple.com95894332014-01-29 19:18:54 +0000274
275void AssemblyHelpers::jitAssertTagsInPlace()
276{
277}
fpizlo@apple.com62fcee02011-11-08 05:48:09 +0000278#endif // USE(JSVALUE32_64)
fpizlo@apple.com8fd61d92012-04-19 21:55:00 +0000279
280void AssemblyHelpers::jitAssertHasValidCallFrame()
281{
282 Jump checkCFR = branchTestPtr(Zero, GPRInfo::callFrameRegister, TrustedImm32(7));
fpizlo@apple.comfac5bed2014-05-14 03:57:18 +0000283 abortWithReason(AHCallFrameMisaligned);
fpizlo@apple.com8fd61d92012-04-19 21:55:00 +0000284 checkCFR.link(this);
285}
msaboff@apple.com5ca16c42013-10-07 18:20:27 +0000286
287void AssemblyHelpers::jitAssertIsNull(GPRReg gpr)
288{
289 Jump checkNull = branchTestPtr(Zero, gpr);
fpizlo@apple.comfac5bed2014-05-14 03:57:18 +0000290 abortWithReason(AHIsNotNull);
msaboff@apple.com5ca16c42013-10-07 18:20:27 +0000291 checkNull.link(this);
292}
msaboff@apple.com95894332014-01-29 19:18:54 +0000293
294void AssemblyHelpers::jitAssertArgumentCountSane()
295{
296 Jump ok = branch32(Below, payloadFor(JSStack::ArgumentCount), TrustedImm32(10000000));
fpizlo@apple.comfac5bed2014-05-14 03:57:18 +0000297 abortWithReason(AHInsaneArgumentCount);
msaboff@apple.com95894332014-01-29 19:18:54 +0000298 ok.link(this);
299}
saambarati1@gmail.comaa599f62015-08-21 19:11:36 +0000300
keith_miller@apple.comc7704742015-12-04 18:45:43 +0000301#endif // !ASSERT_DISABLED
302
303void AssemblyHelpers::jitReleaseAssertNoException()
saambarati1@gmail.comaa599f62015-08-21 19:11:36 +0000304{
305 Jump noException;
306#if USE(JSVALUE64)
307 noException = branchTest64(Zero, AbsoluteAddress(vm()->addressOfException()));
308#elif USE(JSVALUE32_64)
309 noException = branch32(Equal, AbsoluteAddress(vm()->addressOfException()), TrustedImm32(0));
310#endif
311 abortWithReason(JITUncoughtExceptionAfterCall);
312 noException.link(this);
313}
314
fpizlo@apple.com9f1dad42014-07-18 04:34:16 +0000315void AssemblyHelpers::callExceptionFuzz()
316{
mark.lam@apple.comee3c4102015-10-14 18:57:07 +0000317 if (!Options::useExceptionFuzz())
fpizlo@apple.com9f1dad42014-07-18 04:34:16 +0000318 return;
319
saambarati1@gmail.comaa599f62015-08-21 19:11:36 +0000320 EncodedJSValue* buffer = vm()->exceptionFuzzingBuffer(sizeof(EncodedJSValue) * (GPRInfo::numberOfRegisters + FPRInfo::numberOfRegisters));
321
322 for (unsigned i = 0; i < GPRInfo::numberOfRegisters; ++i) {
323#if USE(JSVALUE64)
324 store64(GPRInfo::toRegister(i), buffer + i);
325#else
326 store32(GPRInfo::toRegister(i), buffer + i);
327#endif
328 }
329 for (unsigned i = 0; i < FPRInfo::numberOfRegisters; ++i) {
330 move(TrustedImmPtr(buffer + GPRInfo::numberOfRegisters + i), GPRInfo::regT0);
331 storeDouble(FPRInfo::toRegister(i), Address(GPRInfo::regT0));
332 }
333
334 // Set up one argument.
335#if CPU(X86)
336 poke(GPRInfo::callFrameRegister, 0);
337#else
338 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
339#endif
fpizlo@apple.com9f1dad42014-07-18 04:34:16 +0000340 move(TrustedImmPtr(bitwise_cast<void*>(operationExceptionFuzz)), GPRInfo::nonPreservedNonReturnGPR);
341 call(GPRInfo::nonPreservedNonReturnGPR);
saambarati1@gmail.comaa599f62015-08-21 19:11:36 +0000342
343 for (unsigned i = 0; i < FPRInfo::numberOfRegisters; ++i) {
344 move(TrustedImmPtr(buffer + GPRInfo::numberOfRegisters + i), GPRInfo::regT0);
345 loadDouble(Address(GPRInfo::regT0), FPRInfo::toRegister(i));
346 }
347 for (unsigned i = 0; i < GPRInfo::numberOfRegisters; ++i) {
348#if USE(JSVALUE64)
349 load64(buffer + i, GPRInfo::toRegister(i));
350#else
351 load32(buffer + i, GPRInfo::toRegister(i));
352#endif
353 }
fpizlo@apple.com9f1dad42014-07-18 04:34:16 +0000354}
355
fpizlo@apple.com8fefdd32015-02-18 19:55:47 +0000356AssemblyHelpers::Jump AssemblyHelpers::emitExceptionCheck(ExceptionCheckKind kind, ExceptionJumpWidth width)
fpizlo@apple.com9f1dad42014-07-18 04:34:16 +0000357{
358 callExceptionFuzz();
fpizlo@apple.com8fefdd32015-02-18 19:55:47 +0000359
360 if (width == FarJumpWidth)
361 kind = (kind == NormalExceptionCheck ? InvertedExceptionCheck : NormalExceptionCheck);
fpizlo@apple.com9f1dad42014-07-18 04:34:16 +0000362
fpizlo@apple.com8fefdd32015-02-18 19:55:47 +0000363 Jump result;
fpizlo@apple.com9f1dad42014-07-18 04:34:16 +0000364#if USE(JSVALUE64)
fpizlo@apple.com8fefdd32015-02-18 19:55:47 +0000365 result = branchTest64(kind == NormalExceptionCheck ? NonZero : Zero, AbsoluteAddress(vm()->addressOfException()));
fpizlo@apple.com9f1dad42014-07-18 04:34:16 +0000366#elif USE(JSVALUE32_64)
mark.lam@apple.com6ed08272015-06-05 18:52:12 +0000367 result = branch32(kind == NormalExceptionCheck ? NotEqual : Equal, AbsoluteAddress(vm()->addressOfException()), TrustedImm32(0));
fpizlo@apple.com9f1dad42014-07-18 04:34:16 +0000368#endif
fpizlo@apple.com8fefdd32015-02-18 19:55:47 +0000369
370 if (width == NormalJumpWidth)
371 return result;
msaboff@apple.comcdd479b2015-09-30 22:28:08 +0000372
fpizlo@apple.com8fefdd32015-02-18 19:55:47 +0000373 PatchableJump realJump = patchableJump();
374 result.link(this);
375
376 return realJump.m_jump;
fpizlo@apple.com9f1dad42014-07-18 04:34:16 +0000377}
378
sbarati@apple.com36c13402015-09-18 23:37:42 +0000379AssemblyHelpers::Jump AssemblyHelpers::emitNonPatchableExceptionCheck()
380{
381 callExceptionFuzz();
382
383 Jump result;
384#if USE(JSVALUE64)
385 result = branchTest64(NonZero, AbsoluteAddress(vm()->addressOfException()));
386#elif USE(JSVALUE32_64)
387 result = branch32(NotEqual, AbsoluteAddress(vm()->addressOfException()), TrustedImm32(0));
388#endif
389
390 return result;
391}
392
fpizlo@apple.comfac5bed2014-05-14 03:57:18 +0000393void AssemblyHelpers::emitStoreStructureWithTypeInfo(AssemblyHelpers& jit, TrustedImmPtr structure, RegisterID dest)
394{
395 const Structure* structurePtr = static_cast<const Structure*>(structure.m_value);
396#if USE(JSVALUE64)
397 jit.store64(TrustedImm64(structurePtr->idBlob()), MacroAssembler::Address(dest, JSCell::structureIDOffset()));
398 if (!ASSERT_DISABLED) {
399 Jump correctStructure = jit.branch32(Equal, MacroAssembler::Address(dest, JSCell::structureIDOffset()), TrustedImm32(structurePtr->id()));
400 jit.abortWithReason(AHStructureIDIsValid);
401 correctStructure.link(&jit);
402
403 Jump correctIndexingType = jit.branch8(Equal, MacroAssembler::Address(dest, JSCell::indexingTypeOffset()), TrustedImm32(structurePtr->indexingType()));
404 jit.abortWithReason(AHIndexingTypeIsValid);
405 correctIndexingType.link(&jit);
406
407 Jump correctType = jit.branch8(Equal, MacroAssembler::Address(dest, JSCell::typeInfoTypeOffset()), TrustedImm32(structurePtr->typeInfo().type()));
408 jit.abortWithReason(AHTypeInfoIsValid);
409 correctType.link(&jit);
410
411 Jump correctFlags = jit.branch8(Equal, MacroAssembler::Address(dest, JSCell::typeInfoFlagsOffset()), TrustedImm32(structurePtr->typeInfo().inlineTypeFlags()));
412 jit.abortWithReason(AHTypeInfoInlineTypeFlagsAreValid);
413 correctFlags.link(&jit);
414 }
415#else
416 // Do a 32-bit wide store to initialize the cell's fields.
417 jit.store32(TrustedImm32(structurePtr->objectInitializationBlob()), MacroAssembler::Address(dest, JSCell::indexingTypeOffset()));
418 jit.storePtr(structure, MacroAssembler::Address(dest, JSCell::structureIDOffset()));
419#endif
420}
421
fpizlo@apple.com80d06562016-04-05 19:58:04 +0000422void AssemblyHelpers::loadProperty(GPRReg object, GPRReg offset, JSValueRegs result)
423{
424 Jump isInline = branch32(LessThan, offset, TrustedImm32(firstOutOfLineOffset));
425
426 loadPtr(Address(object, JSObject::butterflyOffset()), result.payloadGPR());
427 neg32(offset);
428 signExtend32ToPtr(offset, offset);
429 Jump ready = jump();
430
431 isInline.link(this);
432 addPtr(
433 TrustedImm32(
434 static_cast<int32_t>(sizeof(JSObject)) -
435 (static_cast<int32_t>(firstOutOfLineOffset) - 2) * static_cast<int32_t>(sizeof(EncodedJSValue))),
436 object, result.payloadGPR());
437
438 ready.link(this);
439
440 loadValue(
441 BaseIndex(
442 result.payloadGPR(), offset, TimesEight, (firstOutOfLineOffset - 2) * sizeof(EncodedJSValue)),
443 result);
444}
445
446void AssemblyHelpers::emitLoadStructure(RegisterID source, RegisterID dest, RegisterID scratch)
447{
448#if USE(JSVALUE64)
449 load32(MacroAssembler::Address(source, JSCell::structureIDOffset()), dest);
450 loadPtr(vm()->heap.structureIDTable().base(), scratch);
451 loadPtr(MacroAssembler::BaseIndex(scratch, dest, MacroAssembler::TimesEight), dest);
452#else
453 UNUSED_PARAM(scratch);
454 loadPtr(MacroAssembler::Address(source, JSCell::structureIDOffset()), dest);
455#endif
456}
457
fpizlo@apple.comf75c0a962016-04-07 18:38:15 +0000458void AssemblyHelpers::makeSpaceOnStackForCCall()
459{
460 unsigned stackOffset = WTF::roundUpToMultipleOf(stackAlignmentBytes(), maxFrameExtentForSlowPathCall);
461 if (stackOffset)
462 subPtr(TrustedImm32(stackOffset), stackPointerRegister);
463}
464
465void AssemblyHelpers::reclaimSpaceOnStackForCCall()
466{
467 unsigned stackOffset = WTF::roundUpToMultipleOf(stackAlignmentBytes(), maxFrameExtentForSlowPathCall);
468 if (stackOffset)
469 addPtr(TrustedImm32(stackOffset), stackPointerRegister);
470}
471
utatane.tea@gmail.comd2fca0a2015-12-15 03:51:42 +0000472#if USE(JSVALUE64)
473template<typename LoadFromHigh, typename StoreToHigh, typename LoadFromLow, typename StoreToLow>
474void emitRandomThunkImpl(AssemblyHelpers& jit, GPRReg scratch0, GPRReg scratch1, GPRReg scratch2, FPRReg result, const LoadFromHigh& loadFromHigh, const StoreToHigh& storeToHigh, const LoadFromLow& loadFromLow, const StoreToLow& storeToLow)
475{
476 // Inlined WeakRandom::advance().
477 // uint64_t x = m_low;
478 loadFromLow(scratch0);
479 // uint64_t y = m_high;
480 loadFromHigh(scratch1);
481 // m_low = y;
482 storeToLow(scratch1);
483
484 // x ^= x << 23;
485 jit.move(scratch0, scratch2);
486 jit.lshift64(AssemblyHelpers::TrustedImm32(23), scratch2);
487 jit.xor64(scratch2, scratch0);
488
489 // x ^= x >> 17;
490 jit.move(scratch0, scratch2);
491 jit.rshift64(AssemblyHelpers::TrustedImm32(17), scratch2);
492 jit.xor64(scratch2, scratch0);
493
494 // x ^= y ^ (y >> 26);
495 jit.move(scratch1, scratch2);
496 jit.rshift64(AssemblyHelpers::TrustedImm32(26), scratch2);
497 jit.xor64(scratch1, scratch2);
498 jit.xor64(scratch2, scratch0);
499
500 // m_high = x;
501 storeToHigh(scratch0);
502
503 // return x + y;
504 jit.add64(scratch1, scratch0);
505
506 // Extract random 53bit. [0, 53] bit is safe integer number ranges in double representation.
507 jit.move(AssemblyHelpers::TrustedImm64((1ULL << 53) - 1), scratch1);
508 jit.and64(scratch1, scratch0);
509 // Now, scratch0 is always in range of int64_t. Safe to convert it to double with cvtsi2sdq.
510 jit.convertInt64ToDouble(scratch0, result);
511
512 // Convert `(53bit double integer value) / (1 << 53)` to `(53bit double integer value) * (1.0 / (1 << 53))`.
513 // In latter case, `1.0 / (1 << 53)` will become a double value represented as (mantissa = 0 & exp = 970, it means 1e-(2**54)).
514 static const double scale = 1.0 / (1ULL << 53);
515
516 // Multiplying 1e-(2**54) with the double integer does not change anything of the mantissa part of the double integer.
517 // It just reduces the exp part of the given 53bit double integer.
518 // (Except for 0.0. This is specially handled and in this case, exp just becomes 0.)
519 // Now we get 53bit precision random double value in [0, 1).
520 jit.move(AssemblyHelpers::TrustedImmPtr(&scale), scratch1);
521 jit.mulDouble(AssemblyHelpers::Address(scratch1), result);
522}
523
524void AssemblyHelpers::emitRandomThunk(JSGlobalObject* globalObject, GPRReg scratch0, GPRReg scratch1, GPRReg scratch2, FPRReg result)
525{
526 void* lowAddress = reinterpret_cast<uint8_t*>(globalObject) + JSGlobalObject::weakRandomOffset() + WeakRandom::lowOffset();
527 void* highAddress = reinterpret_cast<uint8_t*>(globalObject) + JSGlobalObject::weakRandomOffset() + WeakRandom::highOffset();
528
529 auto loadFromHigh = [&](GPRReg high) {
530 load64(highAddress, high);
531 };
532 auto storeToHigh = [&](GPRReg high) {
533 store64(high, highAddress);
534 };
535 auto loadFromLow = [&](GPRReg low) {
536 load64(lowAddress, low);
537 };
538 auto storeToLow = [&](GPRReg low) {
539 store64(low, lowAddress);
540 };
541
542 emitRandomThunkImpl(*this, scratch0, scratch1, scratch2, result, loadFromHigh, storeToHigh, loadFromLow, storeToLow);
543}
544
545void AssemblyHelpers::emitRandomThunk(GPRReg scratch0, GPRReg scratch1, GPRReg scratch2, GPRReg scratch3, FPRReg result)
546{
547 emitGetFromCallFrameHeaderPtr(JSStack::Callee, scratch3);
548 emitLoadStructure(scratch3, scratch3, scratch0);
549 loadPtr(Address(scratch3, Structure::globalObjectOffset()), scratch3);
550 // Now, scratch3 holds JSGlobalObject*.
551
552 auto loadFromHigh = [&](GPRReg high) {
553 load64(Address(scratch3, JSGlobalObject::weakRandomOffset() + WeakRandom::highOffset()), high);
554 };
555 auto storeToHigh = [&](GPRReg high) {
556 store64(high, Address(scratch3, JSGlobalObject::weakRandomOffset() + WeakRandom::highOffset()));
557 };
558 auto loadFromLow = [&](GPRReg low) {
559 load64(Address(scratch3, JSGlobalObject::weakRandomOffset() + WeakRandom::lowOffset()), low);
560 };
561 auto storeToLow = [&](GPRReg low) {
562 store64(low, Address(scratch3, JSGlobalObject::weakRandomOffset() + WeakRandom::lowOffset()));
563 };
564
565 emitRandomThunkImpl(*this, scratch0, scratch1, scratch2, result, loadFromHigh, storeToHigh, loadFromLow, storeToLow);
566}
567#endif
568
mark.lam@apple.com491c2f52016-05-13 20:16:29 +0000569void AssemblyHelpers::restoreCalleeSavesFromVMEntryFrameCalleeSavesBuffer()
sbarati@apple.com8e20f432016-01-08 18:49:26 +0000570{
571#if NUMBER_OF_CALLEE_SAVES_REGISTERS > 0
sbarati@apple.com8e20f432016-01-08 18:49:26 +0000572 RegisterAtOffsetList* allCalleeSaves = m_vm->getAllCalleeSaveRegisterOffsets();
573 RegisterSet dontRestoreRegisters = RegisterSet::stackRegisters();
574 unsigned registerCount = allCalleeSaves->size();
mark.lam@apple.com491c2f52016-05-13 20:16:29 +0000575
576 GPRReg scratch = InvalidGPRReg;
577 unsigned scratchGPREntryIndex = 0;
578
579 // Use the first GPR entry's register as our scratch.
sbarati@apple.com8e20f432016-01-08 18:49:26 +0000580 for (unsigned i = 0; i < registerCount; i++) {
581 RegisterAtOffset entry = allCalleeSaves->at(i);
582 if (dontRestoreRegisters.get(entry.reg()))
583 continue;
mark.lam@apple.com491c2f52016-05-13 20:16:29 +0000584 if (entry.reg().isGPR()) {
585 scratchGPREntryIndex = i;
586 scratch = entry.reg().gpr();
587 break;
588 }
sbarati@apple.com8e20f432016-01-08 18:49:26 +0000589 }
mark.lam@apple.com491c2f52016-05-13 20:16:29 +0000590 ASSERT(scratch != InvalidGPRReg);
591
592 loadPtr(&m_vm->topVMEntryFrame, scratch);
593 addPtr(TrustedImm32(VMEntryFrame::calleeSaveRegistersBufferOffset()), scratch);
594
595 // Restore all callee saves except for the scratch.
596 for (unsigned i = 0; i < registerCount; i++) {
597 RegisterAtOffset entry = allCalleeSaves->at(i);
598 if (dontRestoreRegisters.get(entry.reg()))
599 continue;
600 if (entry.reg().isGPR()) {
601 if (i != scratchGPREntryIndex)
602 loadPtr(Address(scratch, entry.offset()), entry.reg().gpr());
603 } else
604 loadDouble(Address(scratch, entry.offset()), entry.reg().fpr());
605 }
606
607 // Restore the callee save value of the scratch.
608 RegisterAtOffset entry = allCalleeSaves->at(scratchGPREntryIndex);
609 ASSERT(!dontRestoreRegisters.get(entry.reg()));
610 ASSERT(entry.reg().isGPR());
611 ASSERT(scratch == entry.reg().gpr());
612 loadPtr(Address(scratch, entry.offset()), scratch);
sbarati@apple.com8e20f432016-01-08 18:49:26 +0000613#endif
614}
615
fpizlo@apple.comcd8eb2c2013-09-20 18:42:41 +0000616} // namespace JSC
fpizlo@apple.com62fcee02011-11-08 05:48:09 +0000617
fpizlo@apple.comcd8eb2c2013-09-20 18:42:41 +0000618#endif // ENABLE(JIT)
fpizlo@apple.com62fcee02011-11-08 05:48:09 +0000619