X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/4be4e30906bcb8ee30b4d189205cb70bad6707ce..81345200c95645a1b0d2635520f96ad55dfde63f:/jit/AssemblyHelpers.cpp diff --git a/jit/AssemblyHelpers.cpp b/jit/AssemblyHelpers.cpp new file mode 100644 index 0000000..059e5d9 --- /dev/null +++ b/jit/AssemblyHelpers.cpp @@ -0,0 +1,258 @@ +/* + * Copyright (C) 2011, 2013, 2014 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "AssemblyHelpers.h" + +#if ENABLE(JIT) + +#include "JITOperations.h" +#include "JSCInlines.h" + +namespace JSC { + +ExecutableBase* AssemblyHelpers::executableFor(const CodeOrigin& codeOrigin) +{ + if (!codeOrigin.inlineCallFrame) + return m_codeBlock->ownerExecutable(); + + return codeOrigin.inlineCallFrame->executable.get(); +} + +Vector& AssemblyHelpers::decodedCodeMapFor(CodeBlock* codeBlock) +{ + ASSERT(codeBlock == codeBlock->baselineVersion()); + ASSERT(codeBlock->jitType() == JITCode::BaselineJIT); + ASSERT(codeBlock->jitCodeMap()); + + HashMap>::AddResult result = m_decodedCodeMaps.add(codeBlock, Vector()); + + if (result.isNewEntry) + codeBlock->jitCodeMap()->decode(result.iterator->value); + + return result.iterator->value; +} + +void AssemblyHelpers::purifyNaN(FPRReg fpr) +{ + MacroAssembler::Jump notNaN = branchDouble(DoubleEqual, fpr, fpr); + static const double NaN = PNaN; + loadDouble(TrustedImmPtr(&NaN), fpr); + notNaN.link(this); +} + +#if ENABLE(SAMPLING_FLAGS) +void AssemblyHelpers::setSamplingFlag(int32_t flag) +{ + ASSERT(flag >= 1); + ASSERT(flag <= 32); + or32(TrustedImm32(1u << (flag - 1)), AbsoluteAddress(SamplingFlags::addressOfFlags())); +} + +void AssemblyHelpers::clearSamplingFlag(int32_t flag) +{ + ASSERT(flag >= 1); + ASSERT(flag <= 32); + and32(TrustedImm32(~(1u << (flag - 1))), AbsoluteAddress(SamplingFlags::addressOfFlags())); +} +#endif + +#if !ASSERT_DISABLED +#if USE(JSVALUE64) +void AssemblyHelpers::jitAssertIsInt32(GPRReg gpr) +{ +#if CPU(X86_64) + Jump checkInt32 = branch64(BelowOrEqual, gpr, TrustedImm64(static_cast(0xFFFFFFFFu))); + abortWithReason(AHIsNotInt32); + checkInt32.link(this); +#else + UNUSED_PARAM(gpr); +#endif +} + +void AssemblyHelpers::jitAssertIsJSInt32(GPRReg gpr) +{ + Jump checkJSInt32 = branch64(AboveOrEqual, gpr, GPRInfo::tagTypeNumberRegister); + abortWithReason(AHIsNotJSInt32); + checkJSInt32.link(this); +} + +void AssemblyHelpers::jitAssertIsJSNumber(GPRReg gpr) +{ + Jump checkJSNumber = branchTest64(MacroAssembler::NonZero, gpr, GPRInfo::tagTypeNumberRegister); + abortWithReason(AHIsNotJSNumber); + checkJSNumber.link(this); +} + +void AssemblyHelpers::jitAssertIsJSDouble(GPRReg gpr) +{ + Jump checkJSInt32 = branch64(AboveOrEqual, gpr, GPRInfo::tagTypeNumberRegister); + Jump checkJSNumber = branchTest64(MacroAssembler::NonZero, gpr, GPRInfo::tagTypeNumberRegister); + checkJSInt32.link(this); + abortWithReason(AHIsNotJSDouble); + checkJSNumber.link(this); +} + +void AssemblyHelpers::jitAssertIsCell(GPRReg gpr) +{ + Jump checkCell = branchTest64(MacroAssembler::Zero, gpr, GPRInfo::tagMaskRegister); + abortWithReason(AHIsNotCell); + checkCell.link(this); +} + +void AssemblyHelpers::jitAssertTagsInPlace() +{ + Jump ok = branch64(Equal, GPRInfo::tagTypeNumberRegister, TrustedImm64(TagTypeNumber)); + abortWithReason(AHTagTypeNumberNotInPlace); + breakpoint(); + ok.link(this); + + ok = branch64(Equal, GPRInfo::tagMaskRegister, TrustedImm64(TagMask)); + abortWithReason(AHTagMaskNotInPlace); + ok.link(this); +} +#elif USE(JSVALUE32_64) +void AssemblyHelpers::jitAssertIsInt32(GPRReg gpr) +{ + UNUSED_PARAM(gpr); +} + +void AssemblyHelpers::jitAssertIsJSInt32(GPRReg gpr) +{ + Jump checkJSInt32 = branch32(Equal, gpr, TrustedImm32(JSValue::Int32Tag)); + abortWithReason(AHIsNotJSInt32); + checkJSInt32.link(this); +} + +void AssemblyHelpers::jitAssertIsJSNumber(GPRReg gpr) +{ + Jump checkJSInt32 = branch32(Equal, gpr, TrustedImm32(JSValue::Int32Tag)); + Jump checkJSDouble = branch32(Below, gpr, TrustedImm32(JSValue::LowestTag)); + abortWithReason(AHIsNotJSNumber); + checkJSInt32.link(this); + checkJSDouble.link(this); +} + +void AssemblyHelpers::jitAssertIsJSDouble(GPRReg gpr) +{ + Jump checkJSDouble = branch32(Below, gpr, TrustedImm32(JSValue::LowestTag)); + abortWithReason(AHIsNotJSDouble); + checkJSDouble.link(this); +} + +void AssemblyHelpers::jitAssertIsCell(GPRReg gpr) +{ + Jump checkCell = branch32(Equal, gpr, TrustedImm32(JSValue::CellTag)); + abortWithReason(AHIsNotCell); + checkCell.link(this); +} + +void AssemblyHelpers::jitAssertTagsInPlace() +{ +} +#endif // USE(JSVALUE32_64) + +void AssemblyHelpers::jitAssertHasValidCallFrame() +{ + Jump checkCFR = branchTestPtr(Zero, GPRInfo::callFrameRegister, TrustedImm32(7)); + abortWithReason(AHCallFrameMisaligned); + checkCFR.link(this); +} + +void AssemblyHelpers::jitAssertIsNull(GPRReg gpr) +{ + Jump checkNull = branchTestPtr(Zero, gpr); + abortWithReason(AHIsNotNull); + checkNull.link(this); +} + +void AssemblyHelpers::jitAssertArgumentCountSane() +{ + Jump ok = branch32(Below, payloadFor(JSStack::ArgumentCount), TrustedImm32(10000000)); + abortWithReason(AHInsaneArgumentCount); + ok.link(this); +} +#endif // !ASSERT_DISABLED + +void AssemblyHelpers::callExceptionFuzz() +{ + if (!Options::enableExceptionFuzz()) + return; + + ASSERT(stackAlignmentBytes() >= sizeof(void*) * 2); + subPtr(TrustedImm32(stackAlignmentBytes()), stackPointerRegister); + poke(GPRInfo::returnValueGPR, 0); + poke(GPRInfo::returnValueGPR2, 1); + move(TrustedImmPtr(bitwise_cast(operationExceptionFuzz)), GPRInfo::nonPreservedNonReturnGPR); + call(GPRInfo::nonPreservedNonReturnGPR); + peek(GPRInfo::returnValueGPR, 0); + peek(GPRInfo::returnValueGPR2, 1); + addPtr(TrustedImm32(stackAlignmentBytes()), stackPointerRegister); +} + +AssemblyHelpers::Jump AssemblyHelpers::emitExceptionCheck(ExceptionCheckKind kind) +{ + callExceptionFuzz(); + +#if USE(JSVALUE64) + return branchTest64(kind == NormalExceptionCheck ? NonZero : Zero, AbsoluteAddress(vm()->addressOfException())); +#elif USE(JSVALUE32_64) + return branch32(kind == NormalExceptionCheck ? NotEqual : Equal, AbsoluteAddress(reinterpret_cast(vm()->addressOfException()) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), TrustedImm32(JSValue::EmptyValueTag)); +#endif +} + +void AssemblyHelpers::emitStoreStructureWithTypeInfo(AssemblyHelpers& jit, TrustedImmPtr structure, RegisterID dest) +{ + const Structure* structurePtr = static_cast(structure.m_value); +#if USE(JSVALUE64) + jit.store64(TrustedImm64(structurePtr->idBlob()), MacroAssembler::Address(dest, JSCell::structureIDOffset())); + if (!ASSERT_DISABLED) { + Jump correctStructure = jit.branch32(Equal, MacroAssembler::Address(dest, JSCell::structureIDOffset()), TrustedImm32(structurePtr->id())); + jit.abortWithReason(AHStructureIDIsValid); + correctStructure.link(&jit); + + Jump correctIndexingType = jit.branch8(Equal, MacroAssembler::Address(dest, JSCell::indexingTypeOffset()), TrustedImm32(structurePtr->indexingType())); + jit.abortWithReason(AHIndexingTypeIsValid); + correctIndexingType.link(&jit); + + Jump correctType = jit.branch8(Equal, MacroAssembler::Address(dest, JSCell::typeInfoTypeOffset()), TrustedImm32(structurePtr->typeInfo().type())); + jit.abortWithReason(AHTypeInfoIsValid); + correctType.link(&jit); + + Jump correctFlags = jit.branch8(Equal, MacroAssembler::Address(dest, JSCell::typeInfoFlagsOffset()), TrustedImm32(structurePtr->typeInfo().inlineTypeFlags())); + jit.abortWithReason(AHTypeInfoInlineTypeFlagsAreValid); + correctFlags.link(&jit); + } +#else + // Do a 32-bit wide store to initialize the cell's fields. + jit.store32(TrustedImm32(structurePtr->objectInitializationBlob()), MacroAssembler::Address(dest, JSCell::indexingTypeOffset())); + jit.storePtr(structure, MacroAssembler::Address(dest, JSCell::structureIDOffset())); +#endif +} + +} // namespace JSC + +#endif // ENABLE(JIT) +