Bug 258429 - "Crash at startup on mips" [sr=bsmedberg]
authorMike Hommey <mh+mozilla@glandium.org>
Mon, 20 Oct 2008 21:31:13 -0500
changeset 20694 23d35cd4547becabb678739f617974dbcec3ab7a
parent 20693 fba837242af0e1c35d7e3a9b7cc261d1bdf8e104
child 20696 4478b68ef1cf20dd9d4966928d921ee84f194219
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbsmedberg
bugs258429
milestone1.9.1b2pre
Bug 258429 - "Crash at startup on mips" [sr=bsmedberg]
configure.in
xpcom/reflect/xptcall/src/md/unix/Makefile.in
xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_mips.s
xpcom/reflect/xptcall/src/md/unix/xptcinvoke_mips.cpp
xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_mips.s
xpcom/reflect/xptcall/src/md/unix/xptcstubs_mips.cpp
--- a/configure.in
+++ b/configure.in
@@ -1849,18 +1849,17 @@ case "$target" in
     	CFLAGS="$CFLAGS -mieee"
     	CXXFLAGS="$CXXFLAGS -mieee"
     ;;
     i*86)
     	USE_ELF_DYNSTR_GC=1
         MOZ_ENABLE_OLD_ABI_COMPAT_WRAPPERS=1
     ;;
     mips*)
-        CFLAGS="$CFLAGS -Wa,-xgot"
-        CXXFLAGS="$CXXFLAGS -Wa,-xgot"
+        MOZ_DEBUG_FLAGS="-g" # We want inlining
     ;;
     esac
     ;;
 
 *-wince*)
 
     MOZ_TOOLS_DIR=`echo $MOZ_TOOLS`
     AR_LIST="$AR -list"
