/js/src/tracejit/Writer.cpp

http://github.com/zpao/v8monkey · C++ · 592 lines · 341 code · 67 blank · 184 comment · 109 complexity · f978b4d3c7cbbabab336e0ca8740973f MD5 · raw file

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