~ubuntu-branches/debian/sid/iceweasel/sid

« back to all changes in this revision

Viewing changes to .pc/porting/Bug-589735-Allow-static-JS-strings-to-be-turned-off-.patch/js/src/tracejit/Writer.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Mike Hommey
  • Date: 2011-08-26 09:48:52 UTC
  • Revision ID: james.westby@ubuntu.com-20110826094852-9kt0erj7rc2jgf3i
Tags: 6.0-3
* debian/libmozjs-dev.install: Add more missing headers to libmozjs-dev.
* debian/rules, debian/xulrunner-GRE_VERSION.install.in: Install
  plugin-container on all architectures. Closes: #639289.
* debian/extra-stuff/reportbug-helper-script: Avoid listing all debian
  packages in the reportbug helper when no addons are installed.
* debian/duckduckgo.xml, debian/iceweasel.install: Add DuckDuckGo search
  plugin. Closes: #616115.

* js/src/jsgcinlines.h, js/src/jsnum.cpp, js/src/jsstr.cpp, js/src/jsstr.h,
  js/src/jsstrinlines.h, js/src/jstracer.cpp, js/src/jstracer.h,
  js/src/tracejit/Writer.cpp: Allow static JS strings to be turned off;
  turn off on ia64. bz#589735.
* memory/jemalloc/jemalloc.c: Allocate memory with an address with high 17
  bits clear on ia64. bz#589735. This should finally make Iceweasel
  actually work on ia64.
* js/src/jsval.h, js/src/jsvalue.h: Fix jsval_layout on 64-bit big-endian
  platforms. bz#674522. Closes: #638623.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
 
2
 * vim: set ts=4 sw=4 et tw=99 ft=cpp:
 
3
 *
 
4
 * ***** BEGIN LICENSE BLOCK *****
 
5
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 
6
 *
 
7
 * The contents of this file are subject to the Mozilla Public License Version
 
8
 * 1.1 (the "License"); you may not use this file except in compliance with
 
9
 * the License. You may obtain a copy of the License at
 
10
 * http://www.mozilla.org/MPL/
 
11
 *
 
12
 * Software distributed under the License is distributed on an "AS IS" basis,
 
13
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 
14
 * for the specific language governing rights and limitations under the
 
15
 * License.
 
16
 *
 
17
 * The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
 
18
 * May 28, 2008.
 
19
 *
 
20
 * The Initial Developer of the Original Code is
 
21
 *   the Mozilla Corporation.
 
22
 *
 
23
 * Contributor(s):
 
24
 *   Nicholas Nethercote <nnethercote@mozilla.com>
 
25
 *
 
26
 * Alternatively, the contents of this file may be used under the terms of
 
27
 * either of the GNU General Public License Version 2 or later (the "GPL"),
 
28
 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 
29
 * in which case the provisions of the GPL or the LGPL are applicable instead
 
30
 * of those above. If you wish to allow use of your version of this file only
 
31
 * under the terms of either the GPL or the LGPL, and not to allow others to
 
32
 * use your version of this file under the terms of the MPL, indicate your
 
33
 * decision by deleting the provisions above and replace them with the notice
 
34
 * and other provisions required by the GPL or the LGPL. If you do not delete
 
35
 * the provisions above, a recipient may use your version of this file under
 
36
 * the terms of any one of the MPL, the GPL or the LGPL.
 
37
 *
 
38
 * ***** END LICENSE BLOCK ***** */
 
39
 
 
40
#include "jsprf.h"
 
41
#include "jstl.h"
 
42
 
 
43
#include "jscompartment.h"
 
44
#include "Writer.h"
 
45
#include "nanojit.h"
 
46
 
 
47
#include "vm/ArgumentsObject.h"
 
