summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/jit/AssemblyHelpers.h
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2016-04-10 09:28:39 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2016-04-10 09:28:39 +0000
commit32761a6cee1d0dee366b885b7b9c777e67885688 (patch)
treed6bec92bebfb216f4126356e55518842c2f476a1 /Source/JavaScriptCore/jit/AssemblyHelpers.h
parenta4e969f4965059196ca948db781e52f7cfebf19e (diff)
downloadWebKitGtk-tarball-32761a6cee1d0dee366b885b7b9c777e67885688.tar.gz
webkitgtk-2.4.11webkitgtk-2.4.11
Diffstat (limited to 'Source/JavaScriptCore/jit/AssemblyHelpers.h')
-rw-r--r--Source/JavaScriptCore/jit/AssemblyHelpers.h1032
1 files changed, 67 insertions, 965 deletions
diff --git a/Source/JavaScriptCore/jit/AssemblyHelpers.h b/Source/JavaScriptCore/jit/AssemblyHelpers.h
index 918af7dca..36d583139 100644
--- a/Source/JavaScriptCore/jit/AssemblyHelpers.h
+++ b/Source/JavaScriptCore/jit/AssemblyHelpers.h
@@ -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
@@ -26,19 +26,15 @@
#ifndef AssemblyHelpers_h
#define AssemblyHelpers_h
+#include <wtf/Platform.h>
+
#if ENABLE(JIT)
#include "CodeBlock.h"
-#include "CopyBarrier.h"
#include "FPRInfo.h"
#include "GPRInfo.h"
-#include "InlineCallFrame.h"
#include "JITCode.h"
#include "MacroAssembler.h"
-#include "MaxFrameExtentForSlowPathCall.h"
-#include "RegisterAtOffsetList.h"
-#include "RegisterSet.h"
-#include "TypeofType.h"
#include "VM.h"
namespace JSC {
@@ -62,331 +58,8 @@ public:
CodeBlock* codeBlock() { return m_codeBlock; }
VM* vm() { return m_vm; }
AssemblerType_T& assembler() { return m_assembler; }
-
- void checkStackPointerAlignment()
- {
- // This check is both unneeded and harder to write correctly for ARM64
-#if !defined(NDEBUG) && !CPU(ARM64)
- Jump stackPointerAligned = branchTestPtr(Zero, stackPointerRegister, TrustedImm32(0xf));
- abortWithReason(AHStackPointerMisaligned);
- stackPointerAligned.link(this);
-#endif
- }
-
- template<typename T>
- void storeCell(T cell, Address address)
- {
-#if USE(JSVALUE64)
- store64(cell, address);
-#else
- store32(cell, address.withOffset(PayloadOffset));
- store32(TrustedImm32(JSValue::CellTag), address.withOffset(TagOffset));
-#endif
- }
-
- void storeValue(JSValueRegs regs, Address address)
- {
-#if USE(JSVALUE64)
- store64(regs.gpr(), address);
-#else
- store32(regs.payloadGPR(), address.withOffset(PayloadOffset));
- store32(regs.tagGPR(), address.withOffset(TagOffset));
-#endif
- }
-
- void storeValue(JSValueRegs regs, BaseIndex address)
- {
-#if USE(JSVALUE64)
- store64(regs.gpr(), address);
-#else
- store32(regs.payloadGPR(), address.withOffset(PayloadOffset));
- store32(regs.tagGPR(), address.withOffset(TagOffset));
-#endif
- }
-
- void storeValue(JSValueRegs regs, void* address)
- {
-#if USE(JSVALUE64)
- store64(regs.gpr(), address);
-#else
- store32(regs.payloadGPR(), bitwise_cast<void*>(bitwise_cast<uintptr_t>(address) + PayloadOffset));
- store32(regs.tagGPR(), bitwise_cast<void*>(bitwise_cast<uintptr_t>(address) + TagOffset));
-#endif
- }
-
- void loadValue(Address address, JSValueRegs regs)
- {
-#if USE(JSVALUE64)
- load64(address, regs.gpr());
-#else
- if (address.base == regs.payloadGPR()) {
- load32(address.withOffset(TagOffset), regs.tagGPR());
- load32(address.withOffset(PayloadOffset), regs.payloadGPR());
- } else {
- load32(address.withOffset(PayloadOffset), regs.payloadGPR());
- load32(address.withOffset(TagOffset), regs.tagGPR());
- }
-#endif
- }
-
- void loadValue(BaseIndex address, JSValueRegs regs)
- {
-#if USE(JSVALUE64)
- load64(address, regs.gpr());
-#else
- if (address.base == regs.payloadGPR() || address.index == regs.payloadGPR()) {
- // We actually could handle the case where the registers are aliased to both
- // tag and payload, but we don't for now.
- RELEASE_ASSERT(address.base != regs.tagGPR());
- RELEASE_ASSERT(address.index != regs.tagGPR());
-
- load32(address.withOffset(TagOffset), regs.tagGPR());
- load32(address.withOffset(PayloadOffset), regs.payloadGPR());
- } else {
- load32(address.withOffset(PayloadOffset), regs.payloadGPR());
- load32(address.withOffset(TagOffset), regs.tagGPR());
- }
-#endif
- }
-
- void moveValueRegs(JSValueRegs srcRegs, JSValueRegs destRegs)
- {
-#if USE(JSVALUE32_64)
- move(srcRegs.tagGPR(), destRegs.tagGPR());
-#endif
- move(srcRegs.payloadGPR(), destRegs.payloadGPR());
- }
-
- void moveValue(JSValue value, JSValueRegs regs)
- {
-#if USE(JSVALUE64)
- move(Imm64(JSValue::encode(value)), regs.gpr());
-#else
- move(Imm32(value.tag()), regs.tagGPR());
- move(Imm32(value.payload()), regs.payloadGPR());
-#endif
- }
-
- void moveTrustedValue(JSValue value, JSValueRegs regs)
- {
-#if USE(JSVALUE64)
- move(TrustedImm64(JSValue::encode(value)), regs.gpr());
-#else
- move(TrustedImm32(value.tag()), regs.tagGPR());
- move(TrustedImm32(value.payload()), regs.payloadGPR());
-#endif
- }
- void storeTrustedValue(JSValue value, Address address)
- {
-#if USE(JSVALUE64)
- store64(TrustedImm64(JSValue::encode(value)), address);
-#else
- store32(TrustedImm32(value.tag()), address.withOffset(TagOffset));
- store32(TrustedImm32(value.payload()), address.withOffset(PayloadOffset));
-#endif
- }
-
- void storeTrustedValue(JSValue value, BaseIndex address)
- {
-#if USE(JSVALUE64)
- store64(TrustedImm64(JSValue::encode(value)), address);
-#else
- store32(TrustedImm32(value.tag()), address.withOffset(TagOffset));
- store32(TrustedImm32(value.payload()), address.withOffset(PayloadOffset));
-#endif
- }
-
- void emitSaveCalleeSavesFor(CodeBlock* codeBlock)
- {
- ASSERT(codeBlock);
-
- RegisterAtOffsetList* calleeSaves = codeBlock->calleeSaveRegisters();
- RegisterSet dontSaveRegisters = RegisterSet(RegisterSet::stackRegisters(), RegisterSet::allFPRs());
- unsigned registerCount = calleeSaves->size();
-
- for (unsigned i = 0; i < registerCount; i++) {
- RegisterAtOffset entry = calleeSaves->at(i);
- if (dontSaveRegisters.get(entry.reg()))
- continue;
- storePtr(entry.reg().gpr(), Address(framePointerRegister, entry.offset()));
- }
- }
-
- enum RestoreTagRegisterMode { UseExistingTagRegisterContents, CopyBaselineCalleeSavedRegistersFromBaseFrame };
-
- void emitSaveOrCopyCalleeSavesFor(CodeBlock* codeBlock, VirtualRegister offsetVirtualRegister, RestoreTagRegisterMode tagRegisterMode, GPRReg temp)
- {
- ASSERT(codeBlock);
-
- RegisterAtOffsetList* calleeSaves = codeBlock->calleeSaveRegisters();
- RegisterSet dontSaveRegisters = RegisterSet(RegisterSet::stackRegisters(), RegisterSet::allFPRs());
- unsigned registerCount = calleeSaves->size();
-
-#if USE(JSVALUE64)
- RegisterSet baselineCalleeSaves = RegisterSet::llintBaselineCalleeSaveRegisters();
-#endif
-
- for (unsigned i = 0; i < registerCount; i++) {
- RegisterAtOffset entry = calleeSaves->at(i);
- if (dontSaveRegisters.get(entry.reg()))
- continue;
-
- GPRReg registerToWrite;
-
-#if USE(JSVALUE32_64)
- UNUSED_PARAM(tagRegisterMode);
- UNUSED_PARAM(temp);
-#else
- if (tagRegisterMode == CopyBaselineCalleeSavedRegistersFromBaseFrame && baselineCalleeSaves.get(entry.reg())) {
- registerToWrite = temp;
- loadPtr(AssemblyHelpers::Address(GPRInfo::callFrameRegister, entry.offset()), registerToWrite);
- } else
-#endif
- registerToWrite = entry.reg().gpr();
-
- storePtr(registerToWrite, Address(framePointerRegister, offsetVirtualRegister.offsetInBytes() + entry.offset()));
- }
- }
-
- void emitRestoreCalleeSavesFor(CodeBlock* codeBlock)
- {
- ASSERT(codeBlock);
-
- RegisterAtOffsetList* calleeSaves = codeBlock->calleeSaveRegisters();
- RegisterSet dontRestoreRegisters = RegisterSet(RegisterSet::stackRegisters(), RegisterSet::allFPRs());
- unsigned registerCount = calleeSaves->size();
-
- for (unsigned i = 0; i < registerCount; i++) {
- RegisterAtOffset entry = calleeSaves->at(i);
- if (dontRestoreRegisters.get(entry.reg()))
- continue;
- loadPtr(Address(framePointerRegister, entry.offset()), entry.reg().gpr());
- }
- }
-
- void emitSaveCalleeSaves()
- {
- emitSaveCalleeSavesFor(codeBlock());
- }
-
- void emitRestoreCalleeSaves()
- {
- emitRestoreCalleeSavesFor(codeBlock());
- }
-
- void copyCalleeSavesToVMCalleeSavesBuffer(const TempRegisterSet& usedRegisters = { RegisterSet::stubUnavailableRegisters() })
- {
-#if NUMBER_OF_CALLEE_SAVES_REGISTERS > 0
- GPRReg temp1 = usedRegisters.getFreeGPR(0);
-
- move(TrustedImmPtr(m_vm->calleeSaveRegistersBuffer), temp1);
-
- RegisterAtOffsetList* allCalleeSaves = m_vm->getAllCalleeSaveRegisterOffsets();
- RegisterSet dontCopyRegisters = RegisterSet::stackRegisters();
- unsigned registerCount = allCalleeSaves->size();
-
- for (unsigned i = 0; i < registerCount; i++) {
- RegisterAtOffset entry = allCalleeSaves->at(i);
- if (dontCopyRegisters.get(entry.reg()))
- continue;
- if (entry.reg().isGPR())
- storePtr(entry.reg().gpr(), Address(temp1, entry.offset()));
- else
- storeDouble(entry.reg().fpr(), Address(temp1, entry.offset()));
- }
-#else
- UNUSED_PARAM(usedRegisters);
-#endif
- }
-
- void restoreCalleeSavesFromVMCalleeSavesBuffer();
-
- void copyCalleeSavesFromFrameOrRegisterToVMCalleeSavesBuffer(const TempRegisterSet& usedRegisters = { RegisterSet::stubUnavailableRegisters() })
- {
-#if NUMBER_OF_CALLEE_SAVES_REGISTERS > 0
- GPRReg temp1 = usedRegisters.getFreeGPR(0);
- GPRReg temp2 = usedRegisters.getFreeGPR(1);
- FPRReg fpTemp = usedRegisters.getFreeFPR();
- ASSERT(temp2 != InvalidGPRReg);
-
- ASSERT(codeBlock());
-
- // Copy saved calleeSaves on stack or unsaved calleeSaves in register to vm calleeSave buffer
- move(TrustedImmPtr(m_vm->calleeSaveRegistersBuffer), temp1);
-
- RegisterAtOffsetList* allCalleeSaves = m_vm->getAllCalleeSaveRegisterOffsets();
- RegisterAtOffsetList* currentCalleeSaves = codeBlock()->calleeSaveRegisters();
- RegisterSet dontCopyRegisters = RegisterSet::stackRegisters();
- unsigned registerCount = allCalleeSaves->size();
-
- for (unsigned i = 0; i < registerCount; i++) {
- RegisterAtOffset vmEntry = allCalleeSaves->at(i);
- if (dontCopyRegisters.get(vmEntry.reg()))
- continue;
- RegisterAtOffset* currentFrameEntry = currentCalleeSaves->find(vmEntry.reg());
-
- if (vmEntry.reg().isGPR()) {
- GPRReg regToStore;
- if (currentFrameEntry) {
- // Load calleeSave from stack into temp register
- regToStore = temp2;
- loadPtr(Address(framePointerRegister, currentFrameEntry->offset()), regToStore);
- } else
- // Just store callee save directly
- regToStore = vmEntry.reg().gpr();
-
- storePtr(regToStore, Address(temp1, vmEntry.offset()));
- } else {
- FPRReg fpRegToStore;
- if (currentFrameEntry) {
- // Load calleeSave from stack into temp register
- fpRegToStore = fpTemp;
- loadDouble(Address(framePointerRegister, currentFrameEntry->offset()), fpRegToStore);
- } else
- // Just store callee save directly
- fpRegToStore = vmEntry.reg().fpr();
-
- storeDouble(fpRegToStore, Address(temp1, vmEntry.offset()));
- }
- }
-#else
- UNUSED_PARAM(usedRegisters);
-#endif
- }
-
- void emitMaterializeTagCheckRegisters()
- {
-#if USE(JSVALUE64)
- move(MacroAssembler::TrustedImm64(TagTypeNumber), GPRInfo::tagTypeNumberRegister);
- orPtr(MacroAssembler::TrustedImm32(TagBitTypeOther), GPRInfo::tagTypeNumberRegister, GPRInfo::tagMaskRegister);
-#endif
- }
-
#if CPU(X86_64) || CPU(X86)
- static size_t prologueStackPointerDelta()
- {
- // Prologue only saves the framePointerRegister
- return sizeof(void*);
- }
-
- void emitFunctionPrologue()
- {
- push(framePointerRegister);
- move(stackPointerRegister, framePointerRegister);
- }
-
- void emitFunctionEpilogueWithEmptyFrame()
- {
- pop(framePointerRegister);
- }
-
- void emitFunctionEpilogue()
- {
- move(framePointerRegister, stackPointerRegister);
- pop(framePointerRegister);
- }
-
void preserveReturnAddressAfterCall(GPRReg reg)
{
pop(reg);
@@ -404,29 +77,6 @@ public:
#endif // CPU(X86_64) || CPU(X86)
#if CPU(ARM) || CPU(ARM64)
- static size_t prologueStackPointerDelta()
- {
- // Prologue saves the framePointerRegister and linkRegister
- return 2 * sizeof(void*);
- }
-
- void emitFunctionPrologue()
- {
- pushPair(framePointerRegister, linkRegister);
- move(stackPointerRegister, framePointerRegister);
- }
-
- void emitFunctionEpilogueWithEmptyFrame()
- {
- popPair(framePointerRegister, linkRegister);
- }
-
- void emitFunctionEpilogue()
- {
- move(framePointerRegister, stackPointerRegister);
- emitFunctionEpilogueWithEmptyFrame();
- }
-
ALWAYS_INLINE void preserveReturnAddressAfterCall(RegisterID reg)
{
move(linkRegister, reg);
@@ -444,29 +94,6 @@ public:
#endif
#if CPU(MIPS)
- static size_t prologueStackPointerDelta()
- {
- // Prologue saves the framePointerRegister and returnAddressRegister
- return 2 * sizeof(void*);
- }
-
- void emitFunctionPrologue()
- {
- pushPair(framePointerRegister, returnAddressRegister);
- move(stackPointerRegister, framePointerRegister);
- }
-
- void emitFunctionEpilogueWithEmptyFrame()
- {
- popPair(framePointerRegister, returnAddressRegister);
- }
-
- void emitFunctionEpilogue()
- {
- move(framePointerRegister, stackPointerRegister);
- emitFunctionEpilogueWithEmptyFrame();
- }
-
ALWAYS_INLINE void preserveReturnAddressAfterCall(RegisterID reg)
{
move(returnAddressRegister, reg);
@@ -484,26 +111,6 @@ public:
#endif
#if CPU(SH4)
- static size_t prologueStackPointerDelta()
- {
- // Prologue saves the framePointerRegister and link register
- return 2 * sizeof(void*);
- }
-
- void emitFunctionPrologue()
- {
- push(linkRegister);
- push(framePointerRegister);
- move(stackPointerRegister, framePointerRegister);
- }
-
- void emitFunctionEpilogue()
- {
- move(framePointerRegister, stackPointerRegister);
- pop(framePointerRegister);
- pop(linkRegister);
- }
-
ALWAYS_INLINE void preserveReturnAddressAfterCall(RegisterID reg)
{
m_assembler.stspr(reg);
@@ -520,26 +127,16 @@ public:
}
#endif
- void emitGetFromCallFrameHeaderPtr(JSStack::CallFrameHeaderEntry entry, GPRReg to, GPRReg from = GPRInfo::callFrameRegister)
+ void emitGetFromCallFrameHeaderPtr(JSStack::CallFrameHeaderEntry entry, GPRReg to)
{
- loadPtr(Address(from, entry * sizeof(Register)), to);
+ loadPtr(Address(GPRInfo::callFrameRegister, entry * sizeof(Register)), to);
}
- void emitGetFromCallFrameHeader32(JSStack::CallFrameHeaderEntry entry, GPRReg to, GPRReg from = GPRInfo::callFrameRegister)
- {
- load32(Address(from, entry * sizeof(Register)), to);
- }
-#if USE(JSVALUE64)
- void emitGetFromCallFrameHeader64(JSStack::CallFrameHeaderEntry entry, GPRReg to, GPRReg from = GPRInfo::callFrameRegister)
- {
- load64(Address(from, entry * sizeof(Register)), to);
- }
-#endif // USE(JSVALUE64)
void emitPutToCallFrameHeader(GPRReg from, JSStack::CallFrameHeaderEntry entry)
{
storePtr(from, Address(GPRInfo::callFrameRegister, entry * sizeof(Register)));
}
- void emitPutToCallFrameHeader(void* value, JSStack::CallFrameHeaderEntry entry)
+ void emitPutImmediateToCallFrameHeader(void* value, JSStack::CallFrameHeaderEntry entry)
{
storePtr(TrustedImmPtr(value), Address(GPRInfo::callFrameRegister, entry * sizeof(Register)));
}
@@ -553,6 +150,10 @@ public:
storePtr(from, Address(GPRInfo::callFrameRegister, CallFrame::callerFrameOffset()));
}
+ void emitGetReturnPCFromCallFrameHeaderPtr(RegisterID to)
+ {
+ loadPtr(Address(GPRInfo::callFrameRegister, CallFrame::returnPCOffset()), to);
+ }
void emitPutReturnPCToCallFrameHeader(RegisterID from)
{
storePtr(from, Address(GPRInfo::callFrameRegister, CallFrame::returnPCOffset()));
@@ -562,287 +163,14 @@ public:
storePtr(from, Address(GPRInfo::callFrameRegister, CallFrame::returnPCOffset()));
}
- // emitPutToCallFrameHeaderBeforePrologue() and related are used to access callee frame header
- // fields before the code from emitFunctionPrologue() has executed.
- // First, the access is via the stack pointer. Second, the address calculation must also take
- // into account that the stack pointer may not have been adjusted down for the return PC and/or
- // caller's frame pointer. On some platforms, the callee is responsible for pushing the
- // "link register" containing the return address in the function prologue.
-#if USE(JSVALUE64)
- void emitPutToCallFrameHeaderBeforePrologue(GPRReg from, JSStack::CallFrameHeaderEntry entry)
- {
- storePtr(from, Address(stackPointerRegister, entry * static_cast<ptrdiff_t>(sizeof(Register)) - prologueStackPointerDelta()));
- }
-#else
- void emitPutPayloadToCallFrameHeaderBeforePrologue(GPRReg from, JSStack::CallFrameHeaderEntry entry)
- {
- storePtr(from, Address(stackPointerRegister, entry * static_cast<ptrdiff_t>(sizeof(Register)) - prologueStackPointerDelta() + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)));
- }
-
- void emitPutTagToCallFrameHeaderBeforePrologue(TrustedImm32 tag, JSStack::CallFrameHeaderEntry entry)
- {
- storePtr(tag, Address(stackPointerRegister, entry * static_cast<ptrdiff_t>(sizeof(Register)) - prologueStackPointerDelta() + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)));
- }
-#endif
-
- JumpList branchIfNotEqual(JSValueRegs regs, JSValue value)
- {
-#if USE(JSVALUE64)
- return branch64(NotEqual, regs.gpr(), TrustedImm64(JSValue::encode(value)));
-#else
- JumpList result;
- result.append(branch32(NotEqual, regs.tagGPR(), TrustedImm32(value.tag())));
- if (value.isEmpty() || value.isUndefinedOrNull())
- return result; // These don't have anything interesting in the payload.
- result.append(branch32(NotEqual, regs.payloadGPR(), TrustedImm32(value.payload())));
- return result;
-#endif
- }
-
- Jump branchIfEqual(JSValueRegs regs, JSValue value)
+ Jump branchIfNotCell(GPRReg reg)
{
#if USE(JSVALUE64)
- return branch64(Equal, regs.gpr(), TrustedImm64(JSValue::encode(value)));
+ return branchTest64(MacroAssembler::NonZero, reg, GPRInfo::tagMaskRegister);
#else
- Jump notEqual;
- // These don't have anything interesting in the payload.
- if (!value.isEmpty() && !value.isUndefinedOrNull())
- notEqual = branch32(NotEqual, regs.payloadGPR(), TrustedImm32(value.payload()));
- Jump result = branch32(Equal, regs.tagGPR(), TrustedImm32(value.tag()));
- if (notEqual.isSet())
- notEqual.link(this);
- return result;
-#endif
- }
-
- enum TagRegistersMode {
- DoNotHaveTagRegisters,
- HaveTagRegisters
- };
-
- Jump branchIfNotCell(GPRReg reg, TagRegistersMode mode = HaveTagRegisters)
- {
-#if USE(JSVALUE64)
- if (mode == HaveTagRegisters)
- return branchTest64(NonZero, reg, GPRInfo::tagMaskRegister);
- return branchTest64(NonZero, reg, TrustedImm64(TagMask));
-#else
- UNUSED_PARAM(mode);
return branch32(MacroAssembler::NotEqual, reg, TrustedImm32(JSValue::CellTag));
#endif
}
- Jump branchIfNotCell(JSValueRegs regs, TagRegistersMode mode = HaveTagRegisters)
- {
-#if USE(JSVALUE64)
- return branchIfNotCell(regs.gpr(), mode);
-#else
- return branchIfNotCell(regs.tagGPR(), mode);
-#endif
- }
-
- Jump branchIfCell(GPRReg reg, TagRegistersMode mode = HaveTagRegisters)
- {
-#if USE(JSVALUE64)
- if (mode == HaveTagRegisters)
- return branchTest64(Zero, reg, GPRInfo::tagMaskRegister);
- return branchTest64(Zero, reg, TrustedImm64(TagMask));
-#else
- UNUSED_PARAM(mode);
- return branch32(MacroAssembler::Equal, reg, TrustedImm32(JSValue::CellTag));
-#endif
- }
- Jump branchIfCell(JSValueRegs regs, TagRegistersMode mode = HaveTagRegisters)
- {
-#if USE(JSVALUE64)
- return branchIfCell(regs.gpr(), mode);
-#else
- return branchIfCell(regs.tagGPR(), mode);
-#endif
- }
-
- Jump branchIfOther(JSValueRegs regs, GPRReg tempGPR)
- {
-#if USE(JSVALUE64)
- move(regs.gpr(), tempGPR);
- and64(TrustedImm32(~TagBitUndefined), tempGPR);
- return branch64(Equal, tempGPR, TrustedImm64(ValueNull));
-#else
- or32(TrustedImm32(1), regs.tagGPR(), tempGPR);
- return branch32(Equal, tempGPR, TrustedImm32(JSValue::NullTag));
-#endif
- }
-
- Jump branchIfNotOther(JSValueRegs regs, GPRReg tempGPR)
- {
-#if USE(JSVALUE64)
- move(regs.gpr(), tempGPR);
- and64(TrustedImm32(~TagBitUndefined), tempGPR);
- return branch64(NotEqual, tempGPR, TrustedImm64(ValueNull));
-#else
- or32(TrustedImm32(1), regs.tagGPR(), tempGPR);
- return branch32(NotEqual, tempGPR, TrustedImm32(JSValue::NullTag));
-#endif
- }
-
- Jump branchIfInt32(JSValueRegs regs, TagRegistersMode mode = HaveTagRegisters)
- {
-#if USE(JSVALUE64)
- if (mode == HaveTagRegisters)
- return branch64(AboveOrEqual, regs.gpr(), GPRInfo::tagTypeNumberRegister);
- return branch64(AboveOrEqual, regs.gpr(), TrustedImm64(TagTypeNumber));
-#else
- UNUSED_PARAM(mode);
- return branch32(Equal, regs.tagGPR(), TrustedImm32(JSValue::Int32Tag));
-#endif
- }
-
-#if USE(JSVALUE64)
- Jump branchIfNotInt32(GPRReg gpr, TagRegistersMode mode = HaveTagRegisters)
- {
- if (mode == HaveTagRegisters)
- return branch64(Below, gpr, GPRInfo::tagTypeNumberRegister);
- return branch64(Below, gpr, TrustedImm64(TagTypeNumber));
- }
-#endif
-
- Jump branchIfNotInt32(JSValueRegs regs, TagRegistersMode mode = HaveTagRegisters)
- {
-#if USE(JSVALUE64)
- return branchIfNotInt32(regs.gpr(), mode);
-#else
- UNUSED_PARAM(mode);
- return branch32(NotEqual, regs.tagGPR(), TrustedImm32(JSValue::Int32Tag));
-#endif
- }
-
- // Note that the tempGPR is not used in 64-bit mode.
- Jump branchIfNumber(JSValueRegs regs, GPRReg tempGPR, TagRegistersMode mode = HaveTagRegisters)
- {
-#if USE(JSVALUE64)
- UNUSED_PARAM(tempGPR);
- if (mode == HaveTagRegisters)
- return branchTest64(NonZero, regs.gpr(), GPRInfo::tagTypeNumberRegister);
- return branchTest64(NonZero, regs.gpr(), TrustedImm64(TagTypeNumber));
-#else
- UNUSED_PARAM(mode);
- add32(TrustedImm32(1), regs.tagGPR(), tempGPR);
- return branch32(Below, tempGPR, TrustedImm32(JSValue::LowestTag + 1));
-#endif
- }
-
- // Note that the tempGPR is not used in 64-bit mode.
- Jump branchIfNotNumber(JSValueRegs regs, GPRReg tempGPR, TagRegistersMode mode = HaveTagRegisters)
- {
-#if USE(JSVALUE64)
- UNUSED_PARAM(tempGPR);
- if (mode == HaveTagRegisters)
- return branchTest64(Zero, regs.gpr(), GPRInfo::tagTypeNumberRegister);
- return branchTest64(Zero, regs.gpr(), TrustedImm64(TagTypeNumber));
-#else
- UNUSED_PARAM(mode);
- add32(TrustedImm32(1), regs.tagGPR(), tempGPR);
- return branch32(AboveOrEqual, tempGPR, TrustedImm32(JSValue::LowestTag + 1));
-#endif
- }
-
- // Note that the tempGPR is not used in 32-bit mode.
- Jump branchIfBoolean(JSValueRegs regs, GPRReg tempGPR)
- {
-#if USE(JSVALUE64)
- move(regs.gpr(), tempGPR);
- xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), tempGPR);
- return branchTest64(Zero, tempGPR, TrustedImm32(static_cast<int32_t>(~1)));
-#else
- UNUSED_PARAM(tempGPR);
- return branch32(Equal, regs.tagGPR(), TrustedImm32(JSValue::BooleanTag));
-#endif
- }
-
- // Note that the tempGPR is not used in 32-bit mode.
- Jump branchIfNotBoolean(JSValueRegs regs, GPRReg tempGPR)
- {
-#if USE(JSVALUE64)
- move(regs.gpr(), tempGPR);
- xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), tempGPR);
- return branchTest64(NonZero, tempGPR, TrustedImm32(static_cast<int32_t>(~1)));
-#else
- UNUSED_PARAM(tempGPR);
- return branch32(NotEqual, regs.tagGPR(), TrustedImm32(JSValue::BooleanTag));
-#endif
- }
-
- Jump branchIfObject(GPRReg cellGPR)
- {
- return branch8(
- AboveOrEqual, Address(cellGPR, JSCell::typeInfoTypeOffset()), TrustedImm32(ObjectType));
- }
-
- Jump branchIfNotObject(GPRReg cellGPR)
- {
- return branch8(
- Below, Address(cellGPR, JSCell::typeInfoTypeOffset()), TrustedImm32(ObjectType));
- }
-
- Jump branchIfType(GPRReg cellGPR, JSType type)
- {
- return branch8(Equal, Address(cellGPR, JSCell::typeInfoTypeOffset()), TrustedImm32(type));
- }
-
- Jump branchIfNotType(GPRReg cellGPR, JSType type)
- {
- return branch8(NotEqual, Address(cellGPR, JSCell::typeInfoTypeOffset()), TrustedImm32(type));
- }
-
- Jump branchIfString(GPRReg cellGPR) { return branchIfType(cellGPR, StringType); }
- Jump branchIfNotString(GPRReg cellGPR) { return branchIfNotType(cellGPR, StringType); }
- Jump branchIfSymbol(GPRReg cellGPR) { return branchIfType(cellGPR, SymbolType); }
- Jump branchIfNotSymbol(GPRReg cellGPR) { return branchIfNotType(cellGPR, SymbolType); }
- Jump branchIfFunction(GPRReg cellGPR) { return branchIfType(cellGPR, JSFunctionType); }
- Jump branchIfNotFunction(GPRReg cellGPR) { return branchIfNotType(cellGPR, JSFunctionType); }
-
- Jump branchIfEmpty(JSValueRegs regs)
- {
-#if USE(JSVALUE64)
- return branchTest64(Zero, regs.gpr());
-#else
- return branch32(Equal, regs.tagGPR(), TrustedImm32(JSValue::EmptyValueTag));
-#endif
- }
-
- JumpList branchIfNotType(
- JSValueRegs, GPRReg tempGPR, const InferredType::Descriptor&, TagRegistersMode);
-
- template<typename T>
- Jump branchStructure(RelationalCondition condition, T leftHandSide, Structure* structure)
- {
-#if USE(JSVALUE64)
- return branch32(condition, leftHandSide, TrustedImm32(structure->id()));
-#else
- return branchPtr(condition, leftHandSide, TrustedImmPtr(structure));
-#endif
- }
-
- Jump branchIfToSpace(GPRReg storageGPR)
- {
- return branchTest32(Zero, storageGPR, TrustedImm32(CopyBarrierBase::spaceBits));
- }
-
- Jump branchIfNotToSpace(GPRReg storageGPR)
- {
- return branchTest32(NonZero, storageGPR, TrustedImm32(CopyBarrierBase::spaceBits));
- }
-
- void removeSpaceBits(GPRReg storageGPR)
- {
- andPtr(TrustedImmPtr(~static_cast<uintptr_t>(CopyBarrierBase::spaceBits)), storageGPR);
- }
-
- Jump branchIfFastTypedArray(GPRReg baseGPR);
- Jump branchIfNotFastTypedArray(GPRReg baseGPR);
-
- // Returns a jump to slow path for when we need to execute the barrier. Note that baseGPR and
- // resultGPR must be different.
- Jump loadTypedArrayVector(GPRReg baseGPR, GPRReg resultGPR);
static Address addressForByteOffset(ptrdiff_t byteOffset)
{
@@ -855,10 +183,6 @@ public:
}
static Address addressFor(VirtualRegister virtualRegister)
{
- // NB. It's tempting on some architectures to sometimes use an offset from the stack
- // register because for some offsets that will encode to a smaller instruction. But we
- // cannot do this. We use this in places where the stack pointer has been moved to some
- // unpredictable location.
ASSERT(virtualRegister.isValid());
return Address(GPRInfo::callFrameRegister, virtualRegister.offset() * sizeof(Register));
}
@@ -870,7 +194,7 @@ public:
static Address tagFor(VirtualRegister virtualRegister)
{
ASSERT(virtualRegister.isValid());
- return Address(GPRInfo::callFrameRegister, virtualRegister.offset() * sizeof(Register) + TagOffset);
+ return Address(GPRInfo::callFrameRegister, virtualRegister.offset() * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag));
}
static Address tagFor(int operand)
{
@@ -880,69 +204,33 @@ public:
static Address payloadFor(VirtualRegister virtualRegister)
{
ASSERT(virtualRegister.isValid());
- return Address(GPRInfo::callFrameRegister, virtualRegister.offset() * sizeof(Register) + PayloadOffset);
+ return Address(GPRInfo::callFrameRegister, virtualRegister.offset() * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
}
static Address payloadFor(int operand)
{
return payloadFor(static_cast<VirtualRegister>(operand));
}
- // Access to our fixed callee CallFrame.
- static Address calleeFrameSlot(int slot)
- {
- ASSERT(slot >= JSStack::CallerFrameAndPCSize);
- return Address(stackPointerRegister, sizeof(Register) * (slot - JSStack::CallerFrameAndPCSize));
- }
-
- // Access to our fixed callee CallFrame.
- static Address calleeArgumentSlot(int argument)
+ Jump branchIfNotObject(GPRReg structureReg)
{
- return calleeFrameSlot(virtualRegisterForArgument(argument).offset());
+ return branch8(Below, Address(structureReg, Structure::typeInfoTypeOffset()), TrustedImm32(ObjectType));
}
- static Address calleeFrameTagSlot(int slot)
+ static GPRReg selectScratchGPR(GPRReg preserve1 = InvalidGPRReg, GPRReg preserve2 = InvalidGPRReg, GPRReg preserve3 = InvalidGPRReg, GPRReg preserve4 = InvalidGPRReg)
{
- return calleeFrameSlot(slot).withOffset(TagOffset);
- }
-
- static Address calleeFramePayloadSlot(int slot)
- {
- return calleeFrameSlot(slot).withOffset(PayloadOffset);
- }
-
- static Address calleeArgumentTagSlot(int argument)
- {
- return calleeArgumentSlot(argument).withOffset(TagOffset);
- }
-
- static Address calleeArgumentPayloadSlot(int argument)
- {
- return calleeArgumentSlot(argument).withOffset(PayloadOffset);
- }
-
- static Address calleeFrameCallerFrame()
- {
- return calleeFrameSlot(0).withOffset(CallFrame::callerFrameOffset());
- }
-
- static GPRReg selectScratchGPR(GPRReg preserve1 = InvalidGPRReg, GPRReg preserve2 = InvalidGPRReg, GPRReg preserve3 = InvalidGPRReg, GPRReg preserve4 = InvalidGPRReg, GPRReg preserve5 = InvalidGPRReg)
- {
- if (preserve1 != GPRInfo::regT0 && preserve2 != GPRInfo::regT0 && preserve3 != GPRInfo::regT0 && preserve4 != GPRInfo::regT0 && preserve5 != GPRInfo::regT0)
+ if (preserve1 != GPRInfo::regT0 && preserve2 != GPRInfo::regT0 && preserve3 != GPRInfo::regT0 && preserve4 != GPRInfo::regT0)
return GPRInfo::regT0;
- if (preserve1 != GPRInfo::regT1 && preserve2 != GPRInfo::regT1 && preserve3 != GPRInfo::regT1 && preserve4 != GPRInfo::regT1 && preserve5 != GPRInfo::regT1)
+ if (preserve1 != GPRInfo::regT1 && preserve2 != GPRInfo::regT1 && preserve3 != GPRInfo::regT1 && preserve4 != GPRInfo::regT1)
return GPRInfo::regT1;
- if (preserve1 != GPRInfo::regT2 && preserve2 != GPRInfo::regT2 && preserve3 != GPRInfo::regT2 && preserve4 != GPRInfo::regT2 && preserve5 != GPRInfo::regT2)
+ if (preserve1 != GPRInfo::regT2 && preserve2 != GPRInfo::regT2 && preserve3 != GPRInfo::regT2 && preserve4 != GPRInfo::regT2)
return GPRInfo::regT2;
- if (preserve1 != GPRInfo::regT3 && preserve2 != GPRInfo::regT3 && preserve3 != GPRInfo::regT3 && preserve4 != GPRInfo::regT3 && preserve5 != GPRInfo::regT3)
+ if (preserve1 != GPRInfo::regT3 && preserve2 != GPRInfo::regT3 && preserve3 != GPRInfo::regT3 && preserve4 != GPRInfo::regT3)
return GPRInfo::regT3;
- if (preserve1 != GPRInfo::regT4 && preserve2 != GPRInfo::regT4 && preserve3 != GPRInfo::regT4 && preserve4 != GPRInfo::regT4 && preserve5 != GPRInfo::regT4)
- return GPRInfo::regT4;
-
- return GPRInfo::regT5;
+ return GPRInfo::regT4;
}
// Add a debug call. This call has no effect on JIT code execution state.
@@ -1010,8 +298,6 @@ public:
void jitAssertIsCell(GPRReg);
void jitAssertHasValidCallFrame();
void jitAssertIsNull(GPRReg);
- void jitAssertTagsInPlace();
- void jitAssertArgumentCountSane();
#else
void jitAssertIsInt32(GPRReg) { }
void jitAssertIsJSInt32(GPRReg) { }
@@ -1020,14 +306,8 @@ public:
void jitAssertIsCell(GPRReg) { }
void jitAssertHasValidCallFrame() { }
void jitAssertIsNull(GPRReg) { }
- void jitAssertTagsInPlace() { }
- void jitAssertArgumentCountSane() { }
#endif
- void jitReleaseAssertNoException();
-
- void purifyNaN(FPRReg);
-
// These methods convert between doubles, and doubles boxed and JSValues.
#if USE(JSVALUE64)
GPRReg boxDouble(FPRReg fpr, GPRReg gpr)
@@ -1037,28 +317,14 @@ public:
jitAssertIsJSDouble(gpr);
return gpr;
}
- FPRReg unboxDoubleWithoutAssertions(GPRReg gpr, GPRReg resultGPR, FPRReg fpr)
- {
- add64(GPRInfo::tagTypeNumberRegister, gpr, resultGPR);
- move64ToDouble(resultGPR, fpr);
- return fpr;
- }
- FPRReg unboxDouble(GPRReg gpr, GPRReg resultGPR, FPRReg fpr)
+ FPRReg unboxDouble(GPRReg gpr, FPRReg fpr)
{
jitAssertIsJSDouble(gpr);
- return unboxDoubleWithoutAssertions(gpr, resultGPR, fpr);
+ add64(GPRInfo::tagTypeNumberRegister, gpr);
+ move64ToDouble(gpr, fpr);
+ return fpr;
}
- void boxDouble(FPRReg fpr, JSValueRegs regs)
- {
- boxDouble(fpr, regs.gpr());
- }
-
- void unboxDoubleNonDestructive(JSValueRegs regs, FPRReg destFPR, GPRReg resultGPR, FPRReg)
- {
- unboxDouble(regs.payloadGPR(), resultGPR, destFPR);
- }
-
// Here are possible arrangements of source, target, scratch:
// - source, target, scratch can all be separate registers.
// - source and target can be the same but scratch is separate.
@@ -1091,71 +357,18 @@ public:
{
moveIntsToDouble(payloadGPR, tagGPR, fpr, scratchFPR);
}
-
- void boxDouble(FPRReg fpr, JSValueRegs regs)
- {
- boxDouble(fpr, regs.tagGPR(), regs.payloadGPR());
- }
- void unboxDouble(JSValueRegs regs, FPRReg fpr, FPRReg scratchFPR)
- {
- unboxDouble(regs.tagGPR(), regs.payloadGPR(), fpr, scratchFPR);
- }
-
- void unboxDoubleNonDestructive(const JSValueRegs regs, FPRReg destFPR, GPRReg, FPRReg scratchFPR)
- {
- unboxDouble(regs, destFPR, scratchFPR);
- }
#endif
- void boxBooleanPayload(GPRReg boolGPR, GPRReg payloadGPR)
- {
-#if USE(JSVALUE64)
- add32(TrustedImm32(ValueFalse), boolGPR, payloadGPR);
-#else
- move(boolGPR, payloadGPR);
-#endif
- }
-
- void boxBooleanPayload(bool value, GPRReg payloadGPR)
+ enum ExceptionCheckKind { NormalExceptionCheck, InvertedExceptionCheck };
+ Jump emitExceptionCheck(ExceptionCheckKind kind = NormalExceptionCheck)
{
#if USE(JSVALUE64)
- move(TrustedImm32(ValueFalse + value), payloadGPR);
-#else
- move(TrustedImm32(value), payloadGPR);
+ return branchTest64(kind == NormalExceptionCheck ? NonZero : Zero, AbsoluteAddress(vm()->addressOfException()));
+#elif USE(JSVALUE32_64)
+ return branch32(kind == NormalExceptionCheck ? NotEqual : Equal, AbsoluteAddress(reinterpret_cast<char*>(vm()->addressOfException()) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), TrustedImm32(JSValue::EmptyValueTag));
#endif
}
- void boxBoolean(GPRReg boolGPR, JSValueRegs boxedRegs)
- {
- boxBooleanPayload(boolGPR, boxedRegs.payloadGPR());
-#if USE(JSVALUE32_64)
- move(TrustedImm32(JSValue::BooleanTag), boxedRegs.tagGPR());
-#endif
- }
-
- void boxInt32(GPRReg intGPR, JSValueRegs boxedRegs, TagRegistersMode mode = HaveTagRegisters)
- {
-#if USE(JSVALUE64)
- if (mode == DoNotHaveTagRegisters) {
- move(intGPR, boxedRegs.gpr());
- or64(TrustedImm64(TagTypeNumber), boxedRegs.gpr());
- } else
- or64(GPRInfo::tagTypeNumberRegister, intGPR, boxedRegs.gpr());
-#else
- UNUSED_PARAM(mode);
- move(intGPR, boxedRegs.payloadGPR());
- move(TrustedImm32(JSValue::Int32Tag), boxedRegs.tagGPR());
-#endif
- }
-
- void callExceptionFuzz();
-
- enum ExceptionCheckKind { NormalExceptionCheck, InvertedExceptionCheck };
- enum ExceptionJumpWidth { NormalJumpWidth, FarJumpWidth };
- Jump emitExceptionCheck(
- ExceptionCheckKind = NormalExceptionCheck, ExceptionJumpWidth = NormalJumpWidth);
- Jump emitNonPatchableExceptionCheck();
-
#if ENABLE(SAMPLING_COUNTERS)
static void emitCount(MacroAssembler& jit, AbstractSamplingCounter& counter, int32_t increment = 1)
{
@@ -1181,7 +394,7 @@ public:
{
if (!codeOrigin.inlineCallFrame)
return codeBlock()->isStrictMode();
- return codeOrigin.inlineCallFrame->isStrictMode();
+ return jsCast<FunctionExecutable*>(codeOrigin.inlineCallFrame->executable.get())->isStrictMode();
}
ECMAMode ecmaModeFor(CodeOrigin codeOrigin)
@@ -1208,175 +421,64 @@ public:
return m_baselineCodeBlock;
}
- static VirtualRegister argumentsStart(InlineCallFrame* inlineCallFrame)
+ VirtualRegister baselineArgumentsRegisterFor(InlineCallFrame* inlineCallFrame)
{
if (!inlineCallFrame)
- return VirtualRegister(CallFrame::argumentOffset(0));
- if (inlineCallFrame->arguments.size() <= 1)
- return virtualRegisterForLocal(0);
- ValueRecovery recovery = inlineCallFrame->arguments[1];
- RELEASE_ASSERT(recovery.technique() == DisplacedInJSStack);
- return recovery.virtualRegister();
+ return baselineCodeBlock()->argumentsRegister();
+
+ return VirtualRegister(baselineCodeBlockForInlineCallFrame(
+ inlineCallFrame)->argumentsRegister().offset() + inlineCallFrame->stackOffset);
}
- static VirtualRegister argumentsStart(const CodeOrigin& codeOrigin)
+ VirtualRegister baselineArgumentsRegisterFor(const CodeOrigin& codeOrigin)
{
- return argumentsStart(codeOrigin.inlineCallFrame);
+ return baselineArgumentsRegisterFor(codeOrigin.inlineCallFrame);
}
- void emitLoadStructure(RegisterID source, RegisterID dest, RegisterID scratch)
- {
-#if USE(JSVALUE64)
- load32(MacroAssembler::Address(source, JSCell::structureIDOffset()), dest);
- loadPtr(vm()->heap.structureIDTable().base(), scratch);
- loadPtr(MacroAssembler::BaseIndex(scratch, dest, MacroAssembler::TimesEight), dest);
-#else
- UNUSED_PARAM(scratch);
- loadPtr(MacroAssembler::Address(source, JSCell::structureIDOffset()), dest);
-#endif
- }
-
- static void emitLoadStructure(AssemblyHelpers& jit, RegisterID base, RegisterID dest, RegisterID scratch)
+ SymbolTable* symbolTableFor(const CodeOrigin& codeOrigin)
{
-#if USE(JSVALUE64)
- jit.load32(MacroAssembler::Address(base, JSCell::structureIDOffset()), dest);
- jit.loadPtr(jit.vm()->heap.structureIDTable().base(), scratch);
- jit.loadPtr(MacroAssembler::BaseIndex(scratch, dest, MacroAssembler::TimesEight), dest);
-#else
- UNUSED_PARAM(scratch);
- jit.loadPtr(MacroAssembler::Address(base, JSCell::structureIDOffset()), dest);
-#endif
+ return baselineCodeBlockFor(codeOrigin)->symbolTable();
}
- void emitStoreStructureWithTypeInfo(TrustedImmPtr structure, RegisterID dest, RegisterID)
+ int offsetOfLocals(const CodeOrigin& codeOrigin)
{
- emitStoreStructureWithTypeInfo(*this, structure, dest);
+ if (!codeOrigin.inlineCallFrame)
+ return 0;
+ return codeOrigin.inlineCallFrame->stackOffset * sizeof(Register);
}
- void emitStoreStructureWithTypeInfo(RegisterID structure, RegisterID dest, RegisterID scratch)
+ int offsetOfArgumentsIncludingThis(InlineCallFrame* inlineCallFrame)
{
-#if USE(JSVALUE64)
- load64(MacroAssembler::Address(structure, Structure::structureIDOffset()), scratch);
- store64(scratch, MacroAssembler::Address(dest, JSCell::structureIDOffset()));
-#else
- // Store all the info flags using a single 32-bit wide load and store.
- load32(MacroAssembler::Address(structure, Structure::indexingTypeOffset()), scratch);
- store32(scratch, MacroAssembler::Address(dest, JSCell::indexingTypeOffset()));
-
- // Store the StructureID
- storePtr(structure, MacroAssembler::Address(dest, JSCell::structureIDOffset()));
-#endif
+ if (!inlineCallFrame)
+ return CallFrame::argumentOffsetIncludingThis(0) * sizeof(Register);
+ if (inlineCallFrame->arguments.size() <= 1)
+ return 0;
+ ValueRecovery recovery = inlineCallFrame->arguments[1];
+ RELEASE_ASSERT(recovery.technique() == DisplacedInJSStack);
+ return (recovery.virtualRegister().offset() - 1) * sizeof(Register);
}
-
- static void emitStoreStructureWithTypeInfo(AssemblyHelpers& jit, TrustedImmPtr structure, RegisterID dest);
-
- Jump jumpIfIsRememberedOrInEden(GPRReg cell)
+
+ int offsetOfArgumentsIncludingThis(const CodeOrigin& codeOrigin)
{
- return branchTest8(MacroAssembler::NonZero, MacroAssembler::Address(cell, JSCell::cellStateOffset()));
+ return offsetOfArgumentsIncludingThis(codeOrigin.inlineCallFrame);
}
- Jump jumpIfIsRememberedOrInEden(JSCell* cell)
+ void writeBarrier(GPRReg owner, GPRReg scratch1, GPRReg scratch2, WriteBarrierUseKind useKind)
{
- uint8_t* address = reinterpret_cast<uint8_t*>(cell) + JSCell::cellStateOffset();
- return branchTest8(MacroAssembler::NonZero, MacroAssembler::AbsoluteAddress(address));
- }
-
- // Emits the branch structure for typeof. The code emitted by this doesn't fall through. The
- // functor is called at those points where we have pinpointed a type. One way to use this is to
- // have the functor emit the code to put the type string into an appropriate register and then
- // jump out. A secondary functor is used for the call trap and masquerades-as-undefined slow
- // case. It is passed the unlinked jump to the slow case.
- template<typename Functor, typename SlowPathFunctor>
- void emitTypeOf(
- JSValueRegs regs, GPRReg tempGPR, const Functor& functor,
- const SlowPathFunctor& slowPathFunctor)
- {
- // Implements the following branching structure:
- //
- // if (is cell) {
- // if (is object) {
- // if (is function) {
- // return function;
- // } else if (doesn't have call trap and doesn't masquerade as undefined) {
- // return object
- // } else {
- // return slowPath();
- // }
- // } else if (is string) {
- // return string
- // } else {
- // return symbol
- // }
- // } else if (is number) {
- // return number
- // } else if (is null) {
- // return object
- // } else if (is boolean) {
- // return boolean
- // } else {
- // return undefined
- // }
-
- Jump notCell = branchIfNotCell(regs);
-
- GPRReg cellGPR = regs.payloadGPR();
- Jump notObject = branchIfNotObject(cellGPR);
-
- Jump notFunction = branchIfNotFunction(cellGPR);
- functor(TypeofType::Function, false);
-
- notFunction.link(this);
- slowPathFunctor(
- branchTest8(
- NonZero,
- Address(cellGPR, JSCell::typeInfoFlagsOffset()),
- TrustedImm32(MasqueradesAsUndefined | TypeOfShouldCallGetCallData)));
- functor(TypeofType::Object, false);
-
- notObject.link(this);
-
- Jump notString = branchIfNotString(cellGPR);
- functor(TypeofType::String, false);
- notString.link(this);
- functor(TypeofType::Symbol, false);
-
- notCell.link(this);
-
- Jump notNumber = branchIfNotNumber(regs, tempGPR);
- functor(TypeofType::Number, false);
- notNumber.link(this);
-
- JumpList notNull = branchIfNotEqual(regs, jsNull());
- functor(TypeofType::Object, false);
- notNull.link(this);
+ UNUSED_PARAM(owner);
+ UNUSED_PARAM(scratch1);
+ UNUSED_PARAM(scratch2);
+ UNUSED_PARAM(useKind);
+ ASSERT(owner != scratch1);
+ ASSERT(owner != scratch2);
+ ASSERT(scratch1 != scratch2);
- Jump notBoolean = branchIfNotBoolean(regs, tempGPR);
- functor(TypeofType::Boolean, false);
- notBoolean.link(this);
-
- functor(TypeofType::Undefined, true);
+#if ENABLE(WRITE_BARRIER_PROFILING)
+ emitCount(WriteBarrierCounters::jitCounterFor(useKind));
+#endif
}
Vector<BytecodeAndMachineOffset>& decodedCodeMapFor(CodeBlock*);
-
- void makeSpaceOnStackForCCall()
- {
- unsigned stackOffset = WTF::roundUpToMultipleOf(stackAlignmentBytes(), maxFrameExtentForSlowPathCall);
- if (stackOffset)
- subPtr(TrustedImm32(stackOffset), stackPointerRegister);
- }
-
- void reclaimSpaceOnStackForCCall()
- {
- unsigned stackOffset = WTF::roundUpToMultipleOf(stackAlignmentBytes(), maxFrameExtentForSlowPathCall);
- if (stackOffset)
- addPtr(TrustedImm32(stackOffset), stackPointerRegister);
- }
-
-#if USE(JSVALUE64)
- void emitRandomThunk(JSGlobalObject*, GPRReg scratch0, GPRReg scratch1, GPRReg scratch2, FPRReg result);
- void emitRandomThunk(GPRReg scratch0, GPRReg scratch1, GPRReg scratch2, GPRReg scratch3, FPRReg result);
-#endif
protected:
VM* m_vm;