1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/js/src/jit/JitFrameIterator.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,689 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 1.5 + * vim: set ts=8 sts=4 et sw=4 tw=99: 1.6 + * This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#ifndef jit_JitFrameIterator_h 1.11 +#define jit_JitFrameIterator_h 1.12 + 1.13 +#ifdef JS_ION 1.14 + 1.15 +#include "jsfun.h" 1.16 +#include "jsscript.h" 1.17 +#include "jstypes.h" 1.18 + 1.19 +#include "jit/IonCode.h" 1.20 +#include "jit/Snapshots.h" 1.21 + 1.22 +namespace js { 1.23 + class ActivationIterator; 1.24 +}; 1.25 + 1.26 +namespace js { 1.27 +namespace jit { 1.28 + 1.29 +enum FrameType 1.30 +{ 1.31 + // A JS frame is analagous to a js::InterpreterFrame, representing one scripted 1.32 + // functon activation. IonJS frames are used by the optimizing compiler. 1.33 + JitFrame_IonJS, 1.34 + 1.35 + // JS frame used by the baseline JIT. 1.36 + JitFrame_BaselineJS, 1.37 + 1.38 + // Frame pushed for baseline JIT stubs that make non-tail calls, so that the 1.39 + // return address -> ICEntry mapping works. 1.40 + JitFrame_BaselineStub, 1.41 + 1.42 + // The entry frame is the initial prologue block transitioning from the VM 1.43 + // into the Ion world. 1.44 + JitFrame_Entry, 1.45 + 1.46 + // A rectifier frame sits in between two JS frames, adapting argc != nargs 1.47 + // mismatches in calls. 1.48 + JitFrame_Rectifier, 1.49 + 1.50 + // An unwound JS frame is a JS frame signalling that its callee frame has been 1.51 + // turned into an exit frame (see EnsureExitFrame). Used by Ion bailouts and 1.52 + // Baseline exception unwinding. 1.53 + JitFrame_Unwound_IonJS, 1.54 + 1.55 + // Like Unwound_IonJS, but the caller is a baseline stub frame. 1.56 + JitFrame_Unwound_BaselineStub, 1.57 + 1.58 + // An unwound rectifier frame is a rectifier frame signalling that its callee 1.59 + // frame has been turned into an exit frame (see EnsureExitFrame). 1.60 + JitFrame_Unwound_Rectifier, 1.61 + 1.62 + // An exit frame is necessary for transitioning from a JS frame into C++. 1.63 + // From within C++, an exit frame is always the last frame in any 1.64 + // JitActivation. 1.65 + JitFrame_Exit 1.66 +}; 1.67 + 1.68 +enum ReadFrameArgsBehavior { 1.69 + // Only read formals (i.e. [0 ... callee()->nargs] 1.70 + ReadFrame_Formals, 1.71 + 1.72 + // Only read overflown args (i.e. [callee()->nargs ... numActuals()] 1.73 + ReadFrame_Overflown, 1.74 + 1.75 + // Read all args (i.e. [0 ... numActuals()]) 1.76 + ReadFrame_Actuals 1.77 +}; 1.78 + 1.79 +class IonCommonFrameLayout; 1.80 +class IonJSFrameLayout; 1.81 +class IonExitFrameLayout; 1.82 + 1.83 +class BaselineFrame; 1.84 + 1.85 +class JitActivation; 1.86 + 1.87 +class JitFrameIterator 1.88 +{ 1.89 + protected: 1.90 + uint8_t *current_; 1.91 + FrameType type_; 1.92 + uint8_t *returnAddressToFp_; 1.93 + size_t frameSize_; 1.94 + 1.95 + private: 1.96 + mutable const SafepointIndex *cachedSafepointIndex_; 1.97 + const JitActivation *activation_; 1.98 + ExecutionMode mode_; 1.99 + 1.100 + void dumpBaseline() const; 1.101 + 1.102 + public: 1.103 + explicit JitFrameIterator(uint8_t *top, ExecutionMode mode) 1.104 + : current_(top), 1.105 + type_(JitFrame_Exit), 1.106 + returnAddressToFp_(nullptr), 1.107 + frameSize_(0), 1.108 + cachedSafepointIndex_(nullptr), 1.109 + activation_(nullptr), 1.110 + mode_(mode) 1.111 + { } 1.112 + 1.113 + explicit JitFrameIterator(JSContext *cx); 1.114 + explicit JitFrameIterator(const ActivationIterator &activations); 1.115 + explicit JitFrameIterator(IonJSFrameLayout *fp, ExecutionMode mode); 1.116 + 1.117 + // Current frame information. 1.118 + FrameType type() const { 1.119 + return type_; 1.120 + } 1.121 + uint8_t *fp() const { 1.122 + return current_; 1.123 + } 1.124 + const JitActivation *activation() const { 1.125 + return activation_; 1.126 + } 1.127 + 1.128 + IonCommonFrameLayout *current() const { 1.129 + return (IonCommonFrameLayout *)current_; 1.130 + } 1.131 + 1.132 + inline uint8_t *returnAddress() const; 1.133 + 1.134 + IonJSFrameLayout *jsFrame() const { 1.135 + JS_ASSERT(isScripted()); 1.136 + return (IonJSFrameLayout *) fp(); 1.137 + } 1.138 + 1.139 + // Returns true iff this exit frame was created using EnsureExitFrame. 1.140 + inline bool isFakeExitFrame() const; 1.141 + 1.142 + inline IonExitFrameLayout *exitFrame() const; 1.143 + 1.144 + // Returns whether the JS frame has been invalidated and, if so, 1.145 + // places the invalidated Ion script in |ionScript|. 1.146 + bool checkInvalidation(IonScript **ionScript) const; 1.147 + bool checkInvalidation() const; 1.148 + 1.149 + bool isScripted() const { 1.150 + return type_ == JitFrame_BaselineJS || type_ == JitFrame_IonJS; 1.151 + } 1.152 + bool isBaselineJS() const { 1.153 + return type_ == JitFrame_BaselineJS; 1.154 + } 1.155 + bool isIonJS() const { 1.156 + return type_ == JitFrame_IonJS; 1.157 + } 1.158 + bool isBaselineStub() const { 1.159 + return type_ == JitFrame_BaselineStub; 1.160 + } 1.161 + bool isNative() const; 1.162 + bool isOOLNative() const; 1.163 + bool isOOLPropertyOp() const; 1.164 + bool isOOLProxy() const; 1.165 + bool isDOMExit() const; 1.166 + bool isEntry() const { 1.167 + return type_ == JitFrame_Entry; 1.168 + } 1.169 + bool isFunctionFrame() const; 1.170 + 1.171 + bool isConstructing() const; 1.172 + 1.173 + void *calleeToken() const; 1.174 + JSFunction *callee() const; 1.175 + JSFunction *maybeCallee() const; 1.176 + unsigned numActualArgs() const; 1.177 + JSScript *script() const; 1.178 + void baselineScriptAndPc(JSScript **scriptRes, jsbytecode **pcRes) const; 1.179 + Value *actualArgs() const; 1.180 + 1.181 + // Returns the return address of the frame above this one (that is, the 1.182 + // return address that returns back to the current frame). 1.183 + uint8_t *returnAddressToFp() const { 1.184 + return returnAddressToFp_; 1.185 + } 1.186 + 1.187 + // Previous frame information extracted from the current frame. 1.188 + inline size_t prevFrameLocalSize() const; 1.189 + inline FrameType prevType() const; 1.190 + uint8_t *prevFp() const; 1.191 + 1.192 + // Returns the stack space used by the current frame, in bytes. This does 1.193 + // not include the size of its fixed header. 1.194 + size_t frameSize() const { 1.195 + JS_ASSERT(type_ != JitFrame_Exit); 1.196 + return frameSize_; 1.197 + } 1.198 + 1.199 + // Functions used to iterate on frames. When prevType is JitFrame_Entry, 1.200 + // the current frame is the last frame. 1.201 + inline bool done() const { 1.202 + return type_ == JitFrame_Entry; 1.203 + } 1.204 + JitFrameIterator &operator++(); 1.205 + 1.206 + // Returns the IonScript associated with this JS frame. 1.207 + IonScript *ionScript() const; 1.208 + 1.209 + // Returns the Safepoint associated with this JS frame. Incurs a lookup 1.210 + // overhead. 1.211 + const SafepointIndex *safepoint() const; 1.212 + 1.213 + // Returns the OSI index associated with this JS frame. Incurs a lookup 1.214 + // overhead. 1.215 + const OsiIndex *osiIndex() const; 1.216 + 1.217 + uintptr_t *spillBase() const; 1.218 + MachineState machineState() const; 1.219 + 1.220 + template <class Op> 1.221 + void unaliasedForEachActual(Op op, ReadFrameArgsBehavior behavior) const { 1.222 + JS_ASSERT(isBaselineJS()); 1.223 + 1.224 + unsigned nactual = numActualArgs(); 1.225 + unsigned start, end; 1.226 + switch (behavior) { 1.227 + case ReadFrame_Formals: 1.228 + start = 0; 1.229 + end = callee()->nargs(); 1.230 + break; 1.231 + case ReadFrame_Overflown: 1.232 + start = callee()->nargs(); 1.233 + end = nactual; 1.234 + break; 1.235 + case ReadFrame_Actuals: 1.236 + start = 0; 1.237 + end = nactual; 1.238 + } 1.239 + 1.240 + Value *argv = actualArgs(); 1.241 + for (unsigned i = start; i < end; i++) 1.242 + op(argv[i]); 1.243 + } 1.244 + 1.245 + void dump() const; 1.246 + 1.247 + inline BaselineFrame *baselineFrame() const; 1.248 +}; 1.249 + 1.250 +class IonJSFrameLayout; 1.251 +class IonBailoutIterator; 1.252 + 1.253 +class RResumePoint; 1.254 + 1.255 +// Reads frame information in snapshot-encoding order (that is, outermost frame 1.256 +// to innermost frame). 1.257 +class SnapshotIterator 1.258 +{ 1.259 + SnapshotReader snapshot_; 1.260 + RecoverReader recover_; 1.261 + IonJSFrameLayout *fp_; 1.262 + MachineState machine_; 1.263 + IonScript *ionScript_; 1.264 + 1.265 + private: 1.266 + // Read a spilled register from the machine state. 1.267 + bool hasRegister(Register reg) const { 1.268 + return machine_.has(reg); 1.269 + } 1.270 + uintptr_t fromRegister(Register reg) const { 1.271 + return machine_.read(reg); 1.272 + } 1.273 + 1.274 + bool hasRegister(FloatRegister reg) const { 1.275 + return machine_.has(reg); 1.276 + } 1.277 + double fromRegister(FloatRegister reg) const { 1.278 + return machine_.read(reg); 1.279 + } 1.280 + 1.281 + // Read an uintptr_t from the stack. 1.282 + bool hasStack(int32_t offset) const { 1.283 + return true; 1.284 + } 1.285 + uintptr_t fromStack(int32_t offset) const; 1.286 + 1.287 + Value allocationValue(const RValueAllocation &a); 1.288 + bool allocationReadable(const RValueAllocation &a); 1.289 + void warnUnreadableAllocation(); 1.290 + 1.291 + public: 1.292 + // Handle iterating over RValueAllocations of the snapshots. 1.293 + inline RValueAllocation readAllocation() { 1.294 + MOZ_ASSERT(moreAllocations()); 1.295 + return snapshot_.readAllocation(); 1.296 + } 1.297 + Value skip() { 1.298 + snapshot_.skipAllocation(); 1.299 + return UndefinedValue(); 1.300 + } 1.301 + 1.302 + const RResumePoint *resumePoint() const; 1.303 + const RInstruction *instruction() const { 1.304 + return recover_.instruction(); 1.305 + } 1.306 + 1.307 + uint32_t numAllocations() const; 1.308 + inline bool moreAllocations() const { 1.309 + return snapshot_.numAllocationsRead() < numAllocations(); 1.310 + } 1.311 + 1.312 + public: 1.313 + // Exhibits frame properties contained in the snapshot. 1.314 + uint32_t pcOffset() const; 1.315 + inline bool resumeAfter() const { 1.316 + // Inline frames are inlined on calls, which are considered as being 1.317 + // resumed on the Call as baseline will push the pc once we return from 1.318 + // the call. 1.319 + if (moreFrames()) 1.320 + return false; 1.321 + return recover_.resumeAfter(); 1.322 + } 1.323 + inline BailoutKind bailoutKind() const { 1.324 + return snapshot_.bailoutKind(); 1.325 + } 1.326 + 1.327 + public: 1.328 + // Read the next instruction available and get ready to either skip it or 1.329 + // evaluate it. 1.330 + inline void nextInstruction() { 1.331 + MOZ_ASSERT(snapshot_.numAllocationsRead() == numAllocations()); 1.332 + recover_.nextInstruction(); 1.333 + snapshot_.resetNumAllocationsRead(); 1.334 + } 1.335 + 1.336 + // Skip an Instruction by walking to the next instruction and by skipping 1.337 + // all the allocations corresponding to this instruction. 1.338 + void skipInstruction(); 1.339 + 1.340 + inline bool moreInstructions() const { 1.341 + return recover_.moreInstructions(); 1.342 + } 1.343 + 1.344 + public: 1.345 + // Handle iterating over frames of the snapshots. 1.346 + void nextFrame(); 1.347 + 1.348 + inline bool moreFrames() const { 1.349 + // The last instruction is recovering the innermost frame, so as long as 1.350 + // there is more instruction there is necesseray more frames. 1.351 + return moreInstructions(); 1.352 + } 1.353 + 1.354 + public: 1.355 + // Connect all informations about the current script in order to recover the 1.356 + // content of baseline frames. 1.357 + 1.358 + SnapshotIterator(IonScript *ionScript, SnapshotOffset snapshotOffset, 1.359 + IonJSFrameLayout *fp, const MachineState &machine); 1.360 + SnapshotIterator(const JitFrameIterator &iter); 1.361 + SnapshotIterator(const IonBailoutIterator &iter); 1.362 + SnapshotIterator(); 1.363 + 1.364 + Value read() { 1.365 + return allocationValue(readAllocation()); 1.366 + } 1.367 + Value maybeRead(bool silentFailure = false) { 1.368 + RValueAllocation a = readAllocation(); 1.369 + if (allocationReadable(a)) 1.370 + return allocationValue(a); 1.371 + if (!silentFailure) 1.372 + warnUnreadableAllocation(); 1.373 + return UndefinedValue(); 1.374 + } 1.375 + 1.376 + void readCommonFrameSlots(Value *scopeChain, Value *rval) { 1.377 + if (scopeChain) 1.378 + *scopeChain = read(); 1.379 + else 1.380 + skip(); 1.381 + 1.382 + if (rval) 1.383 + *rval = read(); 1.384 + else 1.385 + skip(); 1.386 + } 1.387 + 1.388 + template <class Op> 1.389 + void readFunctionFrameArgs(Op &op, ArgumentsObject **argsObj, Value *thisv, 1.390 + unsigned start, unsigned end, JSScript *script) 1.391 + { 1.392 + // Assumes that the common frame arguments have already been read. 1.393 + if (script->argumentsHasVarBinding()) { 1.394 + if (argsObj) { 1.395 + Value v = read(); 1.396 + if (v.isObject()) 1.397 + *argsObj = &v.toObject().as<ArgumentsObject>(); 1.398 + } else { 1.399 + skip(); 1.400 + } 1.401 + } 1.402 + 1.403 + if (thisv) 1.404 + *thisv = read(); 1.405 + else 1.406 + skip(); 1.407 + 1.408 + unsigned i = 0; 1.409 + if (end < start) 1.410 + i = start; 1.411 + 1.412 + for (; i < start; i++) 1.413 + skip(); 1.414 + for (; i < end; i++) { 1.415 + // We are not always able to read values from the snapshots, some values 1.416 + // such as non-gc things may still be live in registers and cause an 1.417 + // error while reading the machine state. 1.418 + Value v = maybeRead(); 1.419 + op(v); 1.420 + } 1.421 + } 1.422 + 1.423 + Value maybeReadAllocByIndex(size_t index) { 1.424 + while (index--) { 1.425 + JS_ASSERT(moreAllocations()); 1.426 + skip(); 1.427 + } 1.428 + 1.429 + Value s = maybeRead(true); 1.430 + 1.431 + while (moreAllocations()) 1.432 + skip(); 1.433 + 1.434 + return s; 1.435 + } 1.436 +}; 1.437 + 1.438 +// Reads frame information in callstack order (that is, innermost frame to 1.439 +// outermost frame). 1.440 +template <AllowGC allowGC=CanGC> 1.441 +class InlineFrameIteratorMaybeGC 1.442 +{ 1.443 + const JitFrameIterator *frame_; 1.444 + SnapshotIterator start_; 1.445 + SnapshotIterator si_; 1.446 + uint32_t framesRead_; 1.447 + 1.448 + // When the inline-frame-iterator is created, this variable is defined to 1.449 + // UINT32_MAX. Then the first iteration of findNextFrame, which settle on 1.450 + // the innermost frame, is used to update this counter to the number of 1.451 + // frames contained in the recover buffer. 1.452 + uint32_t frameCount_; 1.453 + 1.454 + typename MaybeRooted<JSFunction*, allowGC>::RootType callee_; 1.455 + typename MaybeRooted<JSScript*, allowGC>::RootType script_; 1.456 + jsbytecode *pc_; 1.457 + uint32_t numActualArgs_; 1.458 + 1.459 + struct Nop { 1.460 + void operator()(const Value &v) { } 1.461 + }; 1.462 + 1.463 + private: 1.464 + void findNextFrame(); 1.465 + 1.466 + JSObject *computeScopeChain(Value scopeChainValue) const { 1.467 + if (scopeChainValue.isObject()) 1.468 + return &scopeChainValue.toObject(); 1.469 + 1.470 + if (isFunctionFrame()) { 1.471 + // Heavyweight functions should always have a scope chain. 1.472 + MOZ_ASSERT(!callee()->isHeavyweight()); 1.473 + return callee()->environment(); 1.474 + } 1.475 + 1.476 + // Ion does not handle scripts that are not compile-and-go. 1.477 + MOZ_ASSERT(!script()->isForEval()); 1.478 + MOZ_ASSERT(script()->compileAndGo()); 1.479 + return &script()->global(); 1.480 + } 1.481 + 1.482 + public: 1.483 + InlineFrameIteratorMaybeGC(JSContext *cx, const JitFrameIterator *iter) 1.484 + : callee_(cx), 1.485 + script_(cx) 1.486 + { 1.487 + resetOn(iter); 1.488 + } 1.489 + 1.490 + InlineFrameIteratorMaybeGC(JSRuntime *rt, const JitFrameIterator *iter) 1.491 + : callee_(rt), 1.492 + script_(rt) 1.493 + { 1.494 + resetOn(iter); 1.495 + } 1.496 + 1.497 + InlineFrameIteratorMaybeGC(JSContext *cx, const IonBailoutIterator *iter); 1.498 + 1.499 + InlineFrameIteratorMaybeGC(JSContext *cx, const InlineFrameIteratorMaybeGC *iter) 1.500 + : frame_(iter ? iter->frame_ : nullptr), 1.501 + framesRead_(0), 1.502 + frameCount_(iter ? iter->frameCount_ : UINT32_MAX), 1.503 + callee_(cx), 1.504 + script_(cx) 1.505 + { 1.506 + if (frame_) { 1.507 + start_ = SnapshotIterator(*frame_); 1.508 + // findNextFrame will iterate to the next frame and init. everything. 1.509 + // Therefore to settle on the same frame, we report one frame less readed. 1.510 + framesRead_ = iter->framesRead_ - 1; 1.511 + findNextFrame(); 1.512 + } 1.513 + } 1.514 + 1.515 + bool more() const { 1.516 + return frame_ && framesRead_ < frameCount_; 1.517 + } 1.518 + JSFunction *callee() const { 1.519 + JS_ASSERT(callee_); 1.520 + return callee_; 1.521 + } 1.522 + JSFunction *maybeCallee() const { 1.523 + return callee_; 1.524 + } 1.525 + 1.526 + unsigned numActualArgs() const { 1.527 + // The number of actual arguments of inline frames is recovered by the 1.528 + // iteration process. It is recovered from the bytecode because this 1.529 + // property still hold since the for inlined frames. This property does not 1.530 + // hold for the parent frame because it can have optimize a call to 1.531 + // js_fun_call or js_fun_apply. 1.532 + if (more()) 1.533 + return numActualArgs_; 1.534 + 1.535 + return frame_->numActualArgs(); 1.536 + } 1.537 + 1.538 + template <class ArgOp, class LocalOp> 1.539 + void readFrameArgsAndLocals(JSContext *cx, ArgOp &argOp, LocalOp &localOp, 1.540 + JSObject **scopeChain, Value *rval, 1.541 + ArgumentsObject **argsObj, Value *thisv, 1.542 + ReadFrameArgsBehavior behavior) const 1.543 + { 1.544 + SnapshotIterator s(si_); 1.545 + 1.546 + // Read frame slots common to both function and global frames. 1.547 + Value scopeChainValue; 1.548 + s.readCommonFrameSlots(&scopeChainValue, rval); 1.549 + 1.550 + if (scopeChain) 1.551 + *scopeChain = computeScopeChain(scopeChainValue); 1.552 + 1.553 + // Read arguments, which only function frames have. 1.554 + if (isFunctionFrame()) { 1.555 + unsigned nactual = numActualArgs(); 1.556 + unsigned nformal = callee()->nargs(); 1.557 + 1.558 + // Get the non overflown arguments, which are taken from the inlined 1.559 + // frame, because it will have the updated value when JSOP_SETARG is 1.560 + // done. 1.561 + if (behavior != ReadFrame_Overflown) 1.562 + s.readFunctionFrameArgs(argOp, argsObj, thisv, 0, nformal, script()); 1.563 + 1.564 + if (behavior != ReadFrame_Formals) { 1.565 + if (more()) { 1.566 + // There is still a parent frame of this inlined frame. All 1.567 + // arguments (also the overflown) are the last pushed values 1.568 + // in the parent frame. To get the overflown arguments, we 1.569 + // need to take them from there. 1.570 + 1.571 + // The overflown arguments are not available in current frame. 1.572 + // They are the last pushed arguments in the parent frame of 1.573 + // this inlined frame. 1.574 + InlineFrameIteratorMaybeGC it(cx, this); 1.575 + ++it; 1.576 + unsigned argsObjAdj = it.script()->argumentsHasVarBinding() ? 1 : 0; 1.577 + SnapshotIterator parent_s(it.snapshotIterator()); 1.578 + 1.579 + // Skip over all slots until we get to the last slots 1.580 + // (= arguments slots of callee) the +3 is for [this], [returnvalue], 1.581 + // [scopechain], and maybe +1 for [argsObj] 1.582 + JS_ASSERT(parent_s.numAllocations() >= nactual + 3 + argsObjAdj); 1.583 + unsigned skip = parent_s.numAllocations() - nactual - 3 - argsObjAdj; 1.584 + for (unsigned j = 0; j < skip; j++) 1.585 + parent_s.skip(); 1.586 + 1.587 + // Get the overflown arguments 1.588 + parent_s.readCommonFrameSlots(nullptr, nullptr); 1.589 + parent_s.readFunctionFrameArgs(argOp, nullptr, nullptr, 1.590 + nformal, nactual, it.script()); 1.591 + } else { 1.592 + // There is no parent frame to this inlined frame, we can read 1.593 + // from the frame's Value vector directly. 1.594 + Value *argv = frame_->actualArgs(); 1.595 + for (unsigned i = nformal; i < nactual; i++) 1.596 + argOp(argv[i]); 1.597 + } 1.598 + } 1.599 + } 1.600 + 1.601 + // At this point we've read all the formals in s, and can read the 1.602 + // locals. 1.603 + for (unsigned i = 0; i < script()->nfixed(); i++) 1.604 + localOp(s.read()); 1.605 + } 1.606 + 1.607 + template <class Op> 1.608 + void unaliasedForEachActual(JSContext *cx, Op op, ReadFrameArgsBehavior behavior) const { 1.609 + Nop nop; 1.610 + readFrameArgsAndLocals(cx, op, nop, nullptr, nullptr, nullptr, nullptr, behavior); 1.611 + } 1.612 + 1.613 + JSScript *script() const { 1.614 + return script_; 1.615 + } 1.616 + jsbytecode *pc() const { 1.617 + return pc_; 1.618 + } 1.619 + SnapshotIterator snapshotIterator() const { 1.620 + return si_; 1.621 + } 1.622 + bool isFunctionFrame() const; 1.623 + bool isConstructing() const; 1.624 + 1.625 + JSObject *scopeChain() const { 1.626 + SnapshotIterator s(si_); 1.627 + 1.628 + // scopeChain 1.629 + Value v = s.read(); 1.630 + return computeScopeChain(v); 1.631 + } 1.632 + 1.633 + JSObject *thisObject() const { 1.634 + // In strict modes, |this| may not be an object and thus may not be 1.635 + // readable which can either segv in read or trigger the assertion. 1.636 + Value v = thisValue(); 1.637 + JS_ASSERT(v.isObject()); 1.638 + return &v.toObject(); 1.639 + } 1.640 + 1.641 + Value thisValue() const { 1.642 + // JS_ASSERT(isConstructing(...)); 1.643 + SnapshotIterator s(si_); 1.644 + 1.645 + // scopeChain 1.646 + s.skip(); 1.647 + 1.648 + // return value 1.649 + s.skip(); 1.650 + 1.651 + // Arguments object. 1.652 + if (script()->argumentsHasVarBinding()) 1.653 + s.skip(); 1.654 + 1.655 + return s.read(); 1.656 + } 1.657 + 1.658 + InlineFrameIteratorMaybeGC &operator++() { 1.659 + findNextFrame(); 1.660 + return *this; 1.661 + } 1.662 + 1.663 + void dump() const; 1.664 + 1.665 + void resetOn(const JitFrameIterator *iter); 1.666 + 1.667 + const JitFrameIterator &frame() const { 1.668 + return *frame_; 1.669 + } 1.670 + 1.671 + // Inline frame number, 0 for the outermost (non-inlined) frame. 1.672 + size_t frameNo() const { 1.673 + return frameCount() - framesRead_; 1.674 + } 1.675 + size_t frameCount() const { 1.676 + MOZ_ASSERT(frameCount_ != UINT32_MAX); 1.677 + return frameCount_; 1.678 + } 1.679 + 1.680 + private: 1.681 + InlineFrameIteratorMaybeGC() MOZ_DELETE; 1.682 + InlineFrameIteratorMaybeGC(const InlineFrameIteratorMaybeGC &iter) MOZ_DELETE; 1.683 +}; 1.684 +typedef InlineFrameIteratorMaybeGC<CanGC> InlineFrameIterator; 1.685 +typedef InlineFrameIteratorMaybeGC<NoGC> InlineFrameIteratorNoGC; 1.686 + 1.687 +} // namespace jit 1.688 +} // namespace js 1.689 + 1.690 +#endif // JS_ION 1.691 + 1.692 +#endif /* jit_JitFrameIterator_h */