2 * Copyright (C) 2011, 2013, 2014 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
27 #include "AssemblyHelpers.h"
31 #include "JITOperations.h"
32 #include "JSCInlines.h"
36 ExecutableBase
* AssemblyHelpers::executableFor(const CodeOrigin
& codeOrigin
)
38 if (!codeOrigin
.inlineCallFrame
)
39 return m_codeBlock
->ownerExecutable();
41 return codeOrigin
.inlineCallFrame
->executable
.get();
44 Vector
<BytecodeAndMachineOffset
>& AssemblyHelpers::decodedCodeMapFor(CodeBlock
* codeBlock
)
46 ASSERT(codeBlock
== codeBlock
->baselineVersion());
47 ASSERT(codeBlock
->jitType() == JITCode::BaselineJIT
);
48 ASSERT(codeBlock
->jitCodeMap());
50 HashMap
<CodeBlock
*, Vector
<BytecodeAndMachineOffset
>>::AddResult result
= m_decodedCodeMaps
.add(codeBlock
, Vector
<BytecodeAndMachineOffset
>());
52 if (result
.isNewEntry
)
53 codeBlock
->jitCodeMap()->decode(result
.iterator
->value
);
55 return result
.iterator
->value
;
58 void AssemblyHelpers::purifyNaN(FPRReg fpr
)
60 MacroAssembler::Jump notNaN
= branchDouble(DoubleEqual
, fpr
, fpr
);
61 static const double NaN
= PNaN
;
62 loadDouble(TrustedImmPtr(&NaN
), fpr
);
66 #if ENABLE(SAMPLING_FLAGS)
67 void AssemblyHelpers::setSamplingFlag(int32_t flag
)
71 or32(TrustedImm32(1u << (flag
- 1)), AbsoluteAddress(SamplingFlags::addressOfFlags()));
74 void AssemblyHelpers::clearSamplingFlag(int32_t flag
)
78 and32(TrustedImm32(~(1u << (flag
- 1))), AbsoluteAddress(SamplingFlags::addressOfFlags()));
84 void AssemblyHelpers::jitAssertIsInt32(GPRReg gpr
)
87 Jump checkInt32
= branch64(BelowOrEqual
, gpr
, TrustedImm64(static_cast<uintptr_t>(0xFFFFFFFFu
)));
88 abortWithReason(AHIsNotInt32
);
89 checkInt32
.link(this);
95 void AssemblyHelpers::jitAssertIsJSInt32(GPRReg gpr
)
97 Jump checkJSInt32
= branch64(AboveOrEqual
, gpr
, GPRInfo::tagTypeNumberRegister
);
98 abortWithReason(AHIsNotJSInt32
);
99 checkJSInt32
.link(this);
102 void AssemblyHelpers::jitAssertIsJSNumber(GPRReg gpr
)
104 Jump checkJSNumber
= branchTest64(MacroAssembler::NonZero
, gpr
, GPRInfo::tagTypeNumberRegister
);
105 abortWithReason(AHIsNotJSNumber
);
106 checkJSNumber
.link(this);
109 void AssemblyHelpers::jitAssertIsJSDouble(GPRReg gpr
)
111 Jump checkJSInt32
= branch64(AboveOrEqual
, gpr
, GPRInfo::tagTypeNumberRegister
);
112 Jump checkJSNumber
= branchTest64(MacroAssembler::NonZero
, gpr
, GPRInfo::tagTypeNumberRegister
);
113 checkJSInt32
.link(this);
114 abortWithReason(AHIsNotJSDouble
);
115 checkJSNumber
.link(this);
118 void AssemblyHelpers::jitAssertIsCell(GPRReg gpr
)
120 Jump checkCell
= branchTest64(MacroAssembler::Zero
, gpr
, GPRInfo::tagMaskRegister
);
121 abortWithReason(AHIsNotCell
);
122 checkCell
.link(this);
125 void AssemblyHelpers::jitAssertTagsInPlace()
127 Jump ok
= branch64(Equal
, GPRInfo::tagTypeNumberRegister
, TrustedImm64(TagTypeNumber
));
128 abortWithReason(AHTagTypeNumberNotInPlace
);
132 ok
= branch64(Equal
, GPRInfo::tagMaskRegister
, TrustedImm64(TagMask
));
133 abortWithReason(AHTagMaskNotInPlace
);
136 #elif USE(JSVALUE32_64)
137 void AssemblyHelpers::jitAssertIsInt32(GPRReg gpr
)
142 void AssemblyHelpers::jitAssertIsJSInt32(GPRReg gpr
)
144 Jump checkJSInt32
= branch32(Equal
, gpr
, TrustedImm32(JSValue::Int32Tag
));
145 abortWithReason(AHIsNotJSInt32
);
146 checkJSInt32
.link(this);
149 void AssemblyHelpers::jitAssertIsJSNumber(GPRReg gpr
)
151 Jump checkJSInt32
= branch32(Equal
, gpr
, TrustedImm32(JSValue::Int32Tag
));
152 Jump checkJSDouble
= branch32(Below
, gpr
, TrustedImm32(JSValue::LowestTag
));
153 abortWithReason(AHIsNotJSNumber
);
154 checkJSInt32
.link(this);
155 checkJSDouble
.link(this);
158 void AssemblyHelpers::jitAssertIsJSDouble(GPRReg gpr
)
160 Jump checkJSDouble
= branch32(Below
, gpr
, TrustedImm32(JSValue::LowestTag
));
161 abortWithReason(AHIsNotJSDouble
);
162 checkJSDouble
.link(this);
165 void AssemblyHelpers::jitAssertIsCell(GPRReg gpr
)
167 Jump checkCell
= branch32(Equal
, gpr
, TrustedImm32(JSValue::CellTag
));
168 abortWithReason(AHIsNotCell
);
169 checkCell
.link(this);
172 void AssemblyHelpers::jitAssertTagsInPlace()
175 #endif // USE(JSVALUE32_64)
177 void AssemblyHelpers::jitAssertHasValidCallFrame()
179 Jump checkCFR
= branchTestPtr(Zero
, GPRInfo::callFrameRegister
, TrustedImm32(7));
180 abortWithReason(AHCallFrameMisaligned
);
184 void AssemblyHelpers::jitAssertIsNull(GPRReg gpr
)
186 Jump checkNull
= branchTestPtr(Zero
, gpr
);
187 abortWithReason(AHIsNotNull
);
188 checkNull
.link(this);
191 void AssemblyHelpers::jitAssertArgumentCountSane()
193 Jump ok
= branch32(Below
, payloadFor(JSStack::ArgumentCount
), TrustedImm32(10000000));
194 abortWithReason(AHInsaneArgumentCount
);
197 #endif // !ASSERT_DISABLED
199 void AssemblyHelpers::callExceptionFuzz()
201 if (!Options::enableExceptionFuzz())
204 ASSERT(stackAlignmentBytes() >= sizeof(void*) * 2);
205 subPtr(TrustedImm32(stackAlignmentBytes()), stackPointerRegister
);
206 poke(GPRInfo::returnValueGPR
, 0);
207 poke(GPRInfo::returnValueGPR2
, 1);
208 move(TrustedImmPtr(bitwise_cast
<void*>(operationExceptionFuzz
)), GPRInfo::nonPreservedNonReturnGPR
);
209 call(GPRInfo::nonPreservedNonReturnGPR
);
210 peek(GPRInfo::returnValueGPR
, 0);
211 peek(GPRInfo::returnValueGPR2
, 1);
212 addPtr(TrustedImm32(stackAlignmentBytes()), stackPointerRegister
);
215 AssemblyHelpers::Jump
AssemblyHelpers::emitExceptionCheck(ExceptionCheckKind kind
)
220 return branchTest64(kind
== NormalExceptionCheck
? NonZero
: Zero
, AbsoluteAddress(vm()->addressOfException()));
221 #elif USE(JSVALUE32_64)
222 return branch32(kind
== NormalExceptionCheck
? NotEqual
: Equal
, AbsoluteAddress(reinterpret_cast<char*>(vm()->addressOfException()) + OBJECT_OFFSETOF(JSValue
, u
.asBits
.tag
)), TrustedImm32(JSValue::EmptyValueTag
));
226 void AssemblyHelpers::emitStoreStructureWithTypeInfo(AssemblyHelpers
& jit
, TrustedImmPtr structure
, RegisterID dest
)
228 const Structure
* structurePtr
= static_cast<const Structure
*>(structure
.m_value
);
230 jit
.store64(TrustedImm64(structurePtr
->idBlob()), MacroAssembler::Address(dest
, JSCell::structureIDOffset()));
231 if (!ASSERT_DISABLED
) {
232 Jump correctStructure
= jit
.branch32(Equal
, MacroAssembler::Address(dest
, JSCell::structureIDOffset()), TrustedImm32(structurePtr
->id()));
233 jit
.abortWithReason(AHStructureIDIsValid
);
234 correctStructure
.link(&jit
);
236 Jump correctIndexingType
= jit
.branch8(Equal
, MacroAssembler::Address(dest
, JSCell::indexingTypeOffset()), TrustedImm32(structurePtr
->indexingType()));
237 jit
.abortWithReason(AHIndexingTypeIsValid
);
238 correctIndexingType
.link(&jit
);
240 Jump correctType
= jit
.branch8(Equal
, MacroAssembler::Address(dest
, JSCell::typeInfoTypeOffset()), TrustedImm32(structurePtr
->typeInfo().type()));
241 jit
.abortWithReason(AHTypeInfoIsValid
);
242 correctType
.link(&jit
);
244 Jump correctFlags
= jit
.branch8(Equal
, MacroAssembler::Address(dest
, JSCell::typeInfoFlagsOffset()), TrustedImm32(structurePtr
->typeInfo().inlineTypeFlags()));
245 jit
.abortWithReason(AHTypeInfoInlineTypeFlagsAreValid
);
246 correctFlags
.link(&jit
);
249 // Do a 32-bit wide store to initialize the cell's fields.
250 jit
.store32(TrustedImm32(structurePtr
->objectInitializationBlob()), MacroAssembler::Address(dest
, JSCell::indexingTypeOffset()));
251 jit
.storePtr(structure
, MacroAssembler::Address(dest
, JSCell::structureIDOffset()));
257 #endif // ENABLE(JIT)