js/src/jit/JitFrameIterator.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
michael@0 2 * vim: set ts=8 sts=4 et sw=4 tw=99:
michael@0 3 * This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 #ifndef jit_JitFrameIterator_h
michael@0 8 #define jit_JitFrameIterator_h
michael@0 9
michael@0 10 #ifdef JS_ION
michael@0 11
michael@0 12 #include "jsfun.h"
michael@0 13 #include "jsscript.h"
michael@0 14 #include "jstypes.h"
michael@0 15
michael@0 16 #include "jit/IonCode.h"
michael@0 17 #include "jit/Snapshots.h"
michael@0 18
michael@0 19 namespace js {
michael@0 20 class ActivationIterator;
michael@0 21 };
michael@0 22
michael@0 23 namespace js {
michael@0 24 namespace jit {
michael@0 25
michael@0 26 enum FrameType
michael@0 27 {
michael@0 28 // A JS frame is analagous to a js::InterpreterFrame, representing one scripted
michael@0 29 // functon activation. IonJS frames are used by the optimizing compiler.
michael@0 30 JitFrame_IonJS,
michael@0 31
michael@0 32 // JS frame used by the baseline JIT.
michael@0 33 JitFrame_BaselineJS,
michael@0 34
michael@0 35 // Frame pushed for baseline JIT stubs that make non-tail calls, so that the
michael@0 36 // return address -> ICEntry mapping works.
michael@0 37 JitFrame_BaselineStub,
michael@0 38
michael@0 39 // The entry frame is the initial prologue block transitioning from the VM
michael@0 40 // into the Ion world.
michael@0 41 JitFrame_Entry,
michael@0 42
michael@0 43 // A rectifier frame sits in between two JS frames, adapting argc != nargs
michael@0 44 // mismatches in calls.
michael@0 45 JitFrame_Rectifier,
michael@0 46
michael@0 47 // An unwound JS frame is a JS frame signalling that its callee frame has been
michael@0 48 // turned into an exit frame (see EnsureExitFrame). Used by Ion bailouts and
michael@0 49 // Baseline exception unwinding.
michael@0 50 JitFrame_Unwound_IonJS,
michael@0 51
michael@0 52 // Like Unwound_IonJS, but the caller is a baseline stub frame.
michael@0 53 JitFrame_Unwound_BaselineStub,
michael@0 54
michael@0 55 // An unwound rectifier frame is a rectifier frame signalling that its callee
michael@0 56 // frame has been turned into an exit frame (see EnsureExitFrame).
michael@0 57 JitFrame_Unwound_Rectifier,
michael@0 58
michael@0 59 // An exit frame is necessary for transitioning from a JS frame into C++.
michael@0 60 // From within C++, an exit frame is always the last frame in any
michael@0 61 // JitActivation.
michael@0 62 JitFrame_Exit
michael@0 63 };
michael@0 64
michael@0 65 enum ReadFrameArgsBehavior {
michael@0 66 // Only read formals (i.e. [0 ... callee()->nargs]
michael@0 67 ReadFrame_Formals,
michael@0 68
michael@0 69 // Only read overflown args (i.e. [callee()->nargs ... numActuals()]
michael@0 70 ReadFrame_Overflown,
michael@0 71
michael@0 72 // Read all args (i.e. [0 ... numActuals()])
michael@0 73 ReadFrame_Actuals
michael@0 74 };
michael@0 75
michael@0 76 class IonCommonFrameLayout;
michael@0 77 class IonJSFrameLayout;
michael@0 78 class IonExitFrameLayout;
michael@0 79
michael@0 80 class BaselineFrame;
michael@0 81
michael@0 82 class JitActivation;
michael@0 83
michael@0 84 class JitFrameIterator
michael@0 85 {
michael@0 86 protected:
michael@0 87 uint8_t *current_;
michael@0 88 FrameType type_;
michael@0 89 uint8_t *returnAddressToFp_;
michael@0 90 size_t frameSize_;
michael@0 91
michael@0 92 private:
michael@0 93 mutable const SafepointIndex *cachedSafepointIndex_;
michael@0 94 const JitActivation *activation_;
michael@0 95 ExecutionMode mode_;
michael@0 96
michael@0 97 void dumpBaseline() const;
michael@0 98
michael@0 99 public:
michael@0 100 explicit JitFrameIterator(uint8_t *top, ExecutionMode mode)
michael@0 101 : current_(top),
michael@0 102 type_(JitFrame_Exit),
michael@0 103 returnAddressToFp_(nullptr),
michael@0 104 frameSize_(0),
michael@0 105 cachedSafepointIndex_(nullptr),
michael@0 106 activation_(nullptr),
michael@0 107 mode_(mode)
michael@0 108 { }
michael@0 109
michael@0 110 explicit JitFrameIterator(JSContext *cx);
michael@0 111 explicit JitFrameIterator(const ActivationIterator &activations);
michael@0 112 explicit JitFrameIterator(IonJSFrameLayout *fp, ExecutionMode mode);
michael@0 113
michael@0 114 // Current frame information.
michael@0 115 FrameType type() const {
michael@0 116 return type_;
michael@0 117 }
michael@0 118 uint8_t *fp() const {
michael@0 119 return current_;
michael@0 120 }
michael@0 121 const JitActivation *activation() const {
michael@0 122 return activation_;
michael@0 123 }
michael@0 124
michael@0 125 IonCommonFrameLayout *current() const {
michael@0 126 return (IonCommonFrameLayout *)current_;
michael@0 127 }
michael@0 128
michael@0 129 inline uint8_t *returnAddress() const;
michael@0 130
michael@0 131 IonJSFrameLayout *jsFrame() const {
michael@0 132 JS_ASSERT(isScripted());
michael@0 133 return (IonJSFrameLayout *) fp();
michael@0 134 }
michael@0 135
michael@0 136 // Returns true iff this exit frame was created using EnsureExitFrame.
michael@0 137 inline bool isFakeExitFrame() const;
michael@0 138
michael@0 139 inline IonExitFrameLayout *exitFrame() const;
michael@0 140
michael@0 141 // Returns whether the JS frame has been invalidated and, if so,
michael@0 142 // places the invalidated Ion script in |ionScript|.
michael@0 143 bool checkInvalidation(IonScript **ionScript) const;
michael@0 144 bool checkInvalidation() const;
michael@0 145
michael@0 146 bool isScripted() const {
michael@0 147 return type_ == JitFrame_BaselineJS || type_ == JitFrame_IonJS;
michael@0 148 }
michael@0 149 bool isBaselineJS() const {
michael@0 150 return type_ == JitFrame_BaselineJS;
michael@0 151 }
michael@0 152 bool isIonJS() const {
michael@0 153 return type_ == JitFrame_IonJS;
michael@0 154 }
michael@0 155 bool isBaselineStub() const {
michael@0 156 return type_ == JitFrame_BaselineStub;
michael@0 157 }
michael@0 158 bool isNative() const;
michael@0 159 bool isOOLNative() const;
michael@0 160 bool isOOLPropertyOp() const;
michael@0 161 bool isOOLProxy() const;
michael@0 162 bool isDOMExit() const;
michael@0 163 bool isEntry() const {
michael@0 164 return type_ == JitFrame_Entry;
michael@0 165 }
michael@0 166 bool isFunctionFrame() const;
michael@0 167
michael@0 168 bool isConstructing() const;
michael@0 169
michael@0 170 void *calleeToken() const;
michael@0 171 JSFunction *callee() const;
michael@0 172 JSFunction *maybeCallee() const;
michael@0 173 unsigned numActualArgs() const;
michael@0 174 JSScript *script() const;
michael@0 175 void baselineScriptAndPc(JSScript **scriptRes, jsbytecode **pcRes) const;
michael@0 176 Value *actualArgs() const;
michael@0 177
michael@0 178 // Returns the return address of the frame above this one (that is, the
michael@0 179 // return address that returns back to the current frame).
michael@0 180 uint8_t *returnAddressToFp() const {
michael@0 181 return returnAddressToFp_;
michael@0 182 }
michael@0 183
michael@0 184 // Previous frame information extracted from the current frame.
michael@0 185 inline size_t prevFrameLocalSize() const;
michael@0 186 inline FrameType prevType() const;
michael@0 187 uint8_t *prevFp() const;
michael@0 188
michael@0 189 // Returns the stack space used by the current frame, in bytes. This does
michael@0 190 // not include the size of its fixed header.
michael@0 191 size_t frameSize() const {
michael@0 192 JS_ASSERT(type_ != JitFrame_Exit);
michael@0 193 return frameSize_;
michael@0 194 }
michael@0 195
michael@0 196 // Functions used to iterate on frames. When prevType is JitFrame_Entry,
michael@0 197 // the current frame is the last frame.
michael@0 198 inline bool done() const {
michael@0 199 return type_ == JitFrame_Entry;
michael@0 200 }
michael@0 201 JitFrameIterator &operator++();
michael@0 202
michael@0 203 // Returns the IonScript associated with this JS frame.
michael@0 204 IonScript *ionScript() const;
michael@0 205
michael@0 206 // Returns the Safepoint associated with this JS frame. Incurs a lookup
michael@0 207 // overhead.
michael@0 208 const SafepointIndex *safepoint() const;
michael@0 209
michael@0 210 // Returns the OSI index associated with this JS frame. Incurs a lookup
michael@0 211 // overhead.
michael@0 212 const OsiIndex *osiIndex() const;
michael@0 213
michael@0 214 uintptr_t *spillBase() const;
michael@0 215 MachineState machineState() const;
michael@0 216
michael@0 217 template <class Op>
michael@0 218 void unaliasedForEachActual(Op op, ReadFrameArgsBehavior behavior) const {
michael@0 219 JS_ASSERT(isBaselineJS());
michael@0 220
michael@0 221 unsigned nactual = numActualArgs();
michael@0 222 unsigned start, end;
michael@0 223 switch (behavior) {
michael@0 224 case ReadFrame_Formals:
michael@0 225 start = 0;
michael@0 226 end = callee()->nargs();
michael@0 227 break;
michael@0 228 case ReadFrame_Overflown:
michael@0 229 start = callee()->nargs();
michael@0 230 end = nactual;
michael@0 231 break;
michael@0 232 case ReadFrame_Actuals:
michael@0 233 start = 0;
michael@0 234 end = nactual;
michael@0 235 }
michael@0 236
michael@0 237 Value *argv = actualArgs();
michael@0 238 for (unsigned i = start; i < end; i++)
michael@0 239 op(argv[i]);
michael@0 240 }
michael@0 241
michael@0 242 void dump() const;
michael@0 243
michael@0 244 inline BaselineFrame *baselineFrame() const;
michael@0 245 };
michael@0 246
michael@0 247 class IonJSFrameLayout;
michael@0 248 class IonBailoutIterator;
michael@0 249
michael@0 250 class RResumePoint;
michael@0 251
michael@0 252 // Reads frame information in snapshot-encoding order (that is, outermost frame
michael@0 253 // to innermost frame).
michael@0 254 class SnapshotIterator
michael@0 255 {
michael@0 256 SnapshotReader snapshot_;
michael@0 257 RecoverReader recover_;
michael@0 258 IonJSFrameLayout *fp_;
michael@0 259 MachineState machine_;
michael@0 260 IonScript *ionScript_;
michael@0 261
michael@0 262 private:
michael@0 263 // Read a spilled register from the machine state.
michael@0 264 bool hasRegister(Register reg) const {
michael@0 265 return machine_.has(reg);
michael@0 266 }
michael@0 267 uintptr_t fromRegister(Register reg) const {
michael@0 268 return machine_.read(reg);
michael@0 269 }
michael@0 270
michael@0 271 bool hasRegister(FloatRegister reg) const {
michael@0 272 return machine_.has(reg);
michael@0 273 }
michael@0 274 double fromRegister(FloatRegister reg) const {
michael@0 275 return machine_.read(reg);
michael@0 276 }
michael@0 277
michael@0 278 // Read an uintptr_t from the stack.
michael@0 279 bool hasStack(int32_t offset) const {
michael@0 280 return true;
michael@0 281 }
michael@0 282 uintptr_t fromStack(int32_t offset) const;
michael@0 283
michael@0 284 Value allocationValue(const RValueAllocation &a);
michael@0 285 bool allocationReadable(const RValueAllocation &a);
michael@0 286 void warnUnreadableAllocation();
michael@0 287
michael@0 288 public:
michael@0 289 // Handle iterating over RValueAllocations of the snapshots.
michael@0 290 inline RValueAllocation readAllocation() {
michael@0 291 MOZ_ASSERT(moreAllocations());
michael@0 292 return snapshot_.readAllocation();
michael@0 293 }
michael@0 294 Value skip() {
michael@0 295 snapshot_.skipAllocation();
michael@0 296 return UndefinedValue();
michael@0 297 }
michael@0 298
michael@0 299 const RResumePoint *resumePoint() const;
michael@0 300 const RInstruction *instruction() const {
michael@0 301 return recover_.instruction();
michael@0 302 }
michael@0 303
michael@0 304 uint32_t numAllocations() const;
michael@0 305 inline bool moreAllocations() const {
michael@0 306 return snapshot_.numAllocationsRead() < numAllocations();
michael@0 307 }
michael@0 308
michael@0 309 public:
michael@0 310 // Exhibits frame properties contained in the snapshot.
michael@0 311 uint32_t pcOffset() const;
michael@0 312 inline bool resumeAfter() const {
michael@0 313 // Inline frames are inlined on calls, which are considered as being
michael@0 314 // resumed on the Call as baseline will push the pc once we return from
michael@0 315 // the call.
michael@0 316 if (moreFrames())
michael@0 317 return false;
michael@0 318 return recover_.resumeAfter();
michael@0 319 }
michael@0 320 inline BailoutKind bailoutKind() const {
michael@0 321 return snapshot_.bailoutKind();
michael@0 322 }
michael@0 323
michael@0 324 public:
michael@0 325 // Read the next instruction available and get ready to either skip it or
michael@0 326 // evaluate it.
michael@0 327 inline void nextInstruction() {
michael@0 328 MOZ_ASSERT(snapshot_.numAllocationsRead() == numAllocations());
michael@0 329 recover_.nextInstruction();
michael@0 330 snapshot_.resetNumAllocationsRead();
michael@0 331 }
michael@0 332
michael@0 333 // Skip an Instruction by walking to the next instruction and by skipping
michael@0 334 // all the allocations corresponding to this instruction.
michael@0 335 void skipInstruction();
michael@0 336
michael@0 337 inline bool moreInstructions() const {
michael@0 338 return recover_.moreInstructions();
michael@0 339 }
michael@0 340
michael@0 341 public:
michael@0 342 // Handle iterating over frames of the snapshots.
michael@0 343 void nextFrame();
michael@0 344
michael@0 345 inline bool moreFrames() const {
michael@0 346 // The last instruction is recovering the innermost frame, so as long as
michael@0 347 // there is more instruction there is necesseray more frames.
michael@0 348 return moreInstructions();
michael@0 349 }
michael@0 350
michael@0 351 public:
michael@0 352 // Connect all informations about the current script in order to recover the
michael@0 353 // content of baseline frames.
michael@0 354
michael@0 355 SnapshotIterator(IonScript *ionScript, SnapshotOffset snapshotOffset,
michael@0 356 IonJSFrameLayout *fp, const MachineState &machine);
michael@0 357 SnapshotIterator(const JitFrameIterator &iter);
michael@0 358 SnapshotIterator(const IonBailoutIterator &iter);
michael@0 359 SnapshotIterator();
michael@0 360
michael@0 361 Value read() {
michael@0 362 return allocationValue(readAllocation());
michael@0 363 }
michael@0 364 Value maybeRead(bool silentFailure = false) {
michael@0 365 RValueAllocation a = readAllocation();
michael@0 366 if (allocationReadable(a))
michael@0 367 return allocationValue(a);
michael@0 368 if (!silentFailure)
michael@0 369 warnUnreadableAllocation();
michael@0 370 return UndefinedValue();
michael@0 371 }
michael@0 372
michael@0 373 void readCommonFrameSlots(Value *scopeChain, Value *rval) {
michael@0 374 if (scopeChain)
michael@0 375 *scopeChain = read();
michael@0 376 else
michael@0 377 skip();
michael@0 378
michael@0 379 if (rval)
michael@0 380 *rval = read();
michael@0 381 else
michael@0 382 skip();
michael@0 383 }
michael@0 384
michael@0 385 template <class Op>
michael@0 386 void readFunctionFrameArgs(Op &op, ArgumentsObject **argsObj, Value *thisv,
michael@0 387 unsigned start, unsigned end, JSScript *script)
michael@0 388 {
michael@0 389 // Assumes that the common frame arguments have already been read.
michael@0 390 if (script->argumentsHasVarBinding()) {
michael@0 391 if (argsObj) {
michael@0 392 Value v = read();
michael@0 393 if (v.isObject())
michael@0 394 *argsObj = &v.toObject().as<ArgumentsObject>();
michael@0 395 } else {
michael@0 396 skip();
michael@0 397 }
michael@0 398 }
michael@0 399
michael@0 400 if (thisv)
michael@0 401 *thisv = read();
michael@0 402 else
michael@0 403 skip();
michael@0 404
michael@0 405 unsigned i = 0;
michael@0 406 if (end < start)
michael@0 407 i = start;
michael@0 408
michael@0 409 for (; i < start; i++)
michael@0 410 skip();
michael@0 411 for (; i < end; i++) {
michael@0 412 // We are not always able to read values from the snapshots, some values
michael@0 413 // such as non-gc things may still be live in registers and cause an
michael@0 414 // error while reading the machine state.
michael@0 415 Value v = maybeRead();
michael@0 416 op(v);
michael@0 417 }
michael@0 418 }
michael@0 419
michael@0 420 Value maybeReadAllocByIndex(size_t index) {
michael@0 421 while (index--) {
michael@0 422 JS_ASSERT(moreAllocations());
michael@0 423 skip();
michael@0 424 }
michael@0 425
michael@0 426 Value s = maybeRead(true);
michael@0 427
michael@0 428 while (moreAllocations())
michael@0 429 skip();
michael@0 430
michael@0 431 return s;
michael@0 432 }
michael@0 433 };
michael@0 434
michael@0 435 // Reads frame information in callstack order (that is, innermost frame to
michael@0 436 // outermost frame).
michael@0 437 template <AllowGC allowGC=CanGC>
michael@0 438 class InlineFrameIteratorMaybeGC
michael@0 439 {
michael@0 440 const JitFrameIterator *frame_;
michael@0 441 SnapshotIterator start_;
michael@0 442 SnapshotIterator si_;
michael@0 443 uint32_t framesRead_;
michael@0 444
michael@0 445 // When the inline-frame-iterator is created, this variable is defined to
michael@0 446 // UINT32_MAX. Then the first iteration of findNextFrame, which settle on
michael@0 447 // the innermost frame, is used to update this counter to the number of
michael@0 448 // frames contained in the recover buffer.
michael@0 449 uint32_t frameCount_;
michael@0 450
michael@0 451 typename MaybeRooted<JSFunction*, allowGC>::RootType callee_;
michael@0 452 typename MaybeRooted<JSScript*, allowGC>::RootType script_;
michael@0 453 jsbytecode *pc_;
michael@0 454 uint32_t numActualArgs_;
michael@0 455
michael@0 456 struct Nop {
michael@0 457 void operator()(const Value &v) { }
michael@0 458 };
michael@0 459
michael@0 460 private:
michael@0 461 void findNextFrame();
michael@0 462
michael@0 463 JSObject *computeScopeChain(Value scopeChainValue) const {
michael@0 464 if (scopeChainValue.isObject())
michael@0 465 return &scopeChainValue.toObject();
michael@0 466
michael@0 467 if (isFunctionFrame()) {
michael@0 468 // Heavyweight functions should always have a scope chain.
michael@0 469 MOZ_ASSERT(!callee()->isHeavyweight());
michael@0 470 return callee()->environment();
michael@0 471 }
michael@0 472
michael@0 473 // Ion does not handle scripts that are not compile-and-go.
michael@0 474 MOZ_ASSERT(!script()->isForEval());
michael@0 475 MOZ_ASSERT(script()->compileAndGo());
michael@0 476 return &script()->global();
michael@0 477 }
michael@0 478
michael@0 479 public:
michael@0 480 InlineFrameIteratorMaybeGC(JSContext *cx, const JitFrameIterator *iter)
michael@0 481 : callee_(cx),
michael@0 482 script_(cx)
michael@0 483 {
michael@0 484 resetOn(iter);
michael@0 485 }
michael@0 486
michael@0 487 InlineFrameIteratorMaybeGC(JSRuntime *rt, const JitFrameIterator *iter)
michael@0 488 : callee_(rt),
michael@0 489 script_(rt)
michael@0 490 {
michael@0 491 resetOn(iter);
michael@0 492 }
michael@0 493
michael@0 494 InlineFrameIteratorMaybeGC(JSContext *cx, const IonBailoutIterator *iter);
michael@0 495
michael@0 496 InlineFrameIteratorMaybeGC(JSContext *cx, const InlineFrameIteratorMaybeGC *iter)
michael@0 497 : frame_(iter ? iter->frame_ : nullptr),
michael@0 498 framesRead_(0),
michael@0 499 frameCount_(iter ? iter->frameCount_ : UINT32_MAX),
michael@0 500 callee_(cx),
michael@0 501 script_(cx)
michael@0 502 {
michael@0 503 if (frame_) {
michael@0 504 start_ = SnapshotIterator(*frame_);
michael@0 505 // findNextFrame will iterate to the next frame and init. everything.
michael@0 506 // Therefore to settle on the same frame, we report one frame less readed.
michael@0 507 framesRead_ = iter->framesRead_ - 1;
michael@0 508 findNextFrame();
michael@0 509 }
michael@0 510 }
michael@0 511
michael@0 512 bool more() const {
michael@0 513 return frame_ && framesRead_ < frameCount_;
michael@0 514 }
michael@0 515 JSFunction *callee() const {
michael@0 516 JS_ASSERT(callee_);
michael@0 517 return callee_;
michael@0 518 }
michael@0 519 JSFunction *maybeCallee() const {
michael@0 520 return callee_;
michael@0 521 }
michael@0 522
michael@0 523 unsigned numActualArgs() const {
michael@0 524 // The number of actual arguments of inline frames is recovered by the
michael@0 525 // iteration process. It is recovered from the bytecode because this
michael@0 526 // property still hold since the for inlined frames. This property does not
michael@0 527 // hold for the parent frame because it can have optimize a call to
michael@0 528 // js_fun_call or js_fun_apply.
michael@0 529 if (more())
michael@0 530 return numActualArgs_;
michael@0 531
michael@0 532 return frame_->numActualArgs();
michael@0 533 }
michael@0 534
michael@0 535 template <class ArgOp, class LocalOp>
michael@0 536 void readFrameArgsAndLocals(JSContext *cx, ArgOp &argOp, LocalOp &localOp,
michael@0 537 JSObject **scopeChain, Value *rval,
michael@0 538 ArgumentsObject **argsObj, Value *thisv,
michael@0 539 ReadFrameArgsBehavior behavior) const
michael@0 540 {
michael@0 541 SnapshotIterator s(si_);
michael@0 542
michael@0 543 // Read frame slots common to both function and global frames.
michael@0 544 Value scopeChainValue;
michael@0 545 s.readCommonFrameSlots(&scopeChainValue, rval);
michael@0 546
michael@0 547 if (scopeChain)
michael@0 548 *scopeChain = computeScopeChain(scopeChainValue);
michael@0 549
michael@0 550 // Read arguments, which only function frames have.
michael@0 551 if (isFunctionFrame()) {
michael@0 552 unsigned nactual = numActualArgs();
michael@0 553 unsigned nformal = callee()->nargs();
michael@0 554
michael@0 555 // Get the non overflown arguments, which are taken from the inlined
michael@0 556 // frame, because it will have the updated value when JSOP_SETARG is
michael@0 557 // done.
michael@0 558 if (behavior != ReadFrame_Overflown)
michael@0 559 s.readFunctionFrameArgs(argOp, argsObj, thisv, 0, nformal, script());
michael@0 560
michael@0 561 if (behavior != ReadFrame_Formals) {
michael@0 562 if (more()) {
michael@0 563 // There is still a parent frame of this inlined frame. All
michael@0 564 // arguments (also the overflown) are the last pushed values
michael@0 565 // in the parent frame. To get the overflown arguments, we
michael@0 566 // need to take them from there.
michael@0 567
michael@0 568 // The overflown arguments are not available in current frame.
michael@0 569 // They are the last pushed arguments in the parent frame of
michael@0 570 // this inlined frame.
michael@0 571 InlineFrameIteratorMaybeGC it(cx, this);
michael@0 572 ++it;
michael@0 573 unsigned argsObjAdj = it.script()->argumentsHasVarBinding() ? 1 : 0;
michael@0 574 SnapshotIterator parent_s(it.snapshotIterator());
michael@0 575
michael@0 576 // Skip over all slots until we get to the last slots
michael@0 577 // (= arguments slots of callee) the +3 is for [this], [returnvalue],
michael@0 578 // [scopechain], and maybe +1 for [argsObj]
michael@0 579 JS_ASSERT(parent_s.numAllocations() >= nactual + 3 + argsObjAdj);
michael@0 580 unsigned skip = parent_s.numAllocations() - nactual - 3 - argsObjAdj;
michael@0 581 for (unsigned j = 0; j < skip; j++)
michael@0 582 parent_s.skip();
michael@0 583
michael@0 584 // Get the overflown arguments
michael@0 585 parent_s.readCommonFrameSlots(nullptr, nullptr);
michael@0 586 parent_s.readFunctionFrameArgs(argOp, nullptr, nullptr,
michael@0 587 nformal, nactual, it.script());
michael@0 588 } else {
michael@0 589 // There is no parent frame to this inlined frame, we can read
michael@0 590 // from the frame's Value vector directly.
michael@0 591 Value *argv = frame_->actualArgs();
michael@0 592 for (unsigned i = nformal; i < nactual; i++)
michael@0 593 argOp(argv[i]);
michael@0 594 }
michael@0 595 }
michael@0 596 }
michael@0 597
michael@0 598 // At this point we've read all the formals in s, and can read the
michael@0 599 // locals.
michael@0 600 for (unsigned i = 0; i < script()->nfixed(); i++)
michael@0 601 localOp(s.read());
michael@0 602 }
michael@0 603
michael@0 604 template <class Op>
michael@0 605 void unaliasedForEachActual(JSContext *cx, Op op, ReadFrameArgsBehavior behavior) const {
michael@0 606 Nop nop;
michael@0 607 readFrameArgsAndLocals(cx, op, nop, nullptr, nullptr, nullptr, nullptr, behavior);
michael@0 608 }
michael@0 609
michael@0 610 JSScript *script() const {
michael@0 611 return script_;
michael@0 612 }
michael@0 613 jsbytecode *pc() const {
michael@0 614 return pc_;
michael@0 615 }
michael@0 616 SnapshotIterator snapshotIterator() const {
michael@0 617 return si_;
michael@0 618 }
michael@0 619 bool isFunctionFrame() const;
michael@0 620 bool isConstructing() const;
michael@0 621
michael@0 622 JSObject *scopeChain() const {
michael@0 623 SnapshotIterator s(si_);
michael@0 624
michael@0 625 // scopeChain
michael@0 626 Value v = s.read();
michael@0 627 return computeScopeChain(v);
michael@0 628 }
michael@0 629
michael@0 630 JSObject *thisObject() const {
michael@0 631 // In strict modes, |this| may not be an object and thus may not be
michael@0 632 // readable which can either segv in read or trigger the assertion.
michael@0 633 Value v = thisValue();
michael@0 634 JS_ASSERT(v.isObject());
michael@0 635 return &v.toObject();
michael@0 636 }
michael@0 637
michael@0 638 Value thisValue() const {
michael@0 639 // JS_ASSERT(isConstructing(...));
michael@0 640 SnapshotIterator s(si_);
michael@0 641
michael@0 642 // scopeChain
michael@0 643 s.skip();
michael@0 644
michael@0 645 // return value
michael@0 646 s.skip();
michael@0 647
michael@0 648 // Arguments object.
michael@0 649 if (script()->argumentsHasVarBinding())
michael@0 650 s.skip();
michael@0 651
michael@0 652 return s.read();
michael@0 653 }
michael@0 654
michael@0 655 InlineFrameIteratorMaybeGC &operator++() {
michael@0 656 findNextFrame();
michael@0 657 return *this;
michael@0 658 }
michael@0 659
michael@0 660 void dump() const;
michael@0 661
michael@0 662 void resetOn(const JitFrameIterator *iter);
michael@0 663
michael@0 664 const JitFrameIterator &frame() const {
michael@0 665 return *frame_;
michael@0 666 }
michael@0 667
michael@0 668 // Inline frame number, 0 for the outermost (non-inlined) frame.
michael@0 669 size_t frameNo() const {
michael@0 670 return frameCount() - framesRead_;
michael@0 671 }
michael@0 672 size_t frameCount() const {
michael@0 673 MOZ_ASSERT(frameCount_ != UINT32_MAX);
michael@0 674 return frameCount_;
michael@0 675 }
michael@0 676
michael@0 677 private:
michael@0 678 InlineFrameIteratorMaybeGC() MOZ_DELETE;
michael@0 679 InlineFrameIteratorMaybeGC(const InlineFrameIteratorMaybeGC &iter) MOZ_DELETE;
michael@0 680 };
michael@0 681 typedef InlineFrameIteratorMaybeGC<CanGC> InlineFrameIterator;
michael@0 682 typedef InlineFrameIteratorMaybeGC<NoGC> InlineFrameIteratorNoGC;
michael@0 683
michael@0 684 } // namespace jit
michael@0 685 } // namespace js
michael@0 686
michael@0 687 #endif // JS_ION
michael@0 688
michael@0 689 #endif /* jit_JitFrameIterator_h */

mercurial