48
 
 
49
namespace js {
 
50
namespace tjit {
 
51
 
 
52
using namespace nanojit;
 
53
 
 
54
class FuncFilter : public LirWriter
 
55
{
 
56
public:
 
57
    FuncFilter(LirWriter *out):
 
58
        LirWriter(out)
 
59
    {
 
60
    }
 
61
 
 
62
    LIns *ins2(LOpcode v, LIns *s0, LIns *s1)
 
63
    {
 
64
        if (s0 == s1 && v == LIR_eqd) {
 
65
            // 'eqd x, x' will always succeed if 'x' cannot be NaN
 
66
            if (IsPromotedInt32OrUint32(s0)) {
 
67
                // x = <a number that fits in int32 or uint32>      # cannot be NaN
 
68
                // c = eqd x, x
 
69
                return insImmI(1);
 
70
            }
 
71
            if (s0->isop(LIR_addd) || s0->isop(LIR_subd) || s0->isop(LIR_muld)) {
 
72
                LIns *lhs = s0->oprnd1();
 
73
                LIns *rhs = s0->oprnd2();
 
74
                if (IsPromotedInt32OrUint32(lhs) && IsPromotedInt32OrUint32(rhs)) {
 
75
                    // a = <a number that fits in int32 or uint32>  # cannot be NaN
 
76
                    // b = <a number that fits in int32 or uint32>  # cannot be NaN
 
77
                    // x = addd/subd/muld a, b                      # cannot be NaN
 
78
                    // c = eqd x, x
 
79
                    return insImmI(1);
 
80
                }
 
81
            }
 
82
        } else if (isCmpDOpcode(v)) {
 
83
            if (IsPromotedInt32(s0) && IsPromotedInt32(s1)) {
 
84
                v = cmpOpcodeD2I(v);
 
85
                return out->ins2(v, DemoteToInt32(out, s0), DemoteToInt32(out, s1));
 
86
            } else if (IsPromotedUint32(s0) && IsPromotedUint32(s1)) {
 
87
                // uint compare
 
88
                v = cmpOpcodeD2UI(v);
 
89
                return out->ins2(v, DemoteToUint32(out, s0), DemoteToUint32(out, s1));
 
90
            }
 
91
        }
 
92
        return out->ins2(v, s0, s1);
 
93
    }
 
94
};
 
95
 
 
96
void
 
97
Writer::init(LogControl *logc_, Config *njConfig_)
 
98
{
 
99
    JS_ASSERT(logc_ && njConfig_);
 
100
    logc = logc_;
 
101
    njConfig = njConfig_;
 
102
 
 
103
    LirWriter *&lir = InitConst(this->lir);
 
104
    CseFilter *&cse = InitConst(this->cse);
 
105
    lir = new (alloc) LirBufWriter(lirbuf, *njConfig);
 
106
#ifdef DEBUG
 
107
    ValidateWriter *validate2;
 
108
    lir = validate2 =
 
109
        new (alloc) ValidateWriter(lir, lirbuf->printer, "end of writer pipeline");
 
110
#endif
 
111
#ifdef JS_JIT_SPEW
 
112
    if (logc->lcbits & LC_TMRecorder)
 
113
       lir = new (alloc) VerboseWriter(*alloc, lir, lirbuf->printer, logc);
 
114
#endif
 
115
    // CseFilter must be downstream of SoftFloatFilter (see bug 527754 for why).
 
116
    if (njConfig->cseopt)
 
117
        cse = new (alloc) CseFilter(lir, TM_NUM_USED_ACCS, *alloc);
 
118
        if (!cse->initOOM)
 
119
            lir = cse;      // Skip CseFilter if we OOM'd when creating it.
 
120
    lir = new (alloc) ExprFilter(lir);
 
121
    lir = new (alloc) FuncFilter(lir);
 
122
#ifdef DEBUG
 
123
    ValidateWriter *validate1 =
 
124
        new (alloc) ValidateWriter(lir, lirbuf->printer, "start of writer pipeline");
 
125
    lir = validate1;
 
126
#endif
 
127
}
 
128
 
 
129
bool
 
130
IsPromotedInt32(LIns* ins)
 
131
{
 
132
    if (ins->isop(LIR_i2d))
 
133
        return true;
 
134
    if (ins->isImmD()) {
 
135
        jsdouble d = ins->immD();
 
136
        return d == jsdouble(jsint(d)) && !JSDOUBLE_IS_NEGZERO(d);
 
137
    }
 
138
    return false;
 
139
}
 
140
 
 
141
bool
 
142
IsPromotedUint32(LIns* ins)
 
143
{
 
144
    if (ins->isop(LIR_ui2d))
 
145
        return true;
 
146
    if (ins->isImmD()) {
 
147
        jsdouble d = ins->immD();
 
148
        return d == jsdouble(jsuint(d)) && !JSDOUBLE_IS_NEGZERO(d);
 
149
    }
 
150
    return false;
 
151
}
 
152
 
 
153
bool
 
154
IsPromotedInt32OrUint32(LIns* ins)
 
155
{
 
156
    return IsPromotedInt32(ins) || IsPromotedUint32(ins);
 
157
}
 
158
 
 
159
LIns *
 
160
DemoteToInt32(LirWriter *out, LIns *ins)
 
161
{
 
162
    JS_ASSERT(IsPromotedInt32(ins));
 
163
    if (ins->isop(LIR_i2d))
 
164
        return ins->oprnd1();
 
165
    JS_ASSERT(ins->isImmD());
 
166
    return out->insImmI(int32_t(ins->immD()));
 
167
}
 
168
 
 
169
LIns *
 
170
DemoteToUint32(LirWriter *out, LIns *ins)
 
171
{
 
172
    JS_ASSERT(IsPromotedUint32(ins));
 
173
    if (ins->isop(LIR_ui2d))
 
174
        return ins->oprnd1();
 
175
    JS_ASSERT(ins->isImmD());
 
176
    return out->insImmI(uint32_t(ins->immD()));
 
177
}
 
178
 
 
179
}   /* namespace tjit */
 
180
}   /* namespace js */
 
