xpcom/reflect/xptcall/src/md/unix/xptcinvoke_x86_64_unix.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     2  *
     3  * This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 // Platform specific code to invoke XPCOM methods on native objects
     9 #include "xptcprivate.h"
    11 // 6 integral parameters are passed in registers
    12 const uint32_t GPR_COUNT = 6;
    14 // 8 floating point parameters are passed in SSE registers
    15 const uint32_t FPR_COUNT = 8;
    17 // Remember that these 'words' are 64-bit long
    18 static inline void
    19 invoke_count_words(uint32_t paramCount, nsXPTCVariant * s,
    20                    uint32_t & nr_stack)
    21 {
    22     uint32_t nr_gpr;
    23     uint32_t nr_fpr;
    24     nr_gpr = 1; // skip one GP register for 'that'
    25     nr_fpr = 0;
    26     nr_stack = 0;
    28     /* Compute number of eightbytes of class MEMORY.  */
    29     for (uint32_t i = 0; i < paramCount; i++, s++) {
    30         if (!s->IsPtrData()
    31             && (s->type == nsXPTType::T_FLOAT || s->type == nsXPTType::T_DOUBLE)) {
    32             if (nr_fpr < FPR_COUNT)
    33                 nr_fpr++;
    34             else
    35                 nr_stack++;
    36         }
    37         else {
    38             if (nr_gpr < GPR_COUNT)
    39                 nr_gpr++;
    40             else
    41                 nr_stack++;
    42         }
    43     }
    44 }
    46 static void
    47 invoke_copy_to_stack(uint64_t * d, uint32_t paramCount, nsXPTCVariant * s,
    48                      uint64_t * gpregs, double * fpregs)
    49 {
    50     uint32_t nr_gpr = 1; // skip one GP register for 'that'
    51     uint32_t nr_fpr = 0;
    52     uint64_t value;
    54     for (uint32_t i = 0; i < paramCount; i++, s++) {
    55         if (s->IsPtrData())
    56             value = (uint64_t) s->ptr;
    57         else {
    58             switch (s->type) {
    59             case nsXPTType::T_FLOAT:                                break;
    60             case nsXPTType::T_DOUBLE:                               break;
    61             case nsXPTType::T_I8:     value = s->val.i8;            break;
    62             case nsXPTType::T_I16:    value = s->val.i16;           break;
    63             case nsXPTType::T_I32:    value = s->val.i32;           break;
    64             case nsXPTType::T_I64:    value = s->val.i64;           break;
    65             case nsXPTType::T_U8:     value = s->val.u8;            break;
    66             case nsXPTType::T_U16:    value = s->val.u16;           break;
    67             case nsXPTType::T_U32:    value = s->val.u32;           break;
    68             case nsXPTType::T_U64:    value = s->val.u64;           break;
    69             case nsXPTType::T_BOOL:   value = s->val.b;             break;
    70             case nsXPTType::T_CHAR:   value = s->val.c;             break;
    71             case nsXPTType::T_WCHAR:  value = s->val.wc;            break;
    72             default:                  value = (uint64_t) s->val.p;  break;
    73             }
    74         }
    76         if (!s->IsPtrData() && s->type == nsXPTType::T_DOUBLE) {
    77             if (nr_fpr < FPR_COUNT)
    78                 fpregs[nr_fpr++] = s->val.d;
    79             else {
    80                 *((double *)d) = s->val.d;
    81                 d++;
    82             }
    83         }
    84         else if (!s->IsPtrData() && s->type == nsXPTType::T_FLOAT) {
    85             if (nr_fpr < FPR_COUNT)
    86                 // The value in %xmm register is already prepared to
    87                 // be retrieved as a float. Therefore, we pass the
    88                 // value verbatim, as a double without conversion.
    89                 fpregs[nr_fpr++] = s->val.d;
    90             else {
    91                 *((float *)d) = s->val.f;
    92                 d++;
    93             }
    94         }
    95         else {
    96             if (nr_gpr < GPR_COUNT)
    97                 gpregs[nr_gpr++] = value;
    98             else
    99                 *d++ = value;
   100         }
   101     }
   102 }
   104 EXPORT_XPCOM_API(nsresult)
   105 NS_InvokeByIndex(nsISupports * that, uint32_t methodIndex,
   106                  uint32_t paramCount, nsXPTCVariant * params)
   107 {
   108     uint32_t nr_stack;
   109     invoke_count_words(paramCount, params, nr_stack);
   111     // Stack, if used, must be 16-bytes aligned
   112     if (nr_stack)
   113         nr_stack = (nr_stack + 1) & ~1;
   115     // Load parameters to stack, if necessary
   116     uint64_t *stack = (uint64_t *) __builtin_alloca(nr_stack * 8);
   117     uint64_t gpregs[GPR_COUNT];
   118     double fpregs[FPR_COUNT];
   119     invoke_copy_to_stack(stack, paramCount, params, gpregs, fpregs);
   121     // We used to have switches to make sure we would only load the registers
   122     // that are needed for this call. That produced larger code that was
   123     // not faster in practice. It also caused compiler warnings about the
   124     // variables being used uninitialized.
   125     // We now just load every every register. There could still be a warning
   126     // from a memory analysis tools that we are loading uninitialized stack
   127     // positions.
   129     // FIXME: this function depends on the above __builtin_alloca placing
   130     // the array in the correct spot for the ABI.
   132     // Load FPR registers from fpregs[]
   133     double d0, d1, d2, d3, d4, d5, d6, d7;
   135     d7 = fpregs[7];
   136     d6 = fpregs[6];
   137     d5 = fpregs[5];
   138     d4 = fpregs[4];
   139     d3 = fpregs[3];
   140     d2 = fpregs[2];
   141     d1 = fpregs[1];
   142     d0 = fpregs[0];
   144     // Load GPR registers from gpregs[]
   145     uint64_t a0, a1, a2, a3, a4, a5;
   147     a5 = gpregs[5];
   148     a4 = gpregs[4];
   149     a3 = gpregs[3];
   150     a2 = gpregs[2];
   151     a1 = gpregs[1];
   152     a0 = (uint64_t) that;
   154     // Get pointer to method
   155     uint64_t methodAddress = *((uint64_t *)that);
   156     methodAddress += 8 * methodIndex;
   157     methodAddress = *((uint64_t *)methodAddress);
   159     typedef nsresult (*Method)(uint64_t, uint64_t, uint64_t, uint64_t,
   160                                uint64_t, uint64_t, double, double, double,
   161                                double, double, double, double, double);
   162     nsresult result = ((Method)methodAddress)(a0, a1, a2, a3, a4, a5,
   163                                               d0, d1, d2, d3, d4, d5,
   164                                               d6, d7);
   165     return result;
   166 }

mercurial