diff options
Diffstat (limited to 'Source/JavaScriptCore/jit/AssemblyHelpers.cpp')
-rw-r--r-- | Source/JavaScriptCore/jit/AssemblyHelpers.cpp | 402 |
1 files changed, 13 insertions, 389 deletions
diff --git a/Source/JavaScriptCore/jit/AssemblyHelpers.cpp b/Source/JavaScriptCore/jit/AssemblyHelpers.cpp index c1be5932c..ddf1d6359 100644 --- a/Source/JavaScriptCore/jit/AssemblyHelpers.cpp +++ b/Source/JavaScriptCore/jit/AssemblyHelpers.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011, 2013-2015 Apple Inc. All rights reserved. + * Copyright (C) 2011, 2013 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -28,9 +28,6 @@ #if ENABLE(JIT) -#include "JITOperations.h" -#include "JSCInlines.h" - namespace JSC { ExecutableBase* AssemblyHelpers::executableFor(const CodeOrigin& codeOrigin) @@ -38,7 +35,7 @@ ExecutableBase* AssemblyHelpers::executableFor(const CodeOrigin& codeOrigin) if (!codeOrigin.inlineCallFrame) return m_codeBlock->ownerExecutable(); - return codeOrigin.inlineCallFrame->baselineCodeBlock->ownerExecutable(); + return codeOrigin.inlineCallFrame->executable.get(); } Vector<BytecodeAndMachineOffset>& AssemblyHelpers::decodedCodeMapFor(CodeBlock* codeBlock) @@ -55,118 +52,6 @@ Vector<BytecodeAndMachineOffset>& AssemblyHelpers::decodedCodeMapFor(CodeBlock* return result.iterator->value; } -AssemblyHelpers::JumpList AssemblyHelpers::branchIfNotType( - JSValueRegs regs, GPRReg tempGPR, const InferredType::Descriptor& descriptor, TagRegistersMode mode) -{ - AssemblyHelpers::JumpList result; - - switch (descriptor.kind()) { - case InferredType::Bottom: - result.append(jump()); - break; - - case InferredType::Boolean: - result.append(branchIfNotBoolean(regs, tempGPR)); - break; - - case InferredType::Other: - result.append(branchIfNotOther(regs, tempGPR)); - break; - - case InferredType::Int32: - result.append(branchIfNotInt32(regs, mode)); - break; - - case InferredType::Number: - result.append(branchIfNotNumber(regs, tempGPR, mode)); - break; - - case InferredType::String: - result.append(branchIfNotCell(regs, mode)); - result.append(branchIfNotString(regs.payloadGPR())); - break; - - case InferredType::Symbol: - result.append(branchIfNotCell(regs, mode)); - result.append(branchIfNotSymbol(regs.payloadGPR())); - break; - - case InferredType::ObjectWithStructure: - result.append(branchIfNotCell(regs, mode)); - result.append( - branchStructure( - NotEqual, - Address(regs.payloadGPR(), JSCell::structureIDOffset()), - descriptor.structure())); - break; - - case InferredType::ObjectWithStructureOrOther: { - Jump ok = branchIfOther(regs, tempGPR); - result.append(branchIfNotCell(regs, mode)); - result.append( - branchStructure( - NotEqual, - Address(regs.payloadGPR(), JSCell::structureIDOffset()), - descriptor.structure())); - ok.link(this); - break; - } - - case InferredType::Object: - result.append(branchIfNotCell(regs, mode)); - result.append(branchIfNotObject(regs.payloadGPR())); - break; - - case InferredType::ObjectOrOther: { - Jump ok = branchIfOther(regs, tempGPR); - result.append(branchIfNotCell(regs, mode)); - result.append(branchIfNotObject(regs.payloadGPR())); - ok.link(this); - break; - } - - case InferredType::Top: - break; - } - - return result; -} - -AssemblyHelpers::Jump AssemblyHelpers::branchIfFastTypedArray(GPRReg baseGPR) -{ - return branch32( - Equal, - Address(baseGPR, JSArrayBufferView::offsetOfMode()), - TrustedImm32(FastTypedArray)); -} - -AssemblyHelpers::Jump AssemblyHelpers::branchIfNotFastTypedArray(GPRReg baseGPR) -{ - return branch32( - NotEqual, - Address(baseGPR, JSArrayBufferView::offsetOfMode()), - TrustedImm32(FastTypedArray)); -} - -AssemblyHelpers::Jump AssemblyHelpers::loadTypedArrayVector(GPRReg baseGPR, GPRReg resultGPR) -{ - RELEASE_ASSERT(baseGPR != resultGPR); - - loadPtr(Address(baseGPR, JSArrayBufferView::offsetOfVector()), resultGPR); - Jump ok = branchIfToSpace(resultGPR); - Jump result = branchIfFastTypedArray(baseGPR); - ok.link(this); - return result; -} - -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) { @@ -189,7 +74,7 @@ void AssemblyHelpers::jitAssertIsInt32(GPRReg gpr) { #if CPU(X86_64) Jump checkInt32 = branch64(BelowOrEqual, gpr, TrustedImm64(static_cast<uintptr_t>(0xFFFFFFFFu))); - abortWithReason(AHIsNotInt32); + breakpoint(); checkInt32.link(this); #else UNUSED_PARAM(gpr); @@ -199,14 +84,14 @@ void AssemblyHelpers::jitAssertIsInt32(GPRReg gpr) void AssemblyHelpers::jitAssertIsJSInt32(GPRReg gpr) { Jump checkJSInt32 = branch64(AboveOrEqual, gpr, GPRInfo::tagTypeNumberRegister); - abortWithReason(AHIsNotJSInt32); + breakpoint(); checkJSInt32.link(this); } void AssemblyHelpers::jitAssertIsJSNumber(GPRReg gpr) { Jump checkJSNumber = branchTest64(MacroAssembler::NonZero, gpr, GPRInfo::tagTypeNumberRegister); - abortWithReason(AHIsNotJSNumber); + breakpoint(); checkJSNumber.link(this); } @@ -215,27 +100,15 @@ 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); + breakpoint(); 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); + checkCell.link(this); } #elif USE(JSVALUE32_64) void AssemblyHelpers::jitAssertIsInt32(GPRReg gpr) @@ -246,7 +119,7 @@ void AssemblyHelpers::jitAssertIsInt32(GPRReg gpr) void AssemblyHelpers::jitAssertIsJSInt32(GPRReg gpr) { Jump checkJSInt32 = branch32(Equal, gpr, TrustedImm32(JSValue::Int32Tag)); - abortWithReason(AHIsNotJSInt32); + breakpoint(); checkJSInt32.link(this); } @@ -254,7 +127,7 @@ void AssemblyHelpers::jitAssertIsJSNumber(GPRReg gpr) { Jump checkJSInt32 = branch32(Equal, gpr, TrustedImm32(JSValue::Int32Tag)); Jump checkJSDouble = branch32(Below, gpr, TrustedImm32(JSValue::LowestTag)); - abortWithReason(AHIsNotJSNumber); + breakpoint(); checkJSInt32.link(this); checkJSDouble.link(this); } @@ -262,282 +135,33 @@ void AssemblyHelpers::jitAssertIsJSNumber(GPRReg gpr) void AssemblyHelpers::jitAssertIsJSDouble(GPRReg gpr) { Jump checkJSDouble = branch32(Below, gpr, TrustedImm32(JSValue::LowestTag)); - abortWithReason(AHIsNotJSDouble); + breakpoint(); checkJSDouble.link(this); } void AssemblyHelpers::jitAssertIsCell(GPRReg gpr) { Jump checkCell = branch32(Equal, gpr, TrustedImm32(JSValue::CellTag)); - abortWithReason(AHIsNotCell); + breakpoint(); checkCell.link(this); } - -void AssemblyHelpers::jitAssertTagsInPlace() -{ -} #endif // USE(JSVALUE32_64) void AssemblyHelpers::jitAssertHasValidCallFrame() { Jump checkCFR = branchTestPtr(Zero, GPRInfo::callFrameRegister, TrustedImm32(7)); - abortWithReason(AHCallFrameMisaligned); + breakpoint(); checkCFR.link(this); } void AssemblyHelpers::jitAssertIsNull(GPRReg gpr) { Jump checkNull = branchTestPtr(Zero, gpr); - abortWithReason(AHIsNotNull); + breakpoint(); 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::jitReleaseAssertNoException() -{ - Jump noException; -#if USE(JSVALUE64) - noException = branchTest64(Zero, AbsoluteAddress(vm()->addressOfException())); -#elif USE(JSVALUE32_64) - noException = branch32(Equal, AbsoluteAddress(vm()->addressOfException()), TrustedImm32(0)); -#endif - abortWithReason(JITUncoughtExceptionAfterCall); - noException.link(this); -} - -void AssemblyHelpers::callExceptionFuzz() -{ - if (!Options::useExceptionFuzz()) - return; - - EncodedJSValue* buffer = vm()->exceptionFuzzingBuffer(sizeof(EncodedJSValue) * (GPRInfo::numberOfRegisters + FPRInfo::numberOfRegisters)); - - for (unsigned i = 0; i < GPRInfo::numberOfRegisters; ++i) { -#if USE(JSVALUE64) - store64(GPRInfo::toRegister(i), buffer + i); -#else - store32(GPRInfo::toRegister(i), buffer + i); -#endif - } - for (unsigned i = 0; i < FPRInfo::numberOfRegisters; ++i) { - move(TrustedImmPtr(buffer + GPRInfo::numberOfRegisters + i), GPRInfo::regT0); - storeDouble(FPRInfo::toRegister(i), Address(GPRInfo::regT0)); - } - - // Set up one argument. -#if CPU(X86) - poke(GPRInfo::callFrameRegister, 0); -#else - move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); -#endif - move(TrustedImmPtr(bitwise_cast<void*>(operationExceptionFuzz)), GPRInfo::nonPreservedNonReturnGPR); - call(GPRInfo::nonPreservedNonReturnGPR); - - for (unsigned i = 0; i < FPRInfo::numberOfRegisters; ++i) { - move(TrustedImmPtr(buffer + GPRInfo::numberOfRegisters + i), GPRInfo::regT0); - loadDouble(Address(GPRInfo::regT0), FPRInfo::toRegister(i)); - } - for (unsigned i = 0; i < GPRInfo::numberOfRegisters; ++i) { -#if USE(JSVALUE64) - load64(buffer + i, GPRInfo::toRegister(i)); -#else - load32(buffer + i, GPRInfo::toRegister(i)); -#endif - } -} - -AssemblyHelpers::Jump AssemblyHelpers::emitExceptionCheck(ExceptionCheckKind kind, ExceptionJumpWidth width) -{ - callExceptionFuzz(); - - if (width == FarJumpWidth) - kind = (kind == NormalExceptionCheck ? InvertedExceptionCheck : NormalExceptionCheck); - - Jump result; -#if USE(JSVALUE64) - result = branchTest64(kind == NormalExceptionCheck ? NonZero : Zero, AbsoluteAddress(vm()->addressOfException())); -#elif USE(JSVALUE32_64) - result = branch32(kind == NormalExceptionCheck ? NotEqual : Equal, AbsoluteAddress(vm()->addressOfException()), TrustedImm32(0)); -#endif - - if (width == NormalJumpWidth) - return result; - - PatchableJump realJump = patchableJump(); - result.link(this); - - return realJump.m_jump; -} - -AssemblyHelpers::Jump AssemblyHelpers::emitNonPatchableExceptionCheck() -{ - callExceptionFuzz(); - - Jump result; -#if USE(JSVALUE64) - result = branchTest64(NonZero, AbsoluteAddress(vm()->addressOfException())); -#elif USE(JSVALUE32_64) - result = branch32(NotEqual, AbsoluteAddress(vm()->addressOfException()), TrustedImm32(0)); -#endif - - return result; -} - -void AssemblyHelpers::emitStoreStructureWithTypeInfo(AssemblyHelpers& jit, TrustedImmPtr structure, RegisterID dest) -{ - const Structure* structurePtr = static_cast<const Structure*>(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 -} - -#if USE(JSVALUE64) -template<typename LoadFromHigh, typename StoreToHigh, typename LoadFromLow, typename StoreToLow> -void emitRandomThunkImpl(AssemblyHelpers& jit, GPRReg scratch0, GPRReg scratch1, GPRReg scratch2, FPRReg result, const LoadFromHigh& loadFromHigh, const StoreToHigh& storeToHigh, const LoadFromLow& loadFromLow, const StoreToLow& storeToLow) -{ - // Inlined WeakRandom::advance(). - // uint64_t x = m_low; - loadFromLow(scratch0); - // uint64_t y = m_high; - loadFromHigh(scratch1); - // m_low = y; - storeToLow(scratch1); - - // x ^= x << 23; - jit.move(scratch0, scratch2); - jit.lshift64(AssemblyHelpers::TrustedImm32(23), scratch2); - jit.xor64(scratch2, scratch0); - - // x ^= x >> 17; - jit.move(scratch0, scratch2); - jit.rshift64(AssemblyHelpers::TrustedImm32(17), scratch2); - jit.xor64(scratch2, scratch0); - - // x ^= y ^ (y >> 26); - jit.move(scratch1, scratch2); - jit.rshift64(AssemblyHelpers::TrustedImm32(26), scratch2); - jit.xor64(scratch1, scratch2); - jit.xor64(scratch2, scratch0); - - // m_high = x; - storeToHigh(scratch0); - - // return x + y; - jit.add64(scratch1, scratch0); - - // Extract random 53bit. [0, 53] bit is safe integer number ranges in double representation. - jit.move(AssemblyHelpers::TrustedImm64((1ULL << 53) - 1), scratch1); - jit.and64(scratch1, scratch0); - // Now, scratch0 is always in range of int64_t. Safe to convert it to double with cvtsi2sdq. - jit.convertInt64ToDouble(scratch0, result); - - // Convert `(53bit double integer value) / (1 << 53)` to `(53bit double integer value) * (1.0 / (1 << 53))`. - // In latter case, `1.0 / (1 << 53)` will become a double value represented as (mantissa = 0 & exp = 970, it means 1e-(2**54)). - static const double scale = 1.0 / (1ULL << 53); - - // Multiplying 1e-(2**54) with the double integer does not change anything of the mantissa part of the double integer. - // It just reduces the exp part of the given 53bit double integer. - // (Except for 0.0. This is specially handled and in this case, exp just becomes 0.) - // Now we get 53bit precision random double value in [0, 1). - jit.move(AssemblyHelpers::TrustedImmPtr(&scale), scratch1); - jit.mulDouble(AssemblyHelpers::Address(scratch1), result); -} - -void AssemblyHelpers::emitRandomThunk(JSGlobalObject* globalObject, GPRReg scratch0, GPRReg scratch1, GPRReg scratch2, FPRReg result) -{ - void* lowAddress = reinterpret_cast<uint8_t*>(globalObject) + JSGlobalObject::weakRandomOffset() + WeakRandom::lowOffset(); - void* highAddress = reinterpret_cast<uint8_t*>(globalObject) + JSGlobalObject::weakRandomOffset() + WeakRandom::highOffset(); - - auto loadFromHigh = [&](GPRReg high) { - load64(highAddress, high); - }; - auto storeToHigh = [&](GPRReg high) { - store64(high, highAddress); - }; - auto loadFromLow = [&](GPRReg low) { - load64(lowAddress, low); - }; - auto storeToLow = [&](GPRReg low) { - store64(low, lowAddress); - }; - - emitRandomThunkImpl(*this, scratch0, scratch1, scratch2, result, loadFromHigh, storeToHigh, loadFromLow, storeToLow); -} - -void AssemblyHelpers::emitRandomThunk(GPRReg scratch0, GPRReg scratch1, GPRReg scratch2, GPRReg scratch3, FPRReg result) -{ - emitGetFromCallFrameHeaderPtr(JSStack::Callee, scratch3); - emitLoadStructure(scratch3, scratch3, scratch0); - loadPtr(Address(scratch3, Structure::globalObjectOffset()), scratch3); - // Now, scratch3 holds JSGlobalObject*. - - auto loadFromHigh = [&](GPRReg high) { - load64(Address(scratch3, JSGlobalObject::weakRandomOffset() + WeakRandom::highOffset()), high); - }; - auto storeToHigh = [&](GPRReg high) { - store64(high, Address(scratch3, JSGlobalObject::weakRandomOffset() + WeakRandom::highOffset())); - }; - auto loadFromLow = [&](GPRReg low) { - load64(Address(scratch3, JSGlobalObject::weakRandomOffset() + WeakRandom::lowOffset()), low); - }; - auto storeToLow = [&](GPRReg low) { - store64(low, Address(scratch3, JSGlobalObject::weakRandomOffset() + WeakRandom::lowOffset())); - }; - - emitRandomThunkImpl(*this, scratch0, scratch1, scratch2, result, loadFromHigh, storeToHigh, loadFromLow, storeToLow); -} -#endif - -void AssemblyHelpers::restoreCalleeSavesFromVMCalleeSavesBuffer() -{ -#if NUMBER_OF_CALLEE_SAVES_REGISTERS > 0 - char* sourceBuffer = bitwise_cast<char*>(m_vm->calleeSaveRegistersBuffer); - - RegisterAtOffsetList* allCalleeSaves = m_vm->getAllCalleeSaveRegisterOffsets(); - RegisterSet dontRestoreRegisters = RegisterSet::stackRegisters(); - unsigned registerCount = allCalleeSaves->size(); - - for (unsigned i = 0; i < registerCount; i++) { - RegisterAtOffset entry = allCalleeSaves->at(i); - if (dontRestoreRegisters.get(entry.reg())) - continue; - if (entry.reg().isGPR()) - loadPtr(static_cast<void*>(sourceBuffer + entry.offset()), entry.reg().gpr()); - else - loadDouble(TrustedImmPtr(sourceBuffer + entry.offset()), entry.reg().fpr()); - } -#endif -} - } // namespace JSC #endif // ENABLE(JIT) |