181
 
 
182
#ifdef DEBUG
 
183
namespace nanojit {
 
184
 
 
185
using namespace js;
 
186
using namespace js::tjit;
 
187
 
 
188
static bool
 
189
match(LIns *base, LOpcode opcode, AccSet accSet, int32_t disp)
 
190
{
 
191
    return base->isop(opcode) &&
 
192
           base->accSet() == accSet &&
 
193
           base->disp() == disp;
 
194
}
 
195
 
 
196
static bool
 
197
match(LIns *base, LOpcode opcode, AccSet accSet, LoadQual loadQual, int32_t disp)
 
198
{
 
199
    return base->isop(opcode) &&
 
200
           base->accSet() == accSet &&
 
201
           base->loadQual() == loadQual &&
 
202
           base->disp() == disp;
 
203
}
 
204
 
 
205
static bool
 
206
couldBeObjectOrString(LIns *ins)
 
207
{
 
208
    bool ret = false;
 
209
 
 
210
    if (ins->isop(LIR_callp)) {
 
211
        // ins = callp ...      # could be a call to an object-creating function
 
212
        ret = true;
 
213
 
 
214
    } else if (ins->isop(LIR_ldp)) {
 
215
        // ins = ldp ...        # could be an object, eg. loaded from the stack
 
216
        ret = true;
 
217
 
 
218
    } else if (ins->isImmP()) {
 
219
        // ins = immp ...       # could be a pointer to an object
 
220
        uintptr_t val = uintptr_t(ins->immP());
 
221
        if (val == 0 || val > 4096)
 
222
            ret = true;         // Looks like a pointer
 
223
 
 
224
    } else if (ins->isop(LIR_cmovp)) {
 
225
        // ins = cmovp <JSObject>, <JSObject>
 
226
        ret = couldBeObjectOrString(ins->oprnd2()) &&
 
227
              couldBeObjectOrString(ins->oprnd3());
 
228
 
 
229
    } else if (ins->isop(LIR_ori) &&
 
230
               ins->oprnd1()->isop(LIR_andi) &&
 
231
               ins->oprnd2()->isop(LIR_andi))
 
232
    {
 
233
        // This is a partial check for the insChoose() code that only occurs
 
234
        // is use_cmov() is false.
 
235
        //
 
236
        // ins_oprnd1 = andi ...
 
237
        // ins_oprnd2 = andi ...
 
238
        // ins = ori ins_oprnd1, ins_oprnd2
 
239
        ret = true;
 
240
 
 
241
#if JS_BITS_PER_WORD == 64
 
242
    } else if (ins->isop(LIR_andq) &&
 
243
               ins->oprnd1()->isop(LIR_ldq) &&
 
244
               ins->oprnd2()->isImmQ() &&
 
245
               uintptr_t(ins->oprnd2()->immQ()) == JSVAL_PAYLOAD_MASK)
 
246
    {
 
247
        // ins_oprnd1 = ldq ...
 
248
        // ins_oprnd2 = immq JSVAL_PAYLOAD_MASK
 
249
        // ins = andq ins_oprnd1, ins_oprnd2
 
250
        ret = true;
 
251
#endif
 
252
    } else if (ins->isop(LIR_addp) &&
 
253
               ((ins->oprnd1()->isImmP() &&
 
254
                 (void *)ins->oprnd1()->immP() == JSAtom::unitStaticTable) ||
 
255
                (ins->oprnd2()->isImmP() &&
 
256
                 (void *)ins->oprnd2()->immP() == JSAtom::unitStaticTable)))
 
257
    {
 
258
        // (String only)
 
259
        // ins = addp ..., JSString::unitStringTable
 
260
        //   OR
 
261
        // ins = addp JSString::unitStringTable, ...
 
262
        ret = true;
 
263
    }
 
264
 
 
265
    return ret;
 
266
}
 
267
 
 
268
static bool
 
269
isConstPrivatePtr(LIns *ins, unsigned slot)
 
270
{
 
271
#if JS_BITS_PER_WORD == 32
 
272
    // ins = ldp.slots/c ...[<offset of slot>]
 
273
    return match(ins, LIR_ldp, ACCSET_SLOTS, LOAD_CONST, slot * sizeof(Value) + sPayloadOffset);
 
274
#elif JS_BITS_PER_WORD == 64
 
275
    // ins_oprnd1 = ldp.slots/c ...[<offset of slot>]
 
276
    // ins_oprnd2 = immi 1
 
277
    // ins = lshq ins_oprnd1, ins_oprnd2
 
278
    return ins->isop(LIR_lshq) &&
 
279
           match(ins->oprnd1(), LIR_ldp, ACCSET_SLOTS, LOAD_CONST, slot * sizeof(Value)) &&
 
280
           ins->oprnd2()->isImmI(1);
 
281
#endif
 
282
}
 
283
 
 
284
/*
 
285
 * Any time you use an AccSet annotation other than ACCSET_ALL, you are making
 
286
 * a promise to Nanojit about the properties of the annotated load/store/call.
 
287
 * If that annotation is wrong, it could cause rare and subtle bugs.  So this
 
288
 * function does its damnedest to prevent such bugs occurring by carefully
 
289
 * checking every load and store.
 
290
 *
 
291
 * For some access regions, we can check perfectly -- eg. for an ACCSET_STATE
 
292
 * load/store, the base pointer must be 'state'.  For others, we can only
 
293
 * check imperfectly -- eg. for an ACCSET_OBJ_CLASP load/store, we can check that
 
294
 * the base pointer has one of several forms, but it's possible that a
 
295
 * non-object has that form as well.  This imperfect checking is unfortunate
 
296
 * but unavoidable.  Also, multi-region load/store AccSets are not checked,
 
297
 * and so are best avoided (they're rarely needed).  Finally, the AccSet
 
298
 * annotations on calls cannot be checked here;  in some cases they can be
 
299
 * partially checked via assertions (eg. by checking that certain values
 
300
 * are not changed by the function).
 
301
 */
 
302
void ValidateWriter::checkAccSet(LOpcode op, LIns *base, int32_t disp, AccSet accSet)
 
303
{
 
304
    bool ok;
 
305
 
 
306
    NanoAssert(accSet != ACCSET_NONE);
 
307
 
 
308
    #define dispWithin(Struct) \
 
309
        (0 <= disp && disp < int32_t(sizeof(Struct)))
 
310
 
 
311
    switch (accSet) {
 
312
      case ACCSET_STATE:
 
313
        // base = paramp 0 0
 
314
        // ins  = {ld,st}X.state base[<disp within TracerState>]
 
315
        ok = dispWithin(TracerState) && 
 
316
             base->isop(LIR_paramp) &&
 
317
             base->paramKind() == 0 &&
 
318
             base->paramArg() == 0;
 
319
        break;
 
320
 
 
321
      case ACCSET_STACK:
 
322
        // base = ldp.state ...[offsetof(TracerState, sp)]
 
323
        // ins  = {ld,st}X.sp base[...]
 
324
        //   OR
 
325
        // base_oprnd1 = ldp.state ...[offsetof(TraceState, sp)]
 
326
        // base        = addp base_oprnd1, ...
 
327
        // ins         = {ld,st}X.sp base[...]
 
328
        ok = match(base, LIR_ldp, ACCSET_STATE, offsetof(TracerState, sp)) ||
 
329
             (base->isop(LIR_addp) &&
 
330
              match(base->oprnd1(), LIR_ldp, ACCSET_STATE, offsetof(TracerState, sp)));
 
331
        break;
 
332
 
 
333
      case ACCSET_RSTACK:
 
334
        // base = ldp.state ...[offsetof(TracerState, rp)]
 
335
        // ins  = {ld,st}p.rp base[...]
 
336
        //   OR
 
337
        // base = ldp.state ...[offsetof(TracerState, callstackBaseOffset)]
 
338
        // ins  = {ld,st}p.rp base[...]
 
339
        ok = (op == LIR_ldp || op == LIR_stp) &&
 
340
             (match(base, LIR_ldp, ACCSET_STATE, offsetof(TracerState, rp)) ||
 
341
              match(base, LIR_ldp, ACCSET_STATE, offsetof(TracerState, callstackBase)));
 
342
        break;
 
343
 
 
344
      case ACCSET_CX:
 
345
        // base = ldp.state ...[offsetof(TracerState, cx)]
 
346
        // ins  = {ld,st}X.cx base[<disp within JSContext>]
 
347
        ok = dispWithin(JSContext) &&
 
348
             match(base, LIR_ldp, ACCSET_STATE, offsetof(TracerState, cx));
 
349
        break;
 
350
 
 
351
      case ACCSET_TM:
 
352
          // base = immp
 
353
          ok = base->isImmP() && disp == 0;
 
354
          break;
 
355
 
 
356
      case ACCSET_EOS:
 
357
        // base = ldp.state ...[offsetof(TracerState, eos)]
 
358
        // ins  = {ld,st}X.eos base[...]
 
359
        ok = match(base, LIR_ldp, ACCSET_STATE, offsetof(TracerState, eos));
 
360
        break;
 
361
 
 
362
      case ACCSET_ALLOC:
 
363
        // base = allocp ...
 
364
        // ins  = {ld,st}X.alloc base[...]
 
365
        //   OR
 
366
        // base_oprnd1 = allocp ...
 
367
        // base        = addp base_oprnd1, ...
 
368
        // ins         = {ld,st}X.alloc base[...]
 
369
        ok = base->isop(LIR_allocp) ||
 
370
             (base->isop(LIR_addp) &&
 
371
              base->oprnd1()->isop(LIR_allocp));
 
372
        break;
 
373
 
 
374
      case ACCSET_FRAMEREGS:
 
375
        // base = ldp.cx ...[offsetof(JSContext, regs)]
 
376
        // ins  = ldp.regs base[<disp within FrameRegs>]
 
377
        ok = op == LIR_ldp &&
 
378
             dispWithin(FrameRegs) && 
 
379
             match(base, LIR_ldp, ACCSET_CX, offsetof(JSContext, stack) + ContextStack::offsetOfRegs());
 
380
        break;
 
381
 
 
382
      case ACCSET_STACKFRAME:
 
383
        // base = ldp.regs ...[offsetof(FrameRegs, fp)]
 
384
        // ins  = {ld,st}X.sf base[<disp within StackFrame>]
 
385
        ok = dispWithin(StackFrame) && 
 
386
             match(base, LIR_ldp, ACCSET_FRAMEREGS, FrameRegs::offsetOfFp);
 
387
        break;
 
388
 
 
389
      case ACCSET_RUNTIME:
 
390
        // base = ldp.cx ...[offsetof(JSContext, runtime)]
 
391
        // ins  = ldp.rt base[<disp within JSRuntime>]
 
392
        ok = dispWithin(JSRuntime) &&
 
393
             match(base, LIR_ldp, ACCSET_CX, offsetof(JSContext, runtime));
 
394
        break;
 
395
 
 
396
      // This check is imperfect.
 
397
      //
 
398
      // base = <JSObject>
 
399
      // ins  = ldp.obj<field> base[offsetof(JSObject, <field>)]
 
400
      #define OK_OBJ_FIELD(ldop, field) \
 
401
            op == ldop && \
 
402
            disp == offsetof(JSObject, field) && \
 
403
            couldBeObjectOrString(base)
 
404
 
 
405
      case ACCSET_OBJ_CLASP:
 
406
        ok = OK_OBJ_FIELD(LIR_ldp, clasp);
 
407
        break;
 
408
 
 
409
      case ACCSET_OBJ_FLAGS:
 
410
        ok = OK_OBJ_FIELD(LIR_ldi, flags);
 
411
        break;
 
412
 
 
413
      case ACCSET_OBJ_SHAPE:
 
414
        ok = OK_OBJ_FIELD(LIR_ldi, objShape);
 
415
        break;
 
416
 
 
417
      case ACCSET_OBJ_PROTO:
 
418
        ok = OK_OBJ_FIELD(LIR_ldp, proto);
 
419
        break;
 
420
 
 
421
      case ACCSET_OBJ_PARENT:
 
422
        ok = OK_OBJ_FIELD(LIR_ldp, parent);
 
423
        break;
 
424
 
 
425
      case ACCSET_OBJ_PRIVATE:
 
426
        // base = <JSObject>
 
427
        // ins  = {ld,st}p.objprivate base[offsetof(JSObject, privateData)]
 
428
        ok = (op == LIR_ldi || op == LIR_ldp ||
 
429
              op == LIR_sti || op == LIR_stp) &&
 
430
             disp == offsetof(JSObject, privateData) &&
 
431
             couldBeObjectOrString(base);
 
432
        break;
 
433
 
 
434
      case ACCSET_OBJ_CAPACITY:
 
435
        ok = OK_OBJ_FIELD(LIR_ldi, capacity);
 
436
        break;
 
437
 
 
438
      case ACCSET_OBJ_SLOTS:
 
439
        ok = OK_OBJ_FIELD(LIR_ldp, slots);
 
440
        break;
 
441
 
 
442
      case ACCSET_SLOTS:
 
443
        // This check is imperfect.
 
444
        //
 
445
        // base = <JSObject>                                          # direct slot access
 
446
        // ins  = {ld,st}X.slots base[...]
 
447
        //   OR
 
448
        // base = ldp.objslots ...[offsetof(JSObject, slots)]         # indirect slot access
 
449
        // ins  = {ld,st}X.slots base[...]
 
450
        //   OR
 
451
        // base_oprnd1 = ldp.objslots ...[offsetof(JSObject, slots)]  # indirect scaled slot access
 
452
        // base        = addp base_oprnd1, ...
 
453
        // ins         = {ld,st}X.slots base[...]
 
454
        ok = couldBeObjectOrString(base) ||
 
455
             match(base, LIR_ldp, ACCSET_OBJ_SLOTS, offsetof(JSObject, slots)) ||
 
456
             (base->isop(LIR_addp) &&
 
457
              match(base->oprnd1(), LIR_ldp, ACCSET_OBJ_SLOTS, offsetof(JSObject, slots)));
 
458
        break;
 
459
 
 
460
      case ACCSET_TARRAY:
 
461
        // This check is imperfect.
 
462
        //
 
463
        // base = ldp.objprivate ...[offsetof(JSObject, privateData)]
 
464
        // ins = ld{i,p}.tarray base[<disp within TypedArray>]
 
465
        ok = (op == LIR_ldi || op == LIR_ldp) &&
 
466
             dispWithin(TypedArray) &&
 
467
             match(base, LIR_ldp, ACCSET_OBJ_PRIVATE, offsetof(JSObject, privateData));
 
468
        break;
 
469
 
 
470
      case ACCSET_TARRAY_DATA:
 
471
        // base = ldp.tarray/c ...[TypedArray::dataOffset()]
 
472
        // ins  = {ld,st}X.tdata base[...]
 
473
        //   OR
 
474
        // base_oprnd1 = ldp.tarray/c ...[TypedArray::dataOffset()]
 
475
        // base        = addp base_oprnd1, ...
 
476
        // ins         = {ld,st}X.tdata base[...]
 
477
        ok = match(base, LIR_ldp, ACCSET_TARRAY, LOAD_CONST, TypedArray::dataOffset()) ||
 
478
             (base->isop(LIR_addp) &&
 
479
              match(base->oprnd1(), LIR_ldp, ACCSET_TARRAY, LOAD_CONST, TypedArray::dataOffset()));
 
480
        break;
 
481
 
 
482
      case ACCSET_ITER:
 
483
        // base = ldp.objprivate ...[offsetof(JSObject, privateData)]
 
484
        // ins = {ld,st}p.iter base[<disp within NativeIterator>]
 
485
        ok = (op == LIR_ldp || op == LIR_stp) &&
 
486
             dispWithin(NativeIterator) &&
 
487
             match(base, LIR_ldp, ACCSET_OBJ_PRIVATE, offsetof(JSObject, privateData));
 
488
        break;
 
489
 
 
490
      case ACCSET_ITER_PROPS:
 
491
        // base = ldp.iter ...[offsetof(NativeIterator, props_cursor)]
 
492
        // ins  = ld{i,p,d}.iterprops base[0|4]
 
493
        ok = (op == LIR_ldi || op == LIR_ldp || op == LIR_ldd) &&
 
494
             (disp == 0 || disp == 4) &&
 
495
             match(base, LIR_ldp, ACCSET_ITER, offsetof(NativeIterator, props_cursor));
 
496
        break;
 
497
 
 
498
      case ACCSET_STRING:
 
499
        // This check is imperfect.
 
500
        //
 
501
        // base = <JSString>
 
502
        // ins  = {ld,st}X.str base[<disp within JSString>]
 
503
        ok = dispWithin(JSString) &&
 
504
             couldBeObjectOrString(base);
 
505
        break;
 
506
 
 
507
      case ACCSET_STRING_MCHARS:
 
508
        // base = ldp.string ...[offsetof(JSString, chars)]
 
509
        // ins  = ldus2ui.strchars/c base[0]
 
510
        //   OR
 
511
        // base_oprnd1 = ldp.string ...[offsetof(JSString, chars)]
 
512
        // base        = addp base_oprnd1, ...
 
513
        // ins         = ldus2ui.strchars/c base[0]
 
514
        ok = op == LIR_ldus2ui &&
 
515
             disp == 0 &&
 
516
             (match(base, LIR_ldp, ACCSET_STRING, JSString::offsetOfChars()) ||
 
517
              (base->isop(LIR_addp) &&
 
518
               match(base->oprnd1(), LIR_ldp, ACCSET_STRING, JSString::offsetOfChars())));
 
519
        break;
 
520
 
 
521
      case ACCSET_TYPEMAP:
 
522
        // This check is imperfect, things get complicated once you get back
 
523
        // farther than 'base'.  But the parts we check are pretty distinctive
 
524
        // and should be good enough.
 
525
        //
 
526
        // base = addp base_oprnd1, ...
 
527
        // ins  = lduc2ui.typemap/c base[0]
 
528
        ok = op == LIR_lduc2ui &&
 
529
             disp == 0 &&
 
530
             base->isop(LIR_addp);
 
531
        break;
 
532
 
 
533
      case ACCSET_FCSLOTS:
 
534
        // This check is imperfect.
 
535
        //
 
536
        // base = <const private ptr slots[JSSLOT_FLAT_CLOSURE_UPVARS]>
 
537
        // ins = {ld,st}X.fcslots base[...]
 
538
        ok = isConstPrivatePtr(base, JSObject::JSSLOT_FLAT_CLOSURE_UPVARS);
 
539
        break;
 
540
 
 
541
      case ACCSET_ARGS_DATA:
 
542
        // This check is imperfect.
 
543
        //
 
544
        // base = <const private ptr slots[JSSLOT_ARGS_DATA]>
 
545
        // ins = st{i,p,d}.argsdata base[...]
 
546
        //   OR
 
547
        // base_oprnd1 = <const private ptr slots[JSSLOT_ARGS_DATA]>
 
548
        // base        = addp base_oprnd1, ...
 
549
        // ins         = {ld,st}X.argsdata base[...]
 
550
        ok = (isConstPrivatePtr(base, ArgumentsObject::DATA_SLOT) ||
 
551
              (base->isop(LIR_addp) &&
 
552
               isConstPrivatePtr(base->oprnd1(), ArgumentsObject::DATA_SLOT)));
 
553
        break;
 
554
 
 
555
      default:
 
556
        // This assertion will fail if any single-region AccSets aren't covered
 
557
        // by the switch -- only multi-region AccSets should be handled here.
 
558
        JS_ASSERT(!isSingletonAccSet(accSet));
 
559
        ok = true;
 
560
        break;
 
561
    }
 
562
 
 
563
    if (!ok) {
 
564
        InsBuf b1, b2;
 
565
        printer->formatIns(&b1, base);
 
566
        JS_snprintf(b2.buf, b2.len, "base = (%s); disp = %d", b1.buf, disp);
 
567
        errorAccSet(lirNames[op], accSet, b2.buf);
 
568
    }
 
569
}
 
570
 
 
571
} // namespace nanojit
 
572
 
 
573
#endif
 
574