--- a/xpcom/reflect/xptcall/src/md/unix/Makefile.in
+++ b/xpcom/reflect/xptcall/src/md/unix/Makefile.in
@@ -271,21 +271,17 @@ CXXFLAGS	:= $(shell echo $(CXXFLAGS) | s
 endif
 endif
 endif
 
 ifeq ($(OS_ARCH),Linux)
 ifneq (,$(findstring mips, $(OS_TEST)))
 CPPSRCS		:= xptcinvoke_mips.cpp xptcstubs_mips.cpp
 ASFILES		:= xptcinvoke_asm_mips.s xptcstubs_asm_mips.s
-#xptcstubs_mips.cpp
-# xptcstubs_asm_mips.s
-ifdef GNU_CC
-ASFLAGS		+= $(INCLUDES) -x assembler-with-cpp -D__GNUC__
-endif
+ASFLAGS		+= -I$(PUBLIC) -x assembler-with-cpp
 endif
 endif
 
 ######################################################################
 # PowerPC
 ######################################################################
 #
 # AIX/PPC
@@ -461,20 +457,17 @@ DEFINES		+= -DEXPORT_XPTC_API -D_IMPL_NS
 
 LOCAL_INCLUDES += \
 	-I$(srcdir)/../.. \
 	-I$(srcdir)/../../../../xptinfo/src \
 	$(NULL)
 
 ifeq ($(OS_ARCH),Linux)
 ifneq (,$(findstring mips, $(OS_TEST)))
-xptcstubs_asm_mips.o: xptcstubs_asm_mips.s.m4 $(PUBLIC)/xptcstubsdef.inc
-	m4 $(INCLUDES) $< > ./xptcstubs_asm_mips.s && \
-	$(AS) -o $@ $(ASFLAGS) $(AS_DASH_C_FLAG) ./xptcstubs_asm_mips.s
-	$(RM) -f ./xptcstubs_asm_mips.s
+xptcstubs_asm_mips.o: $(PUBLIC)/xptcstubsdef.inc
 endif
 endif
 
 ifeq ($(OS_ARCH),Darwin)
 xptcstubs_asm_ppc_darwin.o: xptcstubs_asm_ppc_darwin.s.m4 $(PUBLIC)/xptcstubsdef.inc Makefile
 	gm4 $(INCLUDES) $< > ./xptcstubs_asm_ppc_darwin.s && \
 	$(AS) -o $@ $(ASFLAGS) $(AS_DASH_C_FLAG) ./xptcstubs_asm_ppc_darwin.s
 	$(RM) -f ./xptcstubs_asm_ppc_darwin.s
--- a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_mips.s
+++ b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_mips.s
@@ -19,16 +19,17 @@
  * The Initial Developer of the Original Code is
  * Netscape Communications Corp, Inc.
  * Portions created by the Initial Developer are Copyright (C) 2001
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Brendan Eich     <brendan@mozilla.org>
  *   Stuart Parmenter <pavlov@netscape.com>
+ *   Thiemo Seufer    <seufer@csv.ica.uni-stuttgart.de>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either 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
@@ -39,144 +40,128 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 /* This code is for MIPS using the O32 ABI. */
 
 #include <sys/regdef.h>
 #include <sys/asm.h>
 
-.text
-.globl  invoke_count_words
-.globl	invoke_copy_to_stack 
+# NARGSAVE is the argument space in the callers frame, including extra
+# 'shadowed' space for the argument registers. The minimum of 4
+# argument slots is sometimes predefined in the header files.
+#ifndef NARGSAVE
+#define NARGSAVE 4
+#endif
 
-# We need a variable number of words allocated from the stack for copies of
-# the params, and this space must come between the high frame (where ra, gp,
-# and s0 are saved) and the low frame (where a0-a3 are saved by the callee
-# functions we invoke). 
+#define LOCALSZ 3	/* gp, fp, ra */
+#define FRAMESZ ((((NARGSAVE+LOCALSZ)*SZREG)+ALSZ)&ALMASK)
 
-LOCALSZ=4		# s0, s1, ra, gp
-NARGSAVE=4		# a0, a1, a2, a3
-HIFRAMESZ=(LOCALSZ*SZREG)
-LOFRAMESZ=(NARGSAVE*SZREG)
-FRAMESZ=(HIFRAMESZ+LOFRAMESZ+ALSZ)&ALMASK
+#define RAOFF (FRAMESZ - (1*SZREG))
+#define FPOFF (FRAMESZ - (2*SZREG))
+#define GPOFF (FRAMESZ - (3*SZREG))
 
-# XXX these 2*SZREG, etc. are very magic -- we *know* that ALSZ&ALMASK cause
-# FRAMESZ to be 0 mod 8, in this case to be 16 and not 12.
-RAOFF=FRAMESZ - (2*SZREG)
-GPOFF=FRAMESZ - (3*SZREG)
-S0OFF=FRAMESZ - (4*SZREG)
-S1OFF=FRAMESZ - (5*SZREG)
+#define A0OFF (FRAMESZ + (0*SZREG))
+#define A1OFF (FRAMESZ + (1*SZREG))
+#define A2OFF (FRAMESZ + (2*SZREG))
+#define A3OFF (FRAMESZ + (3*SZREG))
+
+	.text
 
-# These are not magic -- they are just our argsave slots in the caller frame.
-A0OFF=FRAMESZ
-A1OFF=FRAMESZ + (1*SZREG)
-A2OFF=FRAMESZ + (2*SZREG)
-A3OFF=FRAMESZ + (3*SZREG)
+#	
+# _NS_InvokeByIndex_P(that, methodIndex, paramCount, params)
+#                      a0       a1          a2         a3
 
-	#	
-	# _XPTC_InvokeByIndex(that, methodIndex, paramCount, params)
-	#                      a0       a1          a2         a3
-
-NESTED(_XPTC_InvokeByIndex, FRAMESZ, ra)
-
-	.set	noreorder
-	.cpload	t9
-	.set	reorder
-
+	.globl	_NS_InvokeByIndex_P
+	.align	2
+	.type	_NS_InvokeByIndex_P,@function
+	.ent	_NS_InvokeByIndex_P,0
+	.frame	fp, FRAMESZ, ra
+_NS_InvokeByIndex_P:
+	SETUP_GP
 	subu	sp, FRAMESZ
 
-	# specify the save register mask -- XXX do we want the a0-a3 here, given
-	# our "split" frame where the args are saved below a dynamicly allocated
-	# region under the high frame?
-	#
-	# 10010000000000010000000011110000
-	.mask 0x900100F0, -((NARGSAVE+LOCALSZ)*SZREG)
+	# specify the save register mask for gp, fp, ra, a3 - a0
+	.mask 0xD00000F0, RAOFF-FRAMESZ
 
-	# thou shalt not use .cprestore if yer frame has variable size...
-	# .cprestore GPOFF
+	sw	ra, RAOFF(sp)
+	sw	fp, FPOFF(sp)
 
-	REG_S	ra, RAOFF(sp)
+	# we can't use .cprestore in a variable stack frame
+	sw	gp, GPOFF(sp)
 
-	# this happens automatically with .cprestore, but we cannot use that op...
-	REG_S	gp, GPOFF(sp)
-	REG_S	s0, S0OFF(sp)
-	REG_S	s1, S1OFF(sp)
+	sw	a0, A0OFF(sp)
+	sw	a1, A1OFF(sp)
+	sw	a2, A2OFF(sp)
+	sw	a3, A3OFF(sp)
 
-	REG_S	a0, A0OFF(sp)
-	REG_S	a1, A1OFF(sp)
-	REG_S	a2, A2OFF(sp)
-	REG_S	a3, A3OFF(sp)
+	# save bottom of fixed frame
+	move	fp, sp
 
-	# invoke_count_words(paramCount, params)
+	# extern "C" uint32
+	# invoke_count_words(PRUint32 paramCount, nsXPTCVariant* s);
+	la	t9, invoke_count_words
 	move	a0, a2
 	move	a1, a3
-
-	jal	invoke_count_words
-	lw	gp, GPOFF(sp)
+	jalr	t9
+	lw  	gp, GPOFF(fp)
 
-	# save the old sp so we can pop the param area and any "low frame"
-	# needed as an argsave area below the param block for callees that
-	# we invoke.
-	move	s0, sp
-
-	REG_L	a1, A2OFF(sp)	# a1 = paramCount
-	REG_L	a2, A3OFF(sp)	# a2 = params
+	# allocate variable stack, with a size of:
+	# wordsize (of 4 bytes) * result (already aligned to dword)
+	# but a minimum of 16 byte
+	sll	v0, 2
+	slt	t0, v0, 16
+	beqz	t0, 1f
+	li	v0, 16
+1:	subu	sp, v0
 
-	# we define a word as 4 bytes, period end of story!
-	sll	v0, 2		# 4 bytes * result of invoke_copy_words
-	subu	v0, LOFRAMESZ	# but we take back the argsave area built into
-				# our stack frame -- SWEET!
-	subu	sp, sp, v0	# make room
-	move	a0, sp		# a0 = param stack address
-	move	s1, a0		# save it for later -- it should be safe here
+	# let a0 point to the bottom of the variable stack, allocate
+	# another fixed stack for:
+	# extern "C" void
+	# invoke_copy_to_stack(PRUint32* d, PRUint32 paramCount,
+	#		       nsXPTCVariant* s);
+	la	t9, invoke_copy_to_stack
+	move	a0, sp
+	lw	a1, A2OFF(fp)
+	lw	a2, A3OFF(fp)
+	subu	sp, 16
+	jalr	t9
+	lw  	gp, GPOFF(fp)
 
-	# the old sp is still saved in s0, but we now need another argsave
-	# area ("low frame") for the invoke_copy_to_stack call.
-	subu	sp, sp, LOFRAMESZ
-
-	# copy the param into the stack areas
-	# invoke_copy_to_stack(PRUint32* d, PRUint32 paramCount,
-	#                      nsXPTCVariant* s)
-	jal     invoke_copy_to_stack
-	lw  	gp, GPOFF(s0)
-
-	move	sp, s0		# get orig sp back, popping params and argsave
-
-	REG_L	a0, A0OFF(sp)	# a0 = set "that" to be "this"
-	REG_L	a1, A1OFF(sp)	# a1 = methodIndex
+	# back to the variable stack frame
+	addu	sp, 16
 
-	# t1 = methodIndex * 4
-	# (use shift instead of mult)
-	sll	t1, a1, 2
-
-	# calculate the function we need to jump to,
-	# which must then be saved in t9
+	# calculate the function we need to jump to, which must then be
+	# stored in t9
+	lw	a0, A0OFF(fp)	# a0 = set "that" to be "this"
+	lw	t0, A1OFF(fp)	# a1 = methodIndex
 	lw	t9, 0(a0)
-	addu	t9, t9, t1
-	lw	t9, 8(t9)
-
-	# a1..a3 and f13..f14 should now be set to what
-	# invoke_copy_to_stack told us. skip a0 and f12
-	# because that is the "this" pointer
-
-	REG_L	a1, 1*SZREG(s1)
-	REG_L	a2, 2*SZREG(s1)
-	REG_L	a3, 3*SZREG(s1)
+	# t0 = methodIndex << PTRLOG
+	sll	t0, t0, PTRLOG
+	addu	t9, t0
+#if defined(__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100 /* G++ V3 ABI */
+	lw	t9, (t9)
+#else /* not G++ V3 ABI */
+	lw	t9, 2*PTRSIZE(t9)
+#endif /* G++ V3 ABI */
 
-	l.d	$f13, 8(s1)
-	l.d	$f14, 16(s1)
-
-	# Create the stack pointer for the function, which must have 4 words
-	# of space for callee-saved args.  invoke_count_words allocated space
-        # for a0 starting at s1, so we just move s1 into sp.
-	move	sp, s1
+	# Set a1-a3 to what invoke_copy_to_stack told us. a0 is already
+	# the "this" pointer. We don't have to care about floating
+	# point arguments, the non-FP "this" pointer as first argument
+	# means they'll never be used.
+	lw	a1, 1*SZREG(sp)
+	lw	a2, 2*SZREG(sp)
+	lw	a3, 3*SZREG(sp)
 
-	jalr	ra, t9
-	lw	gp, GPOFF(s0)
-
-	move	sp, s0
+	jalr	t9
+	# Micro-optimization: There's no gp usage below this point, so
+	# we don't reload.
+	# lw	gp, GPOFF(fp)
 
-	REG_L	ra, RAOFF(sp)
-	REG_L	s0, S0OFF(sp)
-	addu	sp, FRAMESZ
+	# leave variable stack frame
+	move	sp, fp
+
+	lw	ra, RAOFF(sp)
+	lw	fp, FPOFF(sp)
+
+	addiu	sp, FRAMESZ
 	j	ra
-.end _XPTC_InvokeByIndex
+END(_NS_InvokeByIndex_P)
--- a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_mips.cpp
+++ b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_mips.cpp
@@ -19,16 +19,17 @@
  * The Initial Developer of the Original Code is
  * Netscape Communications Corp, Inc.
  * Portions created by the Initial Developer are Copyright (C) 2001
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Stuart Parmenter <pavlov@netscape.com>
  *   Brendan Eich     <brendan@mozilla.org>
+ *   Thiemo Seufer    <seufer@csv.ica.uni-stuttgart.de>
  *
  * 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
@@ -47,32 +48,33 @@
 
 
 extern "C" uint32
 invoke_count_words(PRUint32 paramCount, nsXPTCVariant* s)
 {
     // Count a word for a0 even though it's never stored or loaded
     // We do this only for alignment of register pairs.
     PRUint32 result = 1;
-    for (PRUint32 i = 0; i < paramCount; i++, s++)
+    for (PRUint32 i = 0; i < paramCount; i++, result++, s++)
     {
-        result++;
-
         if (s->IsPtrData())
             continue;
 
         switch(s->type)
         {
         case nsXPTType::T_I64    :
         case nsXPTType::T_U64    :
         case nsXPTType::T_DOUBLE :
 	    if (result & 1)
 		result++;
 	    result++;
 	    break;
+
+        default:
+            break;
         }
     }
     return (result + 1) & ~(PRUint32)1;
 }
 
 extern "C" void
 invoke_copy_to_stack(PRUint32* d, PRUint32 paramCount,
                      nsXPTCVariant* s)
@@ -83,40 +85,39 @@ invoke_copy_to_stack(PRUint32* d, PRUint
     for (PRUint32 i = 0; i < paramCount; i++, d++, s++)
     {
         if (s->IsPtrData())
         {
             *((void**)d) = s->ptr;
             continue;
         }
 
-        *((void**)d) = s->val.p;
-
         switch(s->type)
         {
         case nsXPTType::T_I64    :
             if ((PRWord)d & 4) d++;
             *((PRInt64*) d)  = s->val.i64;    d++;
             break;
         case nsXPTType::T_U64    :
             if ((PRWord)d & 4) d++;
             *((PRUint64*) d) = s->val.u64;    d++;
             break;
         case nsXPTType::T_DOUBLE :
             if ((PRWord)d & 4) d++;
             *((double*)   d) = s->val.d;      d++;
             break;
+        default:
+            *((void**)d) = s->val.p;
+            break;
         }
     }
 }
 
-extern "C" nsresult _XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+extern "C" nsresult _NS_InvokeByIndex_P(nsISupports* that, PRUint32 methodIndex,
                                         PRUint32 paramCount,
                                         nsXPTCVariant* params);
 
-extern "C"
-XPTC_PUBLIC_API(nsresult)
-XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+EXPORT_XPCOM_API(nsresult)
+NS_InvokeByIndex_P(nsISupports* that, PRUint32 methodIndex,
                    PRUint32 paramCount, nsXPTCVariant* params)
 {
-    return _XPTC_InvokeByIndex(that, methodIndex, paramCount, params);
-}    
-
+    return _NS_InvokeByIndex_P(that, methodIndex, paramCount, params);
+}
new file mode 100644
--- /dev/null
+++ b/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_mips.s
@@ -0,0 +1,142 @@
+/* -*- Mode: asm; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * Version: MPL 1.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.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corp, Inc.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Stuart Parmenter <pavlov@netscape.com>
+ *   Chris Waterson   <waterson@netscape.com>
+ *   Thiemo Seufer    <seufer@csv.ica.uni-stuttgart.de>
+ */
+
+/* This code is for MIPS using the O32 ABI. */
+
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+# NARGSAVE is the argument space in the callers frame, including extra
+# 'shadowed' space for the argument registers. The minimum of 4
+# argument slots is sometimes predefined in the header files.
+#ifndef NARGSAVE
+#define NARGSAVE 4
+#endif
+
+#define LOCALSZ 2	/* gp, ra */
+#define FRAMESZ ((((NARGSAVE+LOCALSZ)*SZREG)+ALSZ)&ALMASK)
+
+#define RAOFF (FRAMESZ - (1*SZREG))
+#define GPOFF (FRAMESZ - (2*SZREG))
+
+#define A0OFF (FRAMESZ + (0*SZREG))
+#define A1OFF (FRAMESZ + (1*SZREG))
+#define A2OFF (FRAMESZ + (2*SZREG))
+#define A3OFF (FRAMESZ + (3*SZREG))
+
+	.text
+
+#if defined(__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100 /* G++ V3 ABI */
+#define STUB_ENTRY(x)						\
+	.if x < 10;						\
+	.globl	_ZN14nsXPTCStubBase5Stub ##x ##Ev;		\
+	.type	_ZN14nsXPTCStubBase5Stub ##x ##Ev,@function;	\
+	.aent	_ZN14nsXPTCStubBase5Stub ##x ##Ev,0;		\
+_ZN14nsXPTCStubBase5Stub ##x ##Ev:;				\
+	SETUP_GP;						\
+	li	t0,x;						\
+	b	sharedstub;					\
+	.elseif x < 100;					\
+	.globl	_ZN14nsXPTCStubBase6Stub ##x ##Ev;		\
+	.type	_ZN14nsXPTCStubBase6Stub ##x ##Ev,@function;	\
+	.aent	_ZN14nsXPTCStubBase6Stub ##x ##Ev,0;		\
+_ZN14nsXPTCStubBase6Stub ##x ##Ev:;				\
+	SETUP_GP;						\
+	li	t0,x;						\
+	b	sharedstub;					\
+	.elseif x < 1000;					\
+	.globl	_ZN14nsXPTCStubBase7Stub ##x ##Ev;		\
+	.type	_ZN14nsXPTCStubBase7Stub ##x ##Ev,@function;	\
+	.aent	_ZN14nsXPTCStubBase7Stub ##x ##Ev,0;		\
+_ZN14nsXPTCStubBase7Stub ##x ##Ev:;				\
+	SETUP_GP;						\
+	li	t0,x;						\
+	b	sharedstub;					\
+	.else;							\
+	.err;							\
+	.endif
+#else /* not G++ V3 ABI */
+#define STUB_ENTRY(x)						\
+	.globl	Stub ##x ##__14nsXPTCStubBase;			\
+	.type	Stub ##x ##__14nsXPTCStubBase,@function;	\
+	.aent	Stub ##x ##__14nsXPTCStubBase,0;		\
+Stub ##x ##__14nsXPTCStubBase:;					\
+	SETUP_GP;						\
+	li	t0,x;						\
+	b	sharedstub
+#endif /* G++ V3 ABI */
+
+# SENTINEL_ENTRY is handled in the cpp file.
+#define SENTINEL_ENTRY(x)
+
+#
+# open a dummy frame for the function entries
+#
+	.align	2
+	.type	dummy,@function
+	.ent	dummy, 0
+	.frame	sp, FRAMESZ, ra 
+dummy:
+	SETUP_GP
+
+#include "xptcstubsdef.inc"
+
+sharedstub:
+	subu	sp, FRAMESZ
+
+	# specify the save register mask for gp, ra, a0-a3
+	.mask 0x900000F0, RAOFF-FRAMESZ
+
+	sw	ra, RAOFF(sp)
+	SAVE_GP(GPOFF)
+
+	# Micro-optimization: a0 is already loaded, and its slot gets
+	# ignored by PrepareAndDispatch, so no need to save it here.
+	# sw	a0, A0OFF(sp)
+	sw	a1, A1OFF(sp)
+	sw	a2, A2OFF(sp)
+	sw	a3, A3OFF(sp)
+
+	la	t9, PrepareAndDispatch
+
+	# t0 is methodIndex
+	move	a1, t0
+	# have a2 point to the begin of the argument space on stack
+	addiu	a2, sp, FRAMESZ
+
+	# PrepareAndDispatch(that, methodIndex, args)
+	jalr	t9
+
+	# Micro-optimization: Using jalr explicitly has the side-effect
+	# of not triggering .cprestore. This is ok because we have no
+	# gp reference below this point. It also allows better
+	# instruction sscheduling.
+	# lw	gp, GPOFF(fp)
+ 
+ 	lw	ra, RAOFF(sp)
+	addiu	sp, FRAMESZ
+	j	ra
+	END(dummy)
--- a/xpcom/reflect/xptcall/src/md/unix/xptcstubs_mips.cpp
+++ b/xpcom/reflect/xptcall/src/md/unix/xptcstubs_mips.cpp
@@ -34,44 +34,41 @@
  * 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 ***** */
 
 #include "xptcprivate.h"
