summaryrefslogtreecommitdiff
path: root/js/src/methodjit/ICLabels.h
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/methodjit/ICLabels.h')
-rw-r--r--js/src/methodjit/ICLabels.h508
1 files changed, 508 insertions, 0 deletions
diff --git a/js/src/methodjit/ICLabels.h b/js/src/methodjit/ICLabels.h
new file mode 100644
index 0000000..cddcf7a
--- /dev/null
+++ b/js/src/methodjit/ICLabels.h
@@ -0,0 +1,508 @@
+/* -*- 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__ */