mirror of
https://github.com/UOX3DevTeam/UOX3
synced 2026-08-13 12:27:04 -04:00
508 lines
16 KiB
C++
508 lines
16 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
|
* vim: set ts=4 sw=4 et tw=99:
|
|
*
|
|
* ***** BEGIN LICENSE BLOCK *****
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
*
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
* the License. You may obtain a copy of the License at
|
|
* http://www.mozilla.org/MPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
* for the specific language governing rights and limitations under the
|
|
* License.
|
|
*
|
|
* The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
|
|
* May 28, 2008.
|
|
*
|
|
* The Initial Developer of the Original Code is
|
|
* Brendan Eich <brendan@mozilla.org>
|
|
*
|
|
* Contributor(s):
|
|
* David Mandelin <dmandelin@mozilla.com>
|
|
* David Anderson <danderson@mozilla.com>
|
|
* Chris Leary <cdleary@mozilla.com>
|
|
* Jacob Bramley <Jacob.Bramely@arm.com>
|
|
*
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
|
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
* use your version of this file under the terms of the MPL, indicate your
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
* the provisions above, a recipient may use your version of this file under
|
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
*
|
|
* ***** END LICENSE BLOCK ***** */
|
|
|
|
#if !defined jsjaeger_ic_labels_h__ && defined JS_METHODJIT
|
|
#define jsjaeger_ic_labels_h__
|
|
|
|
#include "methodjit/BaseCompiler.h"
|
|
|
|
class ICOffsetInitializer {
|
|
public:
|
|
ICOffsetInitializer();
|
|
};
|
|
|
|
namespace js {
|
|
namespace mjit {
|
|
namespace ic {
|
|
|
|
/*
|
|
* On x64 and ARM, we record offsets into the labels data structures at runtime
|
|
* instead of using hardcoded offsets into the instruction stream, as we do on
|
|
* x86.
|
|
*
|
|
* This is done on x64 because of variable-width instruction encoding when
|
|
* using the extended register set. It is done on ARM for ease of
|
|
* implementation.
|
|
*/
|
|
|
|
#if defined JS_CPU_X64 || defined JS_CPU_ARM
|
|
# define JS_HAS_IC_LABELS
|
|
#endif
|
|
|
|
/* GetPropCompiler */
|
|
struct GetPropLabels : MacroAssemblerTypedefs {
|
|
friend class ::ICOffsetInitializer;
|
|
|
|
void setValueLoad(MacroAssembler &masm, Label fastPathRejoin, Label fastValueLoad) {
|
|
int offset = masm.differenceBetween(fastPathRejoin, fastValueLoad);
|
|
#ifdef JS_HAS_IC_LABELS
|
|
inlineValueLoadOffset = offset;
|
|
#endif
|
|
/*
|
|
* Note: the offset between the type and data loads for x86 is asserted
|
|
* in NunboxAssembler::loadValueWithAddressOffsetPatch.
|
|
*/
|
|
JS_ASSERT(offset == inlineValueLoadOffset);
|
|
(void) offset;
|
|
}
|
|
|
|
CodeLocationLabel getValueLoad(CodeLocationLabel fastPathRejoin) {
|
|
return fastPathRejoin.labelAtOffset(inlineValueLoadOffset);
|
|
}
|
|
|
|
void setDslotsLoad(MacroAssembler &masm, Label fastPathRejoin, Label dslotsLoad) {
|
|
int offset = masm.differenceBetween(fastPathRejoin, dslotsLoad);
|
|
setDslotsLoadOffset(offset);
|
|
}
|
|
|
|
CodeLocationInstruction getDslotsLoad(CodeLocationLabel fastPathRejoin) {
|
|
return fastPathRejoin.instructionAtOffset(getDslotsLoadOffset());
|
|
}
|
|
|
|
void setInlineShapeData(MacroAssembler &masm, Label shapeGuard, DataLabel32 inlineShape) {
|
|
int offset = masm.differenceBetween(shapeGuard, inlineShape);
|
|
setInlineShapeOffset(offset);
|
|
}
|
|
|
|
CodeLocationDataLabel32 getInlineShapeData(CodeLocationLabel fastShapeGuard) {
|
|
return fastShapeGuard.dataLabel32AtOffset(getInlineShapeOffset());
|
|
}
|
|
|
|
/*
|
|
* Note: on x64, the base is the inlineShapeLabel DataLabel32, whereas on other
|
|
* platforms the base is the shapeGuard.
|
|
*/
|
|
template <typename T>
|
|
void setInlineShapeJump(MacroAssembler &masm, T base, Label afterJump) {
|
|
setInlineShapeJumpOffset(masm.differenceBetween(base, afterJump));
|
|
}
|
|
|
|
CodeLocationJump getInlineShapeJump(CodeLocationLabel fastShapeGuard) {
|
|
return fastShapeGuard.jumpAtOffset(getInlineShapeJumpOffset());
|
|
}
|
|
|
|
void setInlineTypeJump(MacroAssembler &masm, Label fastPathStart, Label afterTypeJump) {
|
|
int offset = masm.differenceBetween(fastPathStart, afterTypeJump);
|
|
setInlineTypeJumpOffset(offset);
|
|
}
|
|
|
|
CodeLocationJump getInlineTypeJump(CodeLocationLabel fastPathStart) {
|
|
return fastPathStart.jumpAtOffset(getInlineTypeJumpOffset());
|
|
}
|
|
|
|
void setStubShapeJump(MacroAssembler &masm, Label stubStart, Label shapeJump) {
|
|
int offset = masm.differenceBetween(stubStart, shapeJump);
|
|
setStubShapeJumpOffset(offset);
|
|
}
|
|
|
|
/* Offset-based interface */
|
|
|
|
void setDslotsLoadOffset(int offset) {
|
|
#ifdef JS_HAS_IC_LABELS
|
|
dslotsLoadOffset = offset;
|
|
#endif
|
|
JS_ASSERT(offset == dslotsLoadOffset);
|
|
}
|
|
|
|
void setInlineShapeOffset(int offset) {
|
|
#ifdef JS_HAS_IC_LABELS
|
|
inlineShapeOffset = offset;
|
|
#endif
|
|
JS_ASSERT(offset == inlineShapeOffset);
|
|
}
|
|
|
|
void setStubShapeJumpOffset(int offset) {
|
|
#ifdef JS_HAS_IC_LABELS
|
|
stubShapeJumpOffset = offset;
|
|
#endif
|
|
JS_ASSERT(offset == stubShapeJumpOffset);
|
|
}
|
|
|
|
int getInlineShapeJumpOffset() {
|
|
#if defined JS_CPU_X64
|
|
return getInlineShapeOffset() + INLINE_SHAPE_JUMP;
|
|
#else
|
|
return POST_INST_OFFSET(INLINE_SHAPE_JUMP);
|
|
#endif
|
|
}
|
|
|
|
void setInlineShapeJumpOffset(int offset) {
|
|
JS_ASSERT(INLINE_SHAPE_JUMP == offset);
|
|
}
|
|
|
|
int getInlineTypeJumpOffset() {
|
|
#if defined JS_CPU_X86 || defined JS_CPU_X64
|
|
return INLINE_TYPE_JUMP;
|
|
#elif defined JS_CPU_ARM
|
|
return POST_INST_OFFSET(inlineTypeJumpOffset);
|
|
#endif
|
|
}
|
|
|
|
void setInlineTypeJumpOffset(int offset) {
|
|
#if defined JS_CPU_X86 || defined JS_CPU_X64
|
|
JS_ASSERT(INLINE_TYPE_JUMP == offset);
|
|
#elif defined JS_CPU_ARM
|
|
inlineTypeJumpOffset = offset;
|
|
JS_ASSERT(offset == inlineTypeJumpOffset);
|
|
#endif
|
|
}
|
|
|
|
int getInlineShapeOffset() {
|
|
return inlineShapeOffset;
|
|
}
|
|
int getDslotsLoadOffset() {
|
|
return dslotsLoadOffset;
|
|
}
|
|
int getStubShapeJumpOffset() {
|
|
return POST_INST_OFFSET(stubShapeJumpOffset);
|
|
}
|
|
|
|
private:
|
|
/* Offset from storeBack to beginning of 'mov dslots, addr' */
|
|
int32 dslotsLoadOffset : 8;
|
|
|
|
/* Offset from shapeGuard to end of shape comparison. */
|
|
int32 inlineShapeOffset : 8;
|
|
|
|
/* Offset from storeBack to end of value load. */
|
|
int32 inlineValueLoadOffset : 8;
|
|
|
|
/*
|
|
* Offset from lastStubStart to end of shape jump.
|
|
* TODO: We can redefine the location of lastStubStart to be
|
|
* after the jump -- at which point this is always 0.
|
|
*/
|
|
int32 stubShapeJumpOffset : 8;
|
|
|
|
#if defined JS_CPU_X86
|
|
static const int32 INLINE_SHAPE_JUMP = 12;
|
|
static const int32 INLINE_TYPE_JUMP = 12;
|
|
#elif defined JS_CPU_X64
|
|
static const int32 INLINE_SHAPE_JUMP = 6;
|
|
static const int32 INLINE_TYPE_JUMP = 19;
|
|
#elif defined JS_CPU_ARM
|
|
/* Offset from the shape guard start to the shape guard jump. */
|
|
static const int32 INLINE_SHAPE_JUMP = 12;
|
|
|
|
/* Offset from the fast path to the type guard jump. */
|
|
int32 inlineTypeJumpOffset : 8;
|
|
#endif
|
|
};
|
|
|
|
/* SetPropCompiler */
|
|
struct SetPropLabels : MacroAssemblerTypedefs {
|
|
friend class ::ICOffsetInitializer;
|
|
|
|
void setInlineValueStore(MacroAssembler &masm, Label fastPathRejoin, DataLabel32 inlineValueStore,
|
|
const ValueRemat &vr) {
|
|
int offset = masm.differenceBetween(fastPathRejoin, inlineValueStore);
|
|
setInlineValueStoreOffset(offset, vr.isConstant(), vr.isTypeKnown());
|
|
}
|
|
|
|
CodeLocationLabel getInlineValueStore(CodeLocationLabel fastPathRejoin, const ValueRemat &vr) {
|
|
return fastPathRejoin.labelAtOffset(getInlineValueStoreOffset(vr.isConstant(),
|
|
vr.isTypeKnown()));
|
|
}
|
|
|
|
void setInlineShapeData(MacroAssembler &masm, Label shapeGuard, DataLabel32 inlineShapeData) {
|
|
int offset = masm.differenceBetween(shapeGuard, inlineShapeData);
|
|
setInlineShapeDataOffset(offset);
|
|
}
|
|
|
|
CodeLocationDataLabel32 getInlineShapeData(CodeLocationLabel fastPathStart, int shapeGuardOffset) {
|
|
return fastPathStart.dataLabel32AtOffset(shapeGuardOffset + getInlineShapeDataOffset());
|
|
}
|
|
|
|
void setDslotsLoad(MacroAssembler &masm, Label fastPathRejoin, Label beforeLoad,
|
|
const ValueRemat &rhs) {
|
|
int offset = masm.differenceBetween(fastPathRejoin, beforeLoad);
|
|
setDslotsLoadOffset(offset, rhs.isConstant(), rhs.isTypeKnown());
|
|
}
|
|
|
|
CodeLocationInstruction getDslotsLoad(CodeLocationLabel fastPathRejoin, const ValueRemat &vr) {
|
|
return fastPathRejoin.instructionAtOffset(getDslotsLoadOffset(vr));
|
|
}
|
|
|
|
void setInlineShapeJump(MacroAssembler &masm, Label shapeGuard, Label afterJump) {
|
|
setInlineShapeJumpOffset(masm.differenceBetween(shapeGuard, afterJump));
|
|
}
|
|
|
|
CodeLocationJump getInlineShapeJump(CodeLocationLabel shapeGuard) {
|
|
return shapeGuard.jumpAtOffset(getInlineShapeJumpOffset());
|
|
}
|
|
|
|
void setStubShapeJump(MacroAssembler &masm, Label stubStart, Label afterShapeJump) {
|
|
int offset = masm.differenceBetween(stubStart, afterShapeJump);
|
|
setStubShapeJumpOffset(offset);
|
|
}
|
|
|
|
CodeLocationJump getStubShapeJump(CodeLocationLabel stubStart) {
|
|
return stubStart.jumpAtOffset(getStubShapeJumpOffset());
|
|
}
|
|
|
|
private:
|
|
|
|
/* Offset-based interface. */
|
|
|
|
void setDslotsLoadOffset(int offset, bool isConstant, bool isTypeKnown) {
|
|
#if defined JS_HAS_IC_LABELS
|
|
dslotsLoadOffset = offset;
|
|
JS_ASSERT(offset == dslotsLoadOffset);
|
|
#elif defined JS_CPU_X86
|
|
JS_ASSERT_IF(isConstant, offset == INLINE_DSLOTS_BEFORE_CONSTANT);
|
|
JS_ASSERT_IF(isTypeKnown && !isConstant, offset == INLINE_DSLOTS_BEFORE_KTYPE);
|
|
JS_ASSERT_IF(!isTypeKnown, offset == INLINE_DSLOTS_BEFORE_DYNAMIC);
|
|
#else
|
|
# error
|
|
#endif
|
|
}
|
|
|
|
int getDslotsLoadOffset(const ValueRemat &vr) {
|
|
#if defined JS_CPU_X86
|
|
if (vr.isConstant())
|
|
return INLINE_DSLOTS_BEFORE_CONSTANT;
|
|
if (vr.isTypeKnown())
|
|
return INLINE_DSLOTS_BEFORE_KTYPE;
|
|
return INLINE_DSLOTS_BEFORE_DYNAMIC;
|
|
#else
|
|
(void) vr;
|
|
return dslotsLoadOffset;
|
|
#endif
|
|
}
|
|
|
|
void setInlineShapeDataOffset(int offset) {
|
|
#ifdef JS_HAS_IC_LABELS
|
|
inlineShapeDataOffset = offset;
|
|
#endif
|
|
JS_ASSERT(offset == inlineShapeDataOffset);
|
|
}
|
|
|
|
void setStubShapeJumpOffset(int offset) {
|
|
#ifdef JS_HAS_IC_LABELS
|
|
stubShapeJumpOffset = offset;
|
|
#endif
|
|
JS_ASSERT(offset == stubShapeJumpOffset);
|
|
}
|
|
|
|
void setInlineValueStoreOffset(int offset, bool isConstant, bool isTypeKnown) {
|
|
#ifdef JS_HAS_IC_LABELS
|
|
inlineValueStoreOffset = offset;
|
|
JS_ASSERT(offset == inlineValueStoreOffset);
|
|
#elif defined JS_CPU_X86
|
|
JS_ASSERT_IF(isConstant, offset == INLINE_VALUE_STORE_CONSTANT);
|
|
JS_ASSERT_IF(isTypeKnown && !isConstant, offset == INLINE_VALUE_STORE_KTYPE);
|
|
JS_ASSERT_IF(!isTypeKnown && !isConstant, offset == INLINE_VALUE_STORE_DYNAMIC);
|
|
#endif
|
|
}
|
|
|
|
void setInlineShapeJumpOffset(int offset) {
|
|
#ifdef JS_HAS_IC_LABELS
|
|
inlineShapeJumpOffset = offset;
|
|
#endif
|
|
JS_ASSERT(offset == inlineShapeJumpOffset);
|
|
}
|
|
|
|
int getInlineShapeJumpOffset() {
|
|
return POST_INST_OFFSET(inlineShapeJumpOffset);
|
|
}
|
|
|
|
int getInlineShapeDataOffset() {
|
|
return inlineShapeDataOffset;
|
|
}
|
|
|
|
int getStubShapeJumpOffset() {
|
|
return POST_INST_OFFSET(stubShapeJumpOffset);
|
|
}
|
|
|
|
int getInlineValueStoreOffset(bool isConstant, bool isTypeKnown) {
|
|
#ifdef JS_HAS_IC_LABELS
|
|
return inlineValueStoreOffset;
|
|
#elif defined JS_CPU_X86
|
|
if (isConstant)
|
|
return INLINE_VALUE_STORE_CONSTANT;
|
|
else if (isTypeKnown)
|
|
return INLINE_VALUE_STORE_KTYPE;
|
|
else
|
|
return INLINE_VALUE_STORE_DYNAMIC;
|
|
#endif
|
|
}
|
|
|
|
/* Offset from storeBack to beginning of 'mov dslots, addr'. */
|
|
#if defined JS_CPU_X86
|
|
static const int INLINE_DSLOTS_BEFORE_CONSTANT = -23;
|
|
static const int INLINE_DSLOTS_BEFORE_KTYPE = -19;
|
|
static const int INLINE_DSLOTS_BEFORE_DYNAMIC = -15;
|
|
#else
|
|
int32 dslotsLoadOffset : 8;
|
|
#endif
|
|
|
|
/* Offset from shapeGuard to end of shape comparison. */
|
|
int32 inlineShapeDataOffset : 8;
|
|
|
|
/*
|
|
* Offset from lastStubStart to end of shape jump.
|
|
* TODO: We can redefine the location of lastStubStart to be
|
|
* after the jump -- at which point this is always 0.
|
|
*/
|
|
int32 stubShapeJumpOffset : 8;
|
|
|
|
#if defined JS_CPU_X86
|
|
static const int INLINE_VALUE_STORE_CONSTANT = -20;
|
|
static const int INLINE_VALUE_STORE_KTYPE = -16;
|
|
static const int INLINE_VALUE_STORE_DYNAMIC = -12;
|
|
#else
|
|
int32 inlineValueStoreOffset : 8;
|
|
#endif
|
|
|
|
/* Offset from shapeGuard to the end of the shape jump. */
|
|
int32 inlineShapeJumpOffset : 8;
|
|
};
|
|
|
|
/* BindNameCompiler */
|
|
struct BindNameLabels : MacroAssemblerTypedefs {
|
|
friend class ::ICOffsetInitializer;
|
|
|
|
void setInlineJumpOffset(int offset) {
|
|
#ifdef JS_HAS_IC_LABELS
|
|
inlineJumpOffset = offset;
|
|
#endif
|
|
JS_ASSERT(offset == inlineJumpOffset);
|
|
}
|
|
|
|
void setInlineJump(MacroAssembler &masm, Label shapeGuard, Jump inlineJump) {
|
|
int offset = masm.differenceBetween(shapeGuard, inlineJump);
|
|
setInlineJumpOffset(offset);
|
|
}
|
|
|
|
CodeLocationJump getInlineJump(CodeLocationLabel fastPathStart) {
|
|
return fastPathStart.jumpAtOffset(getInlineJumpOffset());
|
|
}
|
|
|
|
int getInlineJumpOffset() {
|
|
return inlineJumpOffset;
|
|
}
|
|
|
|
void setStubJumpOffset(int offset) {
|
|
#ifdef JS_HAS_IC_LABELS
|
|
stubJumpOffset = offset;
|
|
#endif
|
|
JS_ASSERT(offset == stubJumpOffset);
|
|
}
|
|
|
|
void setStubJump(MacroAssembler &masm, Label stubStart, Jump stubJump) {
|
|
int offset = masm.differenceBetween(stubStart, stubJump);
|
|
setStubJumpOffset(offset);
|
|
}
|
|
|
|
CodeLocationJump getStubJump(CodeLocationLabel lastStubStart) {
|
|
return lastStubStart.jumpAtOffset(getStubJumpOffset());
|
|
}
|
|
|
|
int getStubJumpOffset() {
|
|
return stubJumpOffset;
|
|
}
|
|
|
|
private:
|
|
/* Offset from shapeGuard to end of shape jump. */
|
|
int32 inlineJumpOffset : 8;
|
|
|
|
/* Offset from lastStubStart to end of the shape jump. */
|
|
int32 stubJumpOffset : 8;
|
|
};
|
|
|
|
/* ScopeNameCompiler */
|
|
struct ScopeNameLabels : MacroAssemblerTypedefs {
|
|
friend class ::ICOffsetInitializer;
|
|
|
|
void setInlineJumpOffset(int offset) {
|
|
#ifdef JS_HAS_IC_LABELS
|
|
inlineJumpOffset = offset;
|
|
#endif
|
|
JS_ASSERT(offset == inlineJumpOffset);
|
|
}
|
|
|
|
void setInlineJump(MacroAssembler &masm, Label fastPathStart, Jump inlineJump) {
|
|
int offset = masm.differenceBetween(fastPathStart, inlineJump);
|
|
setInlineJumpOffset(offset);
|
|
}
|
|
|
|
CodeLocationJump getInlineJump(CodeLocationLabel fastPathStart) {
|
|
return fastPathStart.jumpAtOffset(getInlineJumpOffset());
|
|
}
|
|
|
|
int getInlineJumpOffset() {
|
|
return inlineJumpOffset;
|
|
}
|
|
|
|
void setStubJumpOffset(int offset) {
|
|
#ifdef JS_HAS_IC_LABELS
|
|
stubJumpOffset = offset;
|
|
#endif
|
|
JS_ASSERT(offset == stubJumpOffset);
|
|
}
|
|
|
|
void setStubJump(MacroAssembler &masm, Label stubStart, Jump stubJump) {
|
|
int offset = masm.differenceBetween(stubStart, stubJump);
|
|
setStubJumpOffset(offset);
|
|
}
|
|
|
|
CodeLocationJump getStubJump(CodeLocationLabel lastStubStart) {
|
|
return lastStubStart.jumpAtOffset(getStubJumpOffset());
|
|
}
|
|
|
|
int getStubJumpOffset() {
|
|
return stubJumpOffset;
|
|
}
|
|
|
|
private:
|
|
/* Offset from fastPathStart to end of shape jump. */
|
|
int32 inlineJumpOffset : 8;
|
|
|
|
/* Offset from lastStubStart to end of the shape jump. */
|
|
int32 stubJumpOffset : 8;
|
|
};
|
|
|
|
} /* namespace ic */
|
|
} /* namespace mjit */
|
|
} /* namespace js */
|
|
|
|
#endif /* jsjaeger_ic_labels_h__ */
|