Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * vim: set ts=8 sts=4 et sw=4 tw=99:
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef jit_IonFrames_h
8 #define jit_IonFrames_h
10 #ifdef JS_ION
12 #include <stdint.h>
14 #include "jscntxt.h"
15 #include "jsfun.h"
17 #include "jit/JitFrameIterator.h"
19 namespace js {
20 namespace jit {
22 typedef void * CalleeToken;
24 enum CalleeTokenTag
25 {
26 CalleeToken_Function = 0x0, // untagged
27 CalleeToken_Script = 0x1
28 };
30 static inline CalleeTokenTag
31 GetCalleeTokenTag(CalleeToken token)
32 {
33 CalleeTokenTag tag = CalleeTokenTag(uintptr_t(token) & 0x3);
34 JS_ASSERT(tag <= CalleeToken_Script);
35 return tag;
36 }
37 static inline CalleeToken
38 CalleeToToken(JSFunction *fun)
39 {
40 return CalleeToken(uintptr_t(fun) | uintptr_t(CalleeToken_Function));
41 }
42 static inline CalleeToken
43 CalleeToToken(JSScript *script)
44 {
45 return CalleeToken(uintptr_t(script) | uintptr_t(CalleeToken_Script));
46 }
47 static inline bool
48 CalleeTokenIsFunction(CalleeToken token)
49 {
50 return GetCalleeTokenTag(token) == CalleeToken_Function;
51 }
52 static inline JSFunction *
53 CalleeTokenToFunction(CalleeToken token)
54 {
55 JS_ASSERT(CalleeTokenIsFunction(token));
56 return (JSFunction *)token;
57 }
58 static inline JSScript *
59 CalleeTokenToScript(CalleeToken token)
60 {
61 JS_ASSERT(GetCalleeTokenTag(token) == CalleeToken_Script);
62 return (JSScript *)(uintptr_t(token) & ~uintptr_t(0x3));
63 }
65 static inline JSScript *
66 ScriptFromCalleeToken(CalleeToken token)
67 {
68 switch (GetCalleeTokenTag(token)) {
69 case CalleeToken_Script:
70 return CalleeTokenToScript(token);
71 case CalleeToken_Function:
72 return CalleeTokenToFunction(token)->nonLazyScript();
73 }
74 MOZ_ASSUME_UNREACHABLE("invalid callee token tag");
75 }
77 // In between every two frames lies a small header describing both frames. This
78 // header, minimally, contains a returnAddress word and a descriptor word. The
79 // descriptor describes the size and type of the previous frame, whereas the
80 // returnAddress describes the address the newer frame (the callee) will return
81 // to. The exact mechanism in which frames are laid out is architecture
82 // dependent.
83 //
84 // Two special frame types exist. Entry frames begin an ion activation, and
85 // therefore there is exactly one per activation of jit::Cannon. Exit frames
86 // are necessary to leave JIT code and enter C++, and thus, C++ code will
87 // always begin iterating from the topmost exit frame.
89 class LSafepoint;
91 // Two-tuple that lets you look up the safepoint entry given the
92 // displacement of a call instruction within the JIT code.
93 class SafepointIndex
94 {
95 // The displacement is the distance from the first byte of the JIT'd code
96 // to the return address (of the call that the safepoint was generated for).
97 uint32_t displacement_;
99 union {
100 LSafepoint *safepoint_;
102 // Offset to the start of the encoded safepoint in the safepoint stream.
103 uint32_t safepointOffset_;
104 };
106 #ifdef DEBUG
107 bool resolved;
108 #endif
110 public:
111 SafepointIndex(uint32_t displacement, LSafepoint *safepoint)
112 : displacement_(displacement),
113 safepoint_(safepoint)
114 #ifdef DEBUG
115 , resolved(false)
116 #endif
117 { }
119 void resolve();
121 LSafepoint *safepoint() {
122 JS_ASSERT(!resolved);
123 return safepoint_;
124 }
125 uint32_t displacement() const {
126 return displacement_;
127 }
128 uint32_t safepointOffset() const {
129 return safepointOffset_;
130 }
131 void adjustDisplacement(uint32_t offset) {
132 JS_ASSERT(offset >= displacement_);
133 displacement_ = offset;
134 }
135 inline SnapshotOffset snapshotOffset() const;
136 inline bool hasSnapshotOffset() const;
137 };
139 class MacroAssembler;
140 // The OSI point is patched to a call instruction. Therefore, the
141 // returnPoint for an OSI call is the address immediately following that
142 // call instruction. The displacement of that point within the assembly
143 // buffer is the |returnPointDisplacement|.
144 class OsiIndex
145 {
146 uint32_t callPointDisplacement_;
147 uint32_t snapshotOffset_;
149 public:
150 OsiIndex(uint32_t callPointDisplacement, uint32_t snapshotOffset)
151 : callPointDisplacement_(callPointDisplacement),
152 snapshotOffset_(snapshotOffset)
153 { }
155 uint32_t returnPointDisplacement() const;
156 uint32_t callPointDisplacement() const {
157 return callPointDisplacement_;
158 }
159 uint32_t snapshotOffset() const {
160 return snapshotOffset_;
161 }
162 void fixUpOffset(MacroAssembler &masm);
163 };
165 // The layout of an Ion frame on the C stack is roughly:
166 // argN _
167 // ... \ - These are jsvals
168 // arg0 /
169 // -3 this _/
170 // -2 callee
171 // -1 descriptor
172 // 0 returnAddress
173 // .. locals ..
175 // The descriptor is organized into three sections:
176 // [ frame size | constructing bit | frame type ]
177 // < highest - - - - - - - - - - - - - - lowest >
178 static const uintptr_t FRAMESIZE_SHIFT = 4;
179 static const uintptr_t FRAMETYPE_BITS = 4;
180 static const uintptr_t FRAMETYPE_MASK = (1 << FRAMETYPE_BITS) - 1;
182 // Ion frames have a few important numbers associated with them:
183 // Local depth: The number of bytes required to spill local variables.
184 // Argument depth: The number of bytes required to push arguments and make
185 // a function call.
186 // Slack: A frame may temporarily use extra stack to resolve cycles.
187 //
188 // The (local + argument) depth determines the "fixed frame size". The fixed
189 // frame size is the distance between the stack pointer and the frame header.
190 // Thus, fixed >= (local + argument).
191 //
192 // In order to compress guards, we create shared jump tables that recover the
193 // script from the stack and recover a snapshot pointer based on which jump was
194 // taken. Thus, we create a jump table for each fixed frame size.
195 //
196 // Jump tables are big. To control the amount of jump tables we generate, each
197 // platform chooses how to segregate stack size classes based on its
198 // architecture.
199 //
200 // On some architectures, these jump tables are not used at all, or frame
201 // size segregation is not needed. Thus, there is an option for a frame to not
202 // have any frame size class, and to be totally dynamic.
203 static const uint32_t NO_FRAME_SIZE_CLASS_ID = uint32_t(-1);
205 class FrameSizeClass
206 {
207 uint32_t class_;
209 explicit FrameSizeClass(uint32_t class_) : class_(class_)
210 { }
212 public:
213 FrameSizeClass()
214 { }
216 static FrameSizeClass None() {
217 return FrameSizeClass(NO_FRAME_SIZE_CLASS_ID);
218 }
219 static FrameSizeClass FromClass(uint32_t class_) {
220 return FrameSizeClass(class_);
221 }
223 // These functions are implemented in specific CodeGenerator-* files.
224 static FrameSizeClass FromDepth(uint32_t frameDepth);
225 static FrameSizeClass ClassLimit();
226 uint32_t frameSize() const;
228 uint32_t classId() const {
229 JS_ASSERT(class_ != NO_FRAME_SIZE_CLASS_ID);
230 return class_;
231 }
233 bool operator ==(const FrameSizeClass &other) const {
234 return class_ == other.class_;
235 }
236 bool operator !=(const FrameSizeClass &other) const {
237 return class_ != other.class_;
238 }
239 };
241 struct BaselineBailoutInfo;
243 // Data needed to recover from an exception.
244 struct ResumeFromException
245 {
246 static const uint32_t RESUME_ENTRY_FRAME = 0;
247 static const uint32_t RESUME_CATCH = 1;
248 static const uint32_t RESUME_FINALLY = 2;
249 static const uint32_t RESUME_FORCED_RETURN = 3;
250 static const uint32_t RESUME_BAILOUT = 4;
252 uint8_t *framePointer;
253 uint8_t *stackPointer;
254 uint8_t *target;
255 uint32_t kind;
257 // Value to push when resuming into a |finally| block.
258 Value exception;
260 BaselineBailoutInfo *bailoutInfo;
261 };
263 void HandleException(ResumeFromException *rfe);
264 void HandleParallelFailure(ResumeFromException *rfe);
266 void EnsureExitFrame(IonCommonFrameLayout *frame);
268 void MarkJitActivations(JSRuntime *rt, JSTracer *trc);
269 void MarkIonCompilerRoots(JSTracer *trc);
271 #ifdef JSGC_GENERATIONAL
272 void UpdateJitActivationsForMinorGC(JSRuntime *rt, JSTracer *trc);
273 #endif
275 static inline uint32_t
276 MakeFrameDescriptor(uint32_t frameSize, FrameType type)
277 {
278 return (frameSize << FRAMESIZE_SHIFT) | type;
279 }
281 // Returns the JSScript associated with the topmost Ion frame.
282 inline JSScript *
283 GetTopIonJSScript(uint8_t *ionTop, void **returnAddrOut, ExecutionMode mode)
284 {
285 JitFrameIterator iter(ionTop, mode);
286 JS_ASSERT(iter.type() == JitFrame_Exit);
287 ++iter;
289 JS_ASSERT(iter.returnAddressToFp() != nullptr);
290 if (returnAddrOut)
291 *returnAddrOut = (void *) iter.returnAddressToFp();
293 if (iter.isBaselineStub()) {
294 ++iter;
295 JS_ASSERT(iter.isBaselineJS());
296 }
298 JS_ASSERT(iter.isScripted());
299 return iter.script();
300 }
302 static JitCode *const ION_FRAME_DOMGETTER = (JitCode *)0x1;
303 static JitCode *const ION_FRAME_DOMSETTER = (JitCode *)0x2;
304 static JitCode *const ION_FRAME_DOMMETHOD = (JitCode *)0x3;
305 static JitCode *const ION_FRAME_OOL_NATIVE = (JitCode *)0x4;
306 static JitCode *const ION_FRAME_OOL_PROPERTY_OP = (JitCode *)0x5;
307 static JitCode *const ION_FRAME_OOL_PROXY = (JitCode *)0x6;
309 // Layout of the frame prefix. This assumes the stack architecture grows down.
310 // If this is ever not the case, we'll have to refactor.
311 class IonCommonFrameLayout
312 {
313 uint8_t *returnAddress_;
314 uintptr_t descriptor_;
316 static const uintptr_t FrameTypeMask = (1 << FRAMETYPE_BITS) - 1;
318 public:
319 static size_t offsetOfDescriptor() {
320 return offsetof(IonCommonFrameLayout, descriptor_);
321 }
322 static size_t offsetOfReturnAddress() {
323 return offsetof(IonCommonFrameLayout, returnAddress_);
324 }
325 FrameType prevType() const {
326 return FrameType(descriptor_ & FrameTypeMask);
327 }
328 void changePrevType(FrameType type) {
329 descriptor_ &= ~FrameTypeMask;
330 descriptor_ |= type;
331 }
332 size_t prevFrameLocalSize() const {
333 return descriptor_ >> FRAMESIZE_SHIFT;
334 }
335 void setFrameDescriptor(size_t size, FrameType type) {
336 descriptor_ = (size << FRAMESIZE_SHIFT) | type;
337 }
338 uint8_t *returnAddress() const {
339 return returnAddress_;
340 }
341 void setReturnAddress(uint8_t *addr) {
342 returnAddress_ = addr;
343 }
344 };
346 class IonJSFrameLayout : public IonCommonFrameLayout
347 {
348 CalleeToken calleeToken_;
349 uintptr_t numActualArgs_;
351 public:
352 CalleeToken calleeToken() const {
353 return calleeToken_;
354 }
355 void replaceCalleeToken(CalleeToken calleeToken) {
356 calleeToken_ = calleeToken;
357 }
359 static size_t offsetOfCalleeToken() {
360 return offsetof(IonJSFrameLayout, calleeToken_);
361 }
362 static size_t offsetOfNumActualArgs() {
363 return offsetof(IonJSFrameLayout, numActualArgs_);
364 }
365 static size_t offsetOfThis() {
366 IonJSFrameLayout *base = nullptr;
367 return reinterpret_cast<size_t>(&base->argv()[0]);
368 }
369 static size_t offsetOfActualArgs() {
370 IonJSFrameLayout *base = nullptr;
371 // +1 to skip |this|.
372 return reinterpret_cast<size_t>(&base->argv()[1]);
373 }
374 static size_t offsetOfActualArg(size_t arg) {
375 return offsetOfActualArgs() + arg * sizeof(Value);
376 }
378 Value thisv() {
379 return argv()[0];
380 }
381 Value *argv() {
382 return (Value *)(this + 1);
383 }
384 uintptr_t numActualArgs() const {
385 return numActualArgs_;
386 }
388 // Computes a reference to a slot, where a slot is a distance from the base
389 // frame pointer (as would be used for LStackSlot).
390 uintptr_t *slotRef(uint32_t slot) {
391 return (uintptr_t *)((uint8_t *)this - slot);
392 }
394 static inline size_t Size() {
395 return sizeof(IonJSFrameLayout);
396 }
397 };
399 // this is the layout of the frame that is used when we enter Ion code from platform ABI code
400 class IonEntryFrameLayout : public IonJSFrameLayout
401 {
402 public:
403 static inline size_t Size() {
404 return sizeof(IonEntryFrameLayout);
405 }
406 };
408 class IonRectifierFrameLayout : public IonJSFrameLayout
409 {
410 public:
411 static inline size_t Size() {
412 return sizeof(IonRectifierFrameLayout);
413 }
414 };
416 // The callee token is now dead.
417 class IonUnwoundRectifierFrameLayout : public IonRectifierFrameLayout
418 {
419 public:
420 static inline size_t Size() {
421 // It is not necessary to accout for an extra callee token here because
422 // sizeof(IonExitFrameLayout) == sizeof(IonRectifierFrameLayout) due to
423 // extra padding.
424 return sizeof(IonUnwoundRectifierFrameLayout);
425 }
426 };
428 // GC related data used to keep alive data surrounding the Exit frame.
429 class IonExitFooterFrame
430 {
431 const VMFunction *function_;
432 JitCode *jitCode_;
434 public:
435 static inline size_t Size() {
436 return sizeof(IonExitFooterFrame);
437 }
438 inline JitCode *jitCode() const {
439 return jitCode_;
440 }
441 inline JitCode **addressOfJitCode() {
442 return &jitCode_;
443 }
444 inline const VMFunction *function() const {
445 return function_;
446 }
448 // This should only be called for function()->outParam == Type_Handle
449 template <typename T>
450 T *outParam() {
451 return reinterpret_cast<T *>(reinterpret_cast<char *>(this) - sizeof(T));
452 }
453 };
455 class IonNativeExitFrameLayout;
456 class IonOOLNativeExitFrameLayout;
457 class IonOOLPropertyOpExitFrameLayout;
458 class IonOOLProxyExitFrameLayout;
459 class IonDOMExitFrameLayout;
461 // this is the frame layout when we are exiting ion code, and about to enter platform ABI code
462 class IonExitFrameLayout : public IonCommonFrameLayout
463 {
464 inline uint8_t *top() {
465 return reinterpret_cast<uint8_t *>(this + 1);
466 }
468 public:
469 static inline size_t Size() {
470 return sizeof(IonExitFrameLayout);
471 }
472 static inline size_t SizeWithFooter() {
473 return Size() + IonExitFooterFrame::Size();
474 }
476 inline IonExitFooterFrame *footer() {
477 uint8_t *sp = reinterpret_cast<uint8_t *>(this);
478 return reinterpret_cast<IonExitFooterFrame *>(sp - IonExitFooterFrame::Size());
479 }
481 // argBase targets the point which precedes the exit frame. Arguments of VM
482 // each wrapper are pushed before the exit frame. This correspond exactly
483 // to the value of the argBase register of the generateVMWrapper function.
484 inline uint8_t *argBase() {
485 JS_ASSERT(footer()->jitCode() != nullptr);
486 return top();
487 }
489 inline bool isWrapperExit() {
490 return footer()->function() != nullptr;
491 }
492 inline bool isNativeExit() {
493 return footer()->jitCode() == nullptr;
494 }
495 inline bool isOOLNativeExit() {
496 return footer()->jitCode() == ION_FRAME_OOL_NATIVE;
497 }
498 inline bool isOOLPropertyOpExit() {
499 return footer()->jitCode() == ION_FRAME_OOL_PROPERTY_OP;
500 }
501 inline bool isOOLProxyExit() {
502 return footer()->jitCode() == ION_FRAME_OOL_PROXY;
503 }
504 inline bool isDomExit() {
505 JitCode *code = footer()->jitCode();
506 return
507 code == ION_FRAME_DOMGETTER ||
508 code == ION_FRAME_DOMSETTER ||
509 code == ION_FRAME_DOMMETHOD;
510 }
512 inline IonNativeExitFrameLayout *nativeExit() {
513 // see CodeGenerator::visitCallNative
514 JS_ASSERT(isNativeExit());
515 return reinterpret_cast<IonNativeExitFrameLayout *>(footer());
516 }
517 inline IonOOLNativeExitFrameLayout *oolNativeExit() {
518 JS_ASSERT(isOOLNativeExit());
519 return reinterpret_cast<IonOOLNativeExitFrameLayout *>(footer());
520 }
521 inline IonOOLPropertyOpExitFrameLayout *oolPropertyOpExit() {
522 JS_ASSERT(isOOLPropertyOpExit());
523 return reinterpret_cast<IonOOLPropertyOpExitFrameLayout *>(footer());
524 }
525 inline IonOOLProxyExitFrameLayout *oolProxyExit() {
526 JS_ASSERT(isOOLProxyExit());
527 return reinterpret_cast<IonOOLProxyExitFrameLayout *>(footer());
528 }
529 inline IonDOMExitFrameLayout *DOMExit() {
530 JS_ASSERT(isDomExit());
531 return reinterpret_cast<IonDOMExitFrameLayout *>(footer());
532 }
533 };
535 // Cannot inherit implementa<tion since we need to extend the top of
536 // IonExitFrameLayout.
537 class IonNativeExitFrameLayout
538 {
539 protected: // only to silence a clang warning about unused private fields
540 IonExitFooterFrame footer_;
541 IonExitFrameLayout exit_;
542 uintptr_t argc_;
544 // We need to split the Value into 2 fields of 32 bits, otherwise the C++
545 // compiler may add some padding between the fields.
546 uint32_t loCalleeResult_;
547 uint32_t hiCalleeResult_;
549 public:
550 static inline size_t Size() {
551 return sizeof(IonNativeExitFrameLayout);
552 }
554 static size_t offsetOfResult() {
555 return offsetof(IonNativeExitFrameLayout, loCalleeResult_);
556 }
557 inline Value *vp() {
558 return reinterpret_cast<Value*>(&loCalleeResult_);
559 }
560 inline uintptr_t argc() const {
561 return argc_;
562 }
563 };
565 class IonOOLNativeExitFrameLayout
566 {
567 protected: // only to silence a clang warning about unused private fields
568 IonExitFooterFrame footer_;
569 IonExitFrameLayout exit_;
571 // pointer to root the stub's JitCode
572 JitCode *stubCode_;
574 uintptr_t argc_;
576 // We need to split the Value into 2 fields of 32 bits, otherwise the C++
577 // compiler may add some padding between the fields.
578 uint32_t loCalleeResult_;
579 uint32_t hiCalleeResult_;
581 // Split Value for |this| and args above.
582 uint32_t loThis_;
583 uint32_t hiThis_;
585 public:
586 static inline size_t Size(size_t argc) {
587 // The frame accounts for the callee/result and |this|, so we only need args.
588 return sizeof(IonOOLNativeExitFrameLayout) + (argc * sizeof(Value));
589 }
591 static size_t offsetOfResult() {
592 return offsetof(IonOOLNativeExitFrameLayout, loCalleeResult_);
593 }
595 inline JitCode **stubCode() {
596 return &stubCode_;
597 }
598 inline Value *vp() {
599 return reinterpret_cast<Value*>(&loCalleeResult_);
600 }
601 inline Value *thisp() {
602 return reinterpret_cast<Value*>(&loThis_);
603 }
604 inline uintptr_t argc() const {
605 return argc_;
606 }
607 };
609 class IonOOLPropertyOpExitFrameLayout
610 {
611 protected: // only to silence a clang warning about unused private fields
612 IonExitFooterFrame footer_;
613 IonExitFrameLayout exit_;
615 // Object for HandleObject
616 JSObject *obj_;
618 // id for HandleId
619 jsid id_;
621 // space for MutableHandleValue result
622 // use two uint32_t so compiler doesn't align.
623 uint32_t vp0_;
624 uint32_t vp1_;
626 // pointer to root the stub's JitCode
627 JitCode *stubCode_;
629 public:
630 static inline size_t Size() {
631 return sizeof(IonOOLPropertyOpExitFrameLayout);
632 }
634 static size_t offsetOfResult() {
635 return offsetof(IonOOLPropertyOpExitFrameLayout, vp0_);
636 }
638 inline JitCode **stubCode() {
639 return &stubCode_;
640 }
641 inline Value *vp() {
642 return reinterpret_cast<Value*>(&vp0_);
643 }
644 inline jsid *id() {
645 return &id_;
646 }
647 inline JSObject **obj() {
648 return &obj_;
649 }
650 };
652 // Proxy::get(JSContext *cx, HandleObject proxy, HandleObject receiver, HandleId id,
653 // MutableHandleValue vp)
654 // Proxy::set(JSContext *cx, HandleObject proxy, HandleObject receiver, HandleId id,
655 // bool strict, MutableHandleValue vp)
656 class IonOOLProxyExitFrameLayout
657 {
658 protected: // only to silence a clang warning about unused private fields
659 IonExitFooterFrame footer_;
660 IonExitFrameLayout exit_;
662 // The proxy object.
663 JSObject *proxy_;
665 // Object for HandleObject
666 JSObject *receiver_;
668 // id for HandleId
669 jsid id_;
671 // space for MutableHandleValue result
672 // use two uint32_t so compiler doesn't align.
673 uint32_t vp0_;
674 uint32_t vp1_;
676 // pointer to root the stub's JitCode
677 JitCode *stubCode_;
679 public:
680 static inline size_t Size() {
681 return sizeof(IonOOLProxyExitFrameLayout);
682 }
684 static size_t offsetOfResult() {
685 return offsetof(IonOOLProxyExitFrameLayout, vp0_);
686 }
688 inline JitCode **stubCode() {
689 return &stubCode_;
690 }
691 inline Value *vp() {
692 return reinterpret_cast<Value*>(&vp0_);
693 }
694 inline jsid *id() {
695 return &id_;
696 }
697 inline JSObject **receiver() {
698 return &receiver_;
699 }
700 inline JSObject **proxy() {
701 return &proxy_;
702 }
703 };
705 class IonDOMExitFrameLayout
706 {
707 protected: // only to silence a clang warning about unused private fields
708 IonExitFooterFrame footer_;
709 IonExitFrameLayout exit_;
710 JSObject *thisObj;
712 // We need to split the Value into 2 fields of 32 bits, otherwise the C++
713 // compiler may add some padding between the fields.
714 uint32_t loCalleeResult_;
715 uint32_t hiCalleeResult_;
717 public:
718 static inline size_t Size() {
719 return sizeof(IonDOMExitFrameLayout);
720 }
722 static size_t offsetOfResult() {
723 return offsetof(IonDOMExitFrameLayout, loCalleeResult_);
724 }
725 inline Value *vp() {
726 return reinterpret_cast<Value*>(&loCalleeResult_);
727 }
728 inline JSObject **thisObjAddress() {
729 return &thisObj;
730 }
731 inline bool isMethodFrame() {
732 return footer_.jitCode() == ION_FRAME_DOMMETHOD;
733 }
734 };
736 struct IonDOMMethodExitFrameLayoutTraits;
738 class IonDOMMethodExitFrameLayout
739 {
740 protected: // only to silence a clang warning about unused private fields
741 IonExitFooterFrame footer_;
742 IonExitFrameLayout exit_;
743 // This must be the last thing pushed, so as to stay common with
744 // IonDOMExitFrameLayout.
745 JSObject *thisObj_;
746 Value *argv_;
747 uintptr_t argc_;
749 // We need to split the Value into 2 fields of 32 bits, otherwise the C++
750 // compiler may add some padding between the fields.
751 uint32_t loCalleeResult_;
752 uint32_t hiCalleeResult_;
754 friend struct IonDOMMethodExitFrameLayoutTraits;
756 public:
757 static inline size_t Size() {
758 return sizeof(IonDOMMethodExitFrameLayout);
759 }
761 static size_t offsetOfResult() {
762 return offsetof(IonDOMMethodExitFrameLayout, loCalleeResult_);
763 }
765 inline Value *vp() {
766 // The code in visitCallDOMNative depends on this static assert holding
767 JS_STATIC_ASSERT(offsetof(IonDOMMethodExitFrameLayout, loCalleeResult_) ==
768 (offsetof(IonDOMMethodExitFrameLayout, argc_) + sizeof(uintptr_t)));
769 return reinterpret_cast<Value*>(&loCalleeResult_);
770 }
771 inline JSObject **thisObjAddress() {
772 return &thisObj_;
773 }
774 inline uintptr_t argc() {
775 return argc_;
776 }
777 };
779 struct IonDOMMethodExitFrameLayoutTraits {
780 static const size_t offsetOfArgcFromArgv =
781 offsetof(IonDOMMethodExitFrameLayout, argc_) -
782 offsetof(IonDOMMethodExitFrameLayout, argv_);
783 };
785 class ICStub;
787 class IonBaselineStubFrameLayout : public IonCommonFrameLayout
788 {
789 public:
790 static inline size_t Size() {
791 return sizeof(IonBaselineStubFrameLayout);
792 }
794 static inline int reverseOffsetOfStubPtr() {
795 return -int(sizeof(void *));
796 }
797 static inline int reverseOffsetOfSavedFramePtr() {
798 return -int(2 * sizeof(void *));
799 }
801 inline ICStub *maybeStubPtr() {
802 uint8_t *fp = reinterpret_cast<uint8_t *>(this);
803 return *reinterpret_cast<ICStub **>(fp + reverseOffsetOfStubPtr());
804 }
805 inline void setStubPtr(ICStub *stub) {
806 uint8_t *fp = reinterpret_cast<uint8_t *>(this);
807 *reinterpret_cast<ICStub **>(fp + reverseOffsetOfStubPtr()) = stub;
808 }
809 };
811 // An invalidation bailout stack is at the stack pointer for the callee frame.
812 class InvalidationBailoutStack
813 {
814 mozilla::Array<double, FloatRegisters::Total> fpregs_;
815 mozilla::Array<uintptr_t, Registers::Total> regs_;
816 IonScript *ionScript_;
817 uint8_t *osiPointReturnAddress_;
819 public:
820 uint8_t *sp() const {
821 return (uint8_t *) this + sizeof(InvalidationBailoutStack);
822 }
823 IonJSFrameLayout *fp() const;
824 MachineState machine() {
825 return MachineState::FromBailout(regs_, fpregs_);
826 }
828 IonScript *ionScript() const {
829 return ionScript_;
830 }
831 uint8_t *osiPointReturnAddress() const {
832 return osiPointReturnAddress_;
833 }
835 void checkInvariants() const;
836 };
838 void
839 GetPcScript(JSContext *cx, JSScript **scriptRes, jsbytecode **pcRes);
841 CalleeToken
842 MarkCalleeToken(JSTracer *trc, CalleeToken token);
844 } /* namespace jit */
845 } /* namespace js */
847 #endif // JS_ION
849 #endif /* jit_IonFrames_h */