+#include "xptiprivate.h"
 
 /*
  * This is for MIPS O32 ABI
  * Args contains a0-3 and then the stack.
  * Because a0 is 'this', we want to skip it
  */
 extern "C" nsresult
 PrepareAndDispatch(nsXPTCStubBase* self, PRUint32 methodIndex, PRUint32* args)
 {
     args++; // always skip over a0
 
 #define PARAM_BUFFER_COUNT		16
 
     nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
     nsXPTCMiniVariant* dispatchParams = NULL;
-    nsIInterfaceInfo* iface_info = NULL;
     const nsXPTMethodInfo* info;
     PRUint8 paramCount;
     PRUint8 i;
     nsresult result = NS_ERROR_FAILURE;
 
     NS_ASSERTION(self,"no self");
 
-    self->GetInterfaceInfo(&iface_info);
-    NS_ASSERTION(iface_info,"no interface info");
-
-    iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
-    NS_ASSERTION(info,"no interface info");
+    self->mEntry->GetMethodInfo(PRUint16(methodIndex), &info);
+    NS_ASSERTION(info,"no method info");
 
     paramCount = info->GetParamCount();
 
     // setup variant array pointer
     if(paramCount > PARAM_BUFFER_COUNT)
         dispatchParams = new nsXPTCMiniVariant[paramCount];
     else
         dispatchParams = paramBuffer;
@@ -104,19 +101,17 @@ PrepareAndDispatch(nsXPTCStubBase* self,
             break;
         case nsXPTType::T_DOUBLE:
             if ((PRWord)ap & 4) ap++;
             dp->val.d   = *((double*) ap);  ap++;
             break;
         }
     }
 
-    result = self->CallMethod((PRUint16)methodIndex, info, dispatchParams);
-
-    NS_RELEASE(iface_info);
+    result = self->mOuter->CallMethod((PRUint16)methodIndex, info, dispatchParams);
 
     if(dispatchParams != paramBuffer)
         delete [] dispatchParams;
 
     return result;
 }
 
 #define STUB_ENTRY(n) // done in the .s file