js/src/jit/IonCode.h

branch
TOR_BUG_3246
changeset 7
129ffea94266
equal deleted inserted replaced
-1:000000000000 0:876948db24a0
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/. */
6
7 #ifndef jit_IonCode_h
8 #define jit_IonCode_h
9
10 #include "mozilla/Atomics.h"
11 #include "mozilla/MemoryReporting.h"
12 #include "mozilla/PodOperations.h"
13
14 #include "jsinfer.h"
15 #include "jstypes.h"
16
17 #include "assembler/jit/ExecutableAllocator.h"
18 #include "gc/Heap.h"
19 #include "jit/IonOptimizationLevels.h"
20 #include "jit/IonTypes.h"
21
22 namespace JSC {
23 class ExecutablePool;
24 }
25
26 namespace js {
27
28 class AsmJSModule;
29
30 namespace jit {
31
32 class MacroAssembler;
33 class CodeOffsetLabel;
34 class PatchableBackedge;
35
36 class JitCode : public gc::BarrieredCell<JitCode>
37 {
38 protected:
39 uint8_t *code_;
40 JSC::ExecutablePool *pool_;
41 uint32_t bufferSize_; // Total buffer size. Does not include headerSize_.
42 uint32_t insnSize_; // Instruction stream size.
43 uint32_t dataSize_; // Size of the read-only data area.
44 uint32_t jumpRelocTableBytes_; // Size of the jump relocation table.
45 uint32_t dataRelocTableBytes_; // Size of the data relocation table.
46 uint32_t preBarrierTableBytes_; // Size of the prebarrier table.
47 uint8_t headerSize_ : 5; // Number of bytes allocated before codeStart.
48 uint8_t kind_ : 3; // JSC::CodeKind, for the memory reporters.
49 bool invalidated_ : 1; // Whether the code object has been invalidated.
50 // This is necessary to prevent GC tracing.
51
52 #if JS_BITS_PER_WORD == 32
53 // Ensure JitCode is gc::Cell aligned.
54 uint32_t padding_;
55 #endif
56
57 JitCode()
58 : code_(nullptr),
59 pool_(nullptr)
60 { }
61 JitCode(uint8_t *code, uint32_t bufferSize, uint32_t headerSize, JSC::ExecutablePool *pool,
62 JSC::CodeKind kind)
63 : code_(code),
64 pool_(pool),
65 bufferSize_(bufferSize),
66 insnSize_(0),
67 dataSize_(0),
68 jumpRelocTableBytes_(0),
69 dataRelocTableBytes_(0),
70 preBarrierTableBytes_(0),
71 headerSize_(headerSize),
72 kind_(kind),
73 invalidated_(false)
74 {
75 MOZ_ASSERT(JSC::CodeKind(kind_) == kind);
76 MOZ_ASSERT(headerSize_ == headerSize);
77 }
78
79 uint32_t dataOffset() const {
80 return insnSize_;
81 }
82 uint32_t jumpRelocTableOffset() const {
83 return dataOffset() + dataSize_;
84 }
85 uint32_t dataRelocTableOffset() const {
86 return jumpRelocTableOffset() + jumpRelocTableBytes_;
87 }
88 uint32_t preBarrierTableOffset() const {
89 return dataRelocTableOffset() + dataRelocTableBytes_;
90 }
91
92 public:
93 uint8_t *raw() const {
94 return code_;
95 }
96 size_t instructionsSize() const {
97 return insnSize_;
98 }
99 void trace(JSTracer *trc);
100 void finalize(FreeOp *fop);
101 void setInvalidated() {
102 invalidated_ = true;
103 }
104
105 void togglePreBarriers(bool enabled);
106
107 // If this JitCode object has been, effectively, corrupted due to
108 // invalidation patching, then we have to remember this so we don't try and
109 // trace relocation entries that may now be corrupt.
110 bool invalidated() const {
111 return !!invalidated_;
112 }
113
114 template <typename T> T as() const {
115 return JS_DATA_TO_FUNC_PTR(T, raw());
116 }
117
118 void copyFrom(MacroAssembler &masm);
119
120 static JitCode *FromExecutable(uint8_t *buffer) {
121 JitCode *code = *(JitCode **)(buffer - sizeof(JitCode *));
122 JS_ASSERT(code->raw() == buffer);
123 return code;
124 }
125
126 static size_t offsetOfCode() {
127 return offsetof(JitCode, code_);
128 }
129
130 uint8_t *jumpRelocTable() {
131 return code_ + jumpRelocTableOffset();
132 }
133
134 // Allocates a new JitCode object which will be managed by the GC. If no
135 // object can be allocated, nullptr is returned. On failure, |pool| is
136 // automatically released, so the code may be freed.
137 template <AllowGC allowGC>
138 static JitCode *New(JSContext *cx, uint8_t *code, uint32_t bufferSize, uint32_t headerSize,
139 JSC::ExecutablePool *pool, JSC::CodeKind kind);
140
141 public:
142 static inline ThingRootKind rootKind() { return THING_ROOT_JIT_CODE; }
143 };
144
145 class SnapshotWriter;
146 class RecoverWriter;
147 class SafepointWriter;
148 class SafepointIndex;
149 class OsiIndex;
150 class IonCache;
151 struct PatchableBackedgeInfo;
152 struct CacheLocation;
153
154 // Describes a single AsmJSModule which jumps (via an FFI exit with the given
155 // index) directly into an IonScript.
156 struct DependentAsmJSModuleExit
157 {
158 const AsmJSModule *module;
159 size_t exitIndex;
160
161 DependentAsmJSModuleExit(const AsmJSModule *module, size_t exitIndex)
162 : module(module),
163 exitIndex(exitIndex)
164 { }
165 };
166
167 // An IonScript attaches Ion-generated information to a JSScript.
168 struct IonScript
169 {
170 private:
171 // Code pointer containing the actual method.
172 EncapsulatedPtr<JitCode> method_;
173
174 // Deoptimization table used by this method.
175 EncapsulatedPtr<JitCode> deoptTable_;
176
177 // Entrypoint for OSR, or nullptr.
178 jsbytecode *osrPc_;
179
180 // Offset to OSR entrypoint from method_->raw(), or 0.
181 uint32_t osrEntryOffset_;
182
183 // Offset to entrypoint skipping type arg check from method_->raw().
184 uint32_t skipArgCheckEntryOffset_;
185
186 // Offset of the invalidation epilogue (which pushes this IonScript
187 // and calls the invalidation thunk).
188 uint32_t invalidateEpilogueOffset_;
189
190 // The offset immediately after the IonScript immediate.
191 // NOTE: technically a constant delta from
192 // |invalidateEpilogueOffset_|, so we could hard-code this
193 // per-platform if we want.
194 uint32_t invalidateEpilogueDataOffset_;
195
196 // Number of times this script bailed out without invalidation.
197 uint32_t numBailouts_;
198
199 // Flag set when it is likely that one of our (transitive) call
200 // targets is not compiled. Used in ForkJoin.cpp to decide when
201 // we should add call targets to the worklist.
202 mozilla::Atomic<bool, mozilla::Relaxed> hasUncompiledCallTarget_;
203
204 // Flag set when this script is used as an entry script to parallel
205 // execution. If this is true, then the parent JSScript must be in its
206 // JitCompartment's parallel entry script set.
207 bool isParallelEntryScript_;
208
209 // Flag set if IonScript was compiled with SPS profiling enabled.
210 bool hasSPSInstrumentation_;
211
212 // Flag for if this script is getting recompiled.
213 uint32_t recompiling_;
214
215 // Any kind of data needed by the runtime, these can be either cache
216 // information or profiling info.
217 uint32_t runtimeData_;
218 uint32_t runtimeSize_;
219
220 // State for polymorphic caches in the compiled code. All caches are stored
221 // in the runtimeData buffer and indexed by the cacheIndex which give a
222 // relative offset in the runtimeData array.
223 uint32_t cacheIndex_;
224 uint32_t cacheEntries_;
225
226 // Map code displacement to safepoint / OSI-patch-delta.
227 uint32_t safepointIndexOffset_;
228 uint32_t safepointIndexEntries_;
229
230 // Offset to and length of the safepoint table in bytes.
231 uint32_t safepointsStart_;
232 uint32_t safepointsSize_;
233
234 // Number of bytes this function reserves on the stack.
235 uint32_t frameSlots_;
236
237 // Frame size is the value that can be added to the StackPointer along
238 // with the frame prefix to get a valid IonJSFrameLayout.
239 uint32_t frameSize_;
240
241 // Table mapping bailout IDs to snapshot offsets.
242 uint32_t bailoutTable_;
243 uint32_t bailoutEntries_;
244
245 // Map OSI-point displacement to snapshot.
246 uint32_t osiIndexOffset_;
247 uint32_t osiIndexEntries_;
248
249 // Offset from the start of the code buffer to its snapshot buffer.
250 uint32_t snapshots_;
251 uint32_t snapshotsListSize_;
252 uint32_t snapshotsRVATableSize_;
253
254 // List of instructions needed to recover stack frames.
255 uint32_t recovers_;
256 uint32_t recoversSize_;
257
258 // Constant table for constants stored in snapshots.
259 uint32_t constantTable_;
260 uint32_t constantEntries_;
261
262 // List of scripts that we call.
263 //
264 // Currently this is only non-nullptr for parallel IonScripts.
265 uint32_t callTargetList_;
266 uint32_t callTargetEntries_;
267
268 // List of patchable backedges which are threaded into the runtime's list.
269 uint32_t backedgeList_;
270 uint32_t backedgeEntries_;
271
272 // Number of references from invalidation records.
273 uint32_t refcount_;
274
275 // If this is a parallel script, the number of major GC collections it has
276 // been idle, otherwise 0.
277 //
278 // JSScripts with parallel IonScripts are preserved across GC if the
279 // parallel age is < MAX_PARALLEL_AGE.
280 uint32_t parallelAge_;
281
282 // Identifier of the compilation which produced this code.
283 types::RecompileInfo recompileInfo_;
284
285 // The optimization level this script was compiled in.
286 OptimizationLevel optimizationLevel_;
287
288 // Number of times we tried to enter this script via OSR but failed due to
289 // a LOOPENTRY pc other than osrPc_.
290 uint32_t osrPcMismatchCounter_;
291
292 // If non-null, the list of AsmJSModules
293 // that contain an optimized call directly into this IonScript.
294 Vector<DependentAsmJSModuleExit> *dependentAsmJSModules;
295
296 private:
297 inline uint8_t *bottomBuffer() {
298 return reinterpret_cast<uint8_t *>(this);
299 }
300 inline const uint8_t *bottomBuffer() const {
301 return reinterpret_cast<const uint8_t *>(this);
302 }
303
304 public:
305 SnapshotOffset *bailoutTable() {
306 return (SnapshotOffset *) &bottomBuffer()[bailoutTable_];
307 }
308 EncapsulatedValue *constants() {
309 return (EncapsulatedValue *) &bottomBuffer()[constantTable_];
310 }
311 const SafepointIndex *safepointIndices() const {
312 return const_cast<IonScript *>(this)->safepointIndices();
313 }
314 SafepointIndex *safepointIndices() {
315 return (SafepointIndex *) &bottomBuffer()[safepointIndexOffset_];
316 }
317 const OsiIndex *osiIndices() const {
318 return const_cast<IonScript *>(this)->osiIndices();
319 }
320 OsiIndex *osiIndices() {
321 return (OsiIndex *) &bottomBuffer()[osiIndexOffset_];
322 }
323 uint32_t *cacheIndex() {
324 return (uint32_t *) &bottomBuffer()[cacheIndex_];
325 }
326 uint8_t *runtimeData() {
327 return &bottomBuffer()[runtimeData_];
328 }
329 JSScript **callTargetList() {
330 return (JSScript **) &bottomBuffer()[callTargetList_];
331 }
332 PatchableBackedge *backedgeList() {
333 return (PatchableBackedge *) &bottomBuffer()[backedgeList_];
334 }
335 bool addDependentAsmJSModule(JSContext *cx, DependentAsmJSModuleExit exit);
336 void removeDependentAsmJSModule(DependentAsmJSModuleExit exit) {
337 if (!dependentAsmJSModules)
338 return;
339 for (size_t i = 0; i < dependentAsmJSModules->length(); i++) {
340 if (dependentAsmJSModules->begin()[i].module == exit.module &&
341 dependentAsmJSModules->begin()[i].exitIndex == exit.exitIndex)
342 {
343 dependentAsmJSModules->erase(dependentAsmJSModules->begin() + i);
344 break;
345 }
346 }
347 }
348
349 private:
350 void trace(JSTracer *trc);
351
352 public:
353 // Do not call directly, use IonScript::New. This is public for cx->new_.
354 IonScript();
355
356 static IonScript *New(JSContext *cx, types::RecompileInfo recompileInfo,
357 uint32_t frameLocals, uint32_t frameSize,
358 size_t snapshotsListSize, size_t snapshotsRVATableSize,
359 size_t recoversSize, size_t bailoutEntries,
360 size_t constants, size_t safepointIndexEntries,
361 size_t osiIndexEntries, size_t cacheEntries,
362 size_t runtimeSize, size_t safepointsSize,
363 size_t callTargetEntries, size_t backedgeEntries,
364 OptimizationLevel optimizationLevel);
365 static void Trace(JSTracer *trc, IonScript *script);
366 static void Destroy(FreeOp *fop, IonScript *script);
367
368 static inline size_t offsetOfMethod() {
369 return offsetof(IonScript, method_);
370 }
371 static inline size_t offsetOfOsrEntryOffset() {
372 return offsetof(IonScript, osrEntryOffset_);
373 }
374 static inline size_t offsetOfSkipArgCheckEntryOffset() {
375 return offsetof(IonScript, skipArgCheckEntryOffset_);
376 }
377 static inline size_t offsetOfRefcount() {
378 return offsetof(IonScript, refcount_);
379 }
380 static inline size_t offsetOfRecompiling() {
381 return offsetof(IonScript, recompiling_);
382 }
383
384 public:
385 JitCode *method() const {
386 return method_;
387 }
388 void setMethod(JitCode *code) {
389 JS_ASSERT(!invalidated());
390 method_ = code;
391 }
392 void setDeoptTable(JitCode *code) {
393 deoptTable_ = code;
394 }
395 void setOsrPc(jsbytecode *osrPc) {
396 osrPc_ = osrPc;
397 }
398 jsbytecode *osrPc() const {
399 return osrPc_;
400 }
401 void setOsrEntryOffset(uint32_t offset) {
402 JS_ASSERT(!osrEntryOffset_);
403 osrEntryOffset_ = offset;
404 }
405 uint32_t osrEntryOffset() const {
406 return osrEntryOffset_;
407 }
408 void setSkipArgCheckEntryOffset(uint32_t offset) {
409 JS_ASSERT(!skipArgCheckEntryOffset_);
410 skipArgCheckEntryOffset_ = offset;
411 }
412 uint32_t getSkipArgCheckEntryOffset() const {
413 return skipArgCheckEntryOffset_;
414 }
415 bool containsCodeAddress(uint8_t *addr) const {
416 return method()->raw() <= addr && addr <= method()->raw() + method()->instructionsSize();
417 }
418 bool containsReturnAddress(uint8_t *addr) const {
419 // This accounts for an off by one error caused by the return address of a
420 // bailout sitting outside the range of the containing function.
421 return method()->raw() <= addr && addr <= method()->raw() + method()->instructionsSize();
422 }
423 void setInvalidationEpilogueOffset(uint32_t offset) {
424 JS_ASSERT(!invalidateEpilogueOffset_);
425 invalidateEpilogueOffset_ = offset;
426 }
427 uint32_t invalidateEpilogueOffset() const {
428 JS_ASSERT(invalidateEpilogueOffset_);
429 return invalidateEpilogueOffset_;
430 }
431 void setInvalidationEpilogueDataOffset(uint32_t offset) {
432 JS_ASSERT(!invalidateEpilogueDataOffset_);
433 invalidateEpilogueDataOffset_ = offset;
434 }
435 uint32_t invalidateEpilogueDataOffset() const {
436 JS_ASSERT(invalidateEpilogueDataOffset_);
437 return invalidateEpilogueDataOffset_;
438 }
439 void incNumBailouts() {
440 numBailouts_++;
441 }
442 uint32_t numBailouts() const {
443 return numBailouts_;
444 }
445 bool bailoutExpected() const {
446 return numBailouts_ > 0;
447 }
448 void setHasUncompiledCallTarget() {
449 hasUncompiledCallTarget_ = true;
450 }
451 void clearHasUncompiledCallTarget() {
452 hasUncompiledCallTarget_ = false;
453 }
454 bool hasUncompiledCallTarget() const {
455 return hasUncompiledCallTarget_;
456 }
457 void setIsParallelEntryScript() {
458 isParallelEntryScript_ = true;
459 }
460 bool isParallelEntryScript() const {
461 return isParallelEntryScript_;
462 }
463 void setHasSPSInstrumentation() {
464 hasSPSInstrumentation_ = true;
465 }
466 void clearHasSPSInstrumentation() {
467 hasSPSInstrumentation_ = false;
468 }
469 bool hasSPSInstrumentation() const {
470 return hasSPSInstrumentation_;
471 }
472 const uint8_t *snapshots() const {
473 return reinterpret_cast<const uint8_t *>(this) + snapshots_;
474 }
475 size_t snapshotsListSize() const {
476 return snapshotsListSize_;
477 }
478 size_t snapshotsRVATableSize() const {
479 return snapshotsRVATableSize_;
480 }
481 const uint8_t *recovers() const {
482 return reinterpret_cast<const uint8_t *>(this) + recovers_;
483 }
484 size_t recoversSize() const {
485 return recoversSize_;
486 }
487 const uint8_t *safepoints() const {
488 return reinterpret_cast<const uint8_t *>(this) + safepointsStart_;
489 }
490 size_t safepointsSize() const {
491 return safepointsSize_;
492 }
493 size_t callTargetEntries() const {
494 return callTargetEntries_;
495 }
496 size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
497 return mallocSizeOf(this);
498 }
499 EncapsulatedValue &getConstant(size_t index) {
500 JS_ASSERT(index < numConstants());
501 return constants()[index];
502 }
503 size_t numConstants() const {
504 return constantEntries_;
505 }
506 uint32_t frameSlots() const {
507 return frameSlots_;
508 }
509 uint32_t frameSize() const {
510 return frameSize_;
511 }
512 SnapshotOffset bailoutToSnapshot(uint32_t bailoutId) {
513 JS_ASSERT(bailoutId < bailoutEntries_);
514 return bailoutTable()[bailoutId];
515 }
516 const SafepointIndex *getSafepointIndex(uint32_t disp) const;
517 const SafepointIndex *getSafepointIndex(uint8_t *retAddr) const {
518 JS_ASSERT(containsCodeAddress(retAddr));
519 return getSafepointIndex(retAddr - method()->raw());
520 }
521 const OsiIndex *getOsiIndex(uint32_t disp) const;
522 const OsiIndex *getOsiIndex(uint8_t *retAddr) const;
523 inline IonCache &getCacheFromIndex(uint32_t index) {
524 JS_ASSERT(index < cacheEntries_);
525 uint32_t offset = cacheIndex()[index];
526 return getCache(offset);
527 }
528 inline IonCache &getCache(uint32_t offset) {
529 JS_ASSERT(offset < runtimeSize_);
530 return *(IonCache *) &runtimeData()[offset];
531 }
532 size_t numCaches() const {
533 return cacheEntries_;
534 }
535 size_t runtimeSize() const {
536 return runtimeSize_;
537 }
538 CacheLocation *getCacheLocs(uint32_t locIndex) {
539 JS_ASSERT(locIndex < runtimeSize_);
540 return (CacheLocation *) &runtimeData()[locIndex];
541 }
542 void toggleBarriers(bool enabled);
543 void purgeCaches();
544 void destroyCaches();
545 void unlinkFromRuntime(FreeOp *fop);
546 void copySnapshots(const SnapshotWriter *writer);
547 void copyRecovers(const RecoverWriter *writer);
548 void copyBailoutTable(const SnapshotOffset *table);
549 void copyConstants(const Value *vp);
550 void copySafepointIndices(const SafepointIndex *firstSafepointIndex, MacroAssembler &masm);
551 void copyOsiIndices(const OsiIndex *firstOsiIndex, MacroAssembler &masm);
552 void copyRuntimeData(const uint8_t *data);
553 void copyCacheEntries(const uint32_t *caches, MacroAssembler &masm);
554 void copySafepoints(const SafepointWriter *writer);
555 void copyCallTargetEntries(JSScript **callTargets);
556 void copyPatchableBackedges(JSContext *cx, JitCode *code,
557 PatchableBackedgeInfo *backedges);
558
559 bool invalidated() const {
560 return refcount_ != 0;
561 }
562 size_t refcount() const {
563 return refcount_;
564 }
565 void incref() {
566 refcount_++;
567 }
568 void decref(FreeOp *fop) {
569 JS_ASSERT(refcount_);
570 refcount_--;
571 if (!refcount_)
572 Destroy(fop, this);
573 }
574 const types::RecompileInfo& recompileInfo() const {
575 return recompileInfo_;
576 }
577 types::RecompileInfo& recompileInfoRef() {
578 return recompileInfo_;
579 }
580 OptimizationLevel optimizationLevel() const {
581 return optimizationLevel_;
582 }
583 uint32_t incrOsrPcMismatchCounter() {
584 return ++osrPcMismatchCounter_;
585 }
586 void resetOsrPcMismatchCounter() {
587 osrPcMismatchCounter_ = 0;
588 }
589
590 void setRecompiling() {
591 recompiling_ = true;
592 }
593
594 bool isRecompiling() const {
595 return recompiling_;
596 }
597
598 void clearRecompiling() {
599 recompiling_ = false;
600 }
601
602 static const uint32_t MAX_PARALLEL_AGE = 5;
603
604 void resetParallelAge() {
605 MOZ_ASSERT(isParallelEntryScript());
606 parallelAge_ = 0;
607 }
608 uint32_t parallelAge() const {
609 return parallelAge_;
610 }
611 uint32_t increaseParallelAge() {
612 MOZ_ASSERT(isParallelEntryScript());
613 return ++parallelAge_;
614 }
615
616 static void writeBarrierPre(Zone *zone, IonScript *ionScript);
617 };
618
619 // Execution information for a basic block which may persist after the
620 // accompanying IonScript is destroyed, for use during profiling.
621 struct IonBlockCounts
622 {
623 private:
624 uint32_t id_;
625
626 // Approximate bytecode in the outer (not inlined) script this block
627 // was generated from.
628 uint32_t offset_;
629
630 // ids for successors of this block.
631 uint32_t numSuccessors_;
632 uint32_t *successors_;
633
634 // Hit count for this block.
635 uint64_t hitCount_;
636
637 // Text information about the code generated for this block.
638 char *code_;
639
640 public:
641
642 bool init(uint32_t id, uint32_t offset, uint32_t numSuccessors) {
643 id_ = id;
644 offset_ = offset;
645 numSuccessors_ = numSuccessors;
646 if (numSuccessors) {
647 successors_ = js_pod_calloc<uint32_t>(numSuccessors);
648 if (!successors_)
649 return false;
650 }
651 return true;
652 }
653
654 void destroy() {
655 js_free(successors_);
656 js_free(code_);
657 }
658
659 uint32_t id() const {
660 return id_;
661 }
662
663 uint32_t offset() const {
664 return offset_;
665 }
666
667 size_t numSuccessors() const {
668 return numSuccessors_;
669 }
670
671 void setSuccessor(size_t i, uint32_t id) {
672 JS_ASSERT(i < numSuccessors_);
673 successors_[i] = id;
674 }
675
676 uint32_t successor(size_t i) const {
677 JS_ASSERT(i < numSuccessors_);
678 return successors_[i];
679 }
680
681 uint64_t *addressOfHitCount() {
682 return &hitCount_;
683 }
684
685 uint64_t hitCount() const {
686 return hitCount_;
687 }
688
689 void setCode(const char *code) {
690 char *ncode = (char *) js_malloc(strlen(code) + 1);
691 if (ncode) {
692 strcpy(ncode, code);
693 code_ = ncode;
694 }
695 }
696
697 const char *code() const {
698 return code_;
699 }
700 };
701
702 // Execution information for a compiled script which may persist after the
703 // IonScript is destroyed, for use during profiling.
704 struct IonScriptCounts
705 {
706 private:
707 // Any previous invalidated compilation(s) for the script.
708 IonScriptCounts *previous_;
709
710 // Information about basic blocks in this script.
711 size_t numBlocks_;
712 IonBlockCounts *blocks_;
713
714 public:
715
716 IonScriptCounts() {
717 mozilla::PodZero(this);
718 }
719
720 ~IonScriptCounts() {
721 for (size_t i = 0; i < numBlocks_; i++)
722 blocks_[i].destroy();
723 js_free(blocks_);
724 js_delete(previous_);
725 }
726
727 bool init(size_t numBlocks) {
728 numBlocks_ = numBlocks;
729 blocks_ = js_pod_calloc<IonBlockCounts>(numBlocks);
730 return blocks_ != nullptr;
731 }
732
733 size_t numBlocks() const {
734 return numBlocks_;
735 }
736
737 IonBlockCounts &block(size_t i) {
738 JS_ASSERT(i < numBlocks_);
739 return blocks_[i];
740 }
741
742 void setPrevious(IonScriptCounts *previous) {
743 previous_ = previous;
744 }
745
746 IonScriptCounts *previous() const {
747 return previous_;
748 }
749 };
750
751 struct VMFunction;
752
753 class JitCompartment;
754 class JitRuntime;
755
756 struct AutoFlushICache
757 {
758 private:
759 uintptr_t start_;
760 uintptr_t stop_;
761 const char *name_;
762 bool inhibit_;
763 AutoFlushICache *prev_;
764
765 public:
766 static void setRange(uintptr_t p, size_t len);
767 static void flush(uintptr_t p, size_t len);
768 static void setInhibit();
769 ~AutoFlushICache();
770 AutoFlushICache(const char *nonce, bool inhibit=false);
771 };
772
773 } // namespace jit
774
775 namespace gc {
776
777 inline bool
778 IsMarked(const jit::VMFunction *)
779 {
780 // VMFunction are only static objects which are used by WeakMaps as keys.
781 // It is considered as a root object which is always marked.
782 return true;
783 }
784
785 } // namespace gc
786
787 } // namespace js
788
789 #endif /* jit_IonCode_h */

mercurial