Line data Source code
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_BaselineJIT_h
8 : #define jit_BaselineJIT_h
9 :
10 : #include "mozilla/MemoryReporting.h"
11 :
12 : #include "jscntxt.h"
13 : #include "jscompartment.h"
14 :
15 : #include "ds/LifoAlloc.h"
16 : #include "jit/Bailouts.h"
17 : #include "jit/IonCode.h"
18 : #include "jit/MacroAssembler.h"
19 : #include "vm/TraceLogging.h"
20 :
21 : namespace js {
22 : namespace jit {
23 :
24 : class StackValue;
25 : class BaselineICEntry;
26 : class ICStub;
27 : class ControlFlowGraph;
28 :
29 : class PCMappingSlotInfo
30 : {
31 : uint8_t slotInfo_;
32 :
33 : public:
34 : // SlotInfo encoding:
35 : // Bits 0 & 1: number of slots at top of stack which are unsynced.
36 : // Bits 2 & 3: SlotLocation of top slot value (only relevant if numUnsynced > 0).
37 : // Bits 3 & 4: SlotLocation of next slot value (only relevant if numUnsynced > 1).
38 : enum SlotLocation { SlotInR0 = 0, SlotInR1 = 1, SlotIgnore = 3 };
39 :
40 61179 : PCMappingSlotInfo()
41 61179 : : slotInfo_(0)
42 61179 : { }
43 :
44 61179 : explicit PCMappingSlotInfo(uint8_t slotInfo)
45 61179 : : slotInfo_(slotInfo)
46 61179 : { }
47 :
48 51873 : static inline bool ValidSlotLocation(SlotLocation loc) {
49 51873 : return (loc == SlotInR0) || (loc == SlotInR1) || (loc == SlotIgnore);
50 : }
51 :
52 : static SlotLocation ToSlotLocation(const StackValue* stackVal);
53 :
54 22871 : inline static PCMappingSlotInfo MakeSlotInfo() { return PCMappingSlotInfo(0); }
55 :
56 24743 : inline static PCMappingSlotInfo MakeSlotInfo(SlotLocation topSlotLoc) {
57 24743 : MOZ_ASSERT(ValidSlotLocation(topSlotLoc));
58 24743 : return PCMappingSlotInfo(1 | (topSlotLoc << 2));
59 : }
60 :
61 13565 : inline static PCMappingSlotInfo MakeSlotInfo(SlotLocation topSlotLoc, SlotLocation nextSlotLoc) {
62 13565 : MOZ_ASSERT(ValidSlotLocation(topSlotLoc));
63 13565 : MOZ_ASSERT(ValidSlotLocation(nextSlotLoc));
64 13565 : return PCMappingSlotInfo(2 | (topSlotLoc << 2) | (nextSlotLoc) << 4);
65 : }
66 :
67 0 : inline unsigned numUnsynced() const {
68 0 : return slotInfo_ & 0x3;
69 : }
70 0 : inline SlotLocation topSlotLocation() const {
71 0 : return static_cast<SlotLocation>((slotInfo_ >> 2) & 0x3);
72 : }
73 0 : inline SlotLocation nextSlotLocation() const {
74 0 : return static_cast<SlotLocation>((slotInfo_ >> 4) & 0x3);
75 : }
76 122356 : inline uint8_t toByte() const {
77 122356 : return slotInfo_;
78 : }
79 : };
80 :
81 : // A CompactBuffer is used to store native code offsets (relative to the
82 : // previous pc) and PCMappingSlotInfo bytes. To allow binary search into this
83 : // table, we maintain a second table of "index" entries. Every X ops, the
84 : // compiler will add an index entry, so that from the index entry to the
85 : // actual native code offset, we have to iterate at most X times.
86 : struct PCMappingIndexEntry
87 : {
88 : // jsbytecode offset.
89 : uint32_t pcOffset;
90 :
91 : // Native code offset.
92 : uint32_t nativeOffset;
93 :
94 : // Offset in the CompactBuffer where data for pcOffset starts.
95 : uint32_t bufferOffset;
96 : };
97 :
98 : // Describes a single wasm::ImportExit which jumps (via an import with
99 : // the given index) directly to a BaselineScript or IonScript.
100 : struct DependentWasmImport
101 : {
102 : wasm::Instance* instance;
103 : size_t importIndex;
104 :
105 0 : DependentWasmImport(wasm::Instance& instance, size_t importIndex)
106 0 : : instance(&instance),
107 0 : importIndex(importIndex)
108 0 : { }
109 : };
110 :
111 : struct BaselineScript
112 : {
113 : public:
114 : // Largest script that the baseline compiler will attempt to compile.
115 : #if defined(JS_CODEGEN_ARM)
116 : // ARM branches can only reach 32MB, and the macroassembler doesn't mitigate
117 : // that limitation. Use a stricter limit on the acceptable script size to
118 : // avoid crashing when branches go out of range.
119 : static const uint32_t MAX_JSSCRIPT_LENGTH = 1000000u;
120 : #else
121 : static const uint32_t MAX_JSSCRIPT_LENGTH = 0x0fffffffu;
122 : #endif
123 :
124 : // Limit the locals on a given script so that stack check on baseline frames
125 : // doesn't overflow a uint32_t value.
126 : // (MAX_JSSCRIPT_SLOTS * sizeof(Value)) must fit within a uint32_t.
127 : static const uint32_t MAX_JSSCRIPT_SLOTS = 0xffffu;
128 :
129 : private:
130 : // Code pointer containing the actual method.
131 : HeapPtr<JitCode*> method_;
132 :
133 : // For functions with a call object, template objects to use for the call
134 : // object and decl env object (linked via the call object's enclosing
135 : // scope).
136 : HeapPtr<EnvironmentObject*> templateEnv_;
137 :
138 : // Allocated space for fallback stubs.
139 : FallbackICStubSpace fallbackStubSpace_;
140 :
141 : // If non-null, the list of wasm::Modules that contain an optimized call
142 : // directly to this script.
143 : Vector<DependentWasmImport>* dependentWasmImports_;
144 :
145 : // Native code offset right before the scope chain is initialized.
146 : uint32_t prologueOffset_;
147 :
148 : // Native code offset right before the frame is popped and the method
149 : // returned from.
150 : uint32_t epilogueOffset_;
151 :
152 : // The offsets for the toggledJump instructions for profiler instrumentation.
153 : uint32_t profilerEnterToggleOffset_;
154 : uint32_t profilerExitToggleOffset_;
155 :
156 : // The offsets and event used for Tracelogger toggling.
157 : #ifdef JS_TRACE_LOGGING
158 : # ifdef DEBUG
159 : bool traceLoggerScriptsEnabled_;
160 : bool traceLoggerEngineEnabled_;
161 : # endif
162 : TraceLoggerEvent traceLoggerScriptEvent_;
163 : #endif
164 :
165 : // Native code offsets right after the debug prologue VM call returns, or
166 : // would have returned. This offset is recorded even when debug mode is
167 : // off to aid on-stack debug mode recompilation.
168 : //
169 : // We don't need one for the debug epilogue because that always happens
170 : // right before the epilogue, so we just use the epilogue offset.
171 : uint32_t postDebugPrologueOffset_;
172 :
173 : public:
174 : enum Flag {
175 : // Flag set by JSScript::argumentsOptimizationFailed. Similar to
176 : // JSScript::needsArgsObj_, but can be read from JIT code.
177 : NEEDS_ARGS_OBJ = 1 << 0,
178 :
179 : // Flag set when discarding JIT code, to indicate this script is
180 : // on the stack and should not be discarded.
181 : ACTIVE = 1 << 1,
182 :
183 : // Flag set when the script contains any writes to its on-stack
184 : // (rather than call object stored) arguments.
185 : MODIFIES_ARGUMENTS = 1 << 2,
186 :
187 : // Flag set when compiled for use with Debugger. Handles various
188 : // Debugger hooks and compiles toggled calls for traps.
189 : HAS_DEBUG_INSTRUMENTATION = 1 << 3,
190 :
191 : // Flag set if this script has ever been Ion compiled, either directly
192 : // or inlined into another script. This is cleared when the script's
193 : // type information or caches are cleared.
194 : ION_COMPILED_OR_INLINED = 1 << 4,
195 :
196 : // Flag is set if this script has profiling instrumentation turned on.
197 : PROFILER_INSTRUMENTATION_ON = 1 << 5
198 : };
199 :
200 : private:
201 : uint32_t flags_;
202 :
203 : private:
204 : void trace(JSTracer* trc);
205 :
206 : uint32_t icEntriesOffset_;
207 : uint32_t icEntries_;
208 :
209 : uint32_t pcMappingIndexOffset_;
210 : uint32_t pcMappingIndexEntries_;
211 :
212 : uint32_t pcMappingOffset_;
213 : uint32_t pcMappingSize_;
214 :
215 : // List mapping indexes of bytecode type sets to the offset of the opcode
216 : // they correspond to, for use by TypeScript::BytecodeTypes.
217 : uint32_t bytecodeTypeMapOffset_;
218 :
219 : // For generator scripts, we store the native code address for each yield
220 : // instruction.
221 : uint32_t yieldEntriesOffset_;
222 :
223 : // By default tracelogger is disabled. Therefore we disable the logging code
224 : // by default. We store the offsets we must patch to enable the logging.
225 : uint32_t traceLoggerToggleOffsetsOffset_;
226 : uint32_t numTraceLoggerToggleOffsets_;
227 :
228 : // The total bytecode length of all scripts we inlined when we Ion-compiled
229 : // this script. 0 if Ion did not compile this script or if we didn't inline
230 : // anything.
231 : uint16_t inlinedBytecodeLength_;
232 :
233 : // The max inlining depth where we can still inline all functions we inlined
234 : // when we Ion-compiled this script. This starts as UINT8_MAX, since we have
235 : // no data yet, and won't affect inlining heuristics in that case. The value
236 : // is updated when we Ion-compile this script. See makeInliningDecision for
237 : // more info.
238 : uint8_t maxInliningDepth_;
239 :
240 : // An ion compilation that is ready, but isn't linked yet.
241 : IonBuilder *pendingBuilder_;
242 :
243 : ControlFlowGraph* controlFlowGraph_;
244 :
245 : public:
246 : // Do not call directly, use BaselineScript::New. This is public for cx->new_.
247 : BaselineScript(uint32_t prologueOffset, uint32_t epilogueOffset,
248 : uint32_t profilerEnterToggleOffset,
249 : uint32_t profilerExitToggleOffset,
250 : uint32_t postDebugPrologueOffset);
251 :
252 1092 : ~BaselineScript() {
253 : // The contents of the fallback stub space are removed and freed
254 : // separately after the next minor GC. See BaselineScript::Destroy.
255 546 : MOZ_ASSERT(fallbackStubSpace_.isEmpty());
256 546 : }
257 :
258 : static BaselineScript* New(JSScript* jsscript,
259 : uint32_t prologueOffset, uint32_t epilogueOffset,
260 : uint32_t profilerEnterToggleOffset,
261 : uint32_t profilerExitToggleOffset,
262 : uint32_t postDebugPrologueOffset,
263 : size_t icEntries,
264 : size_t pcMappingIndexEntries, size_t pcMappingSize,
265 : size_t bytecodeTypeMapEntries,
266 : size_t yieldEntries,
267 : size_t traceLoggerToggleOffsetEntries);
268 :
269 : static void Trace(JSTracer* trc, BaselineScript* script);
270 : static void Destroy(FreeOp* fop, BaselineScript* script);
271 :
272 : void purgeOptimizedStubs(Zone* zone);
273 :
274 : static inline size_t offsetOfMethod() {
275 : return offsetof(BaselineScript, method_);
276 : }
277 :
278 0 : void addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf, size_t* data,
279 : size_t* fallbackStubs) const {
280 0 : *data += mallocSizeOf(this);
281 :
282 : // |data| already includes the ICStubSpace itself, so use
283 : // sizeOfExcludingThis.
284 0 : *fallbackStubs += fallbackStubSpace_.sizeOfExcludingThis(mallocSizeOf);
285 0 : }
286 :
287 1092 : bool active() const {
288 1092 : return flags_ & ACTIVE;
289 : }
290 0 : void setActive() {
291 0 : flags_ |= ACTIVE;
292 0 : }
293 0 : void resetActive() {
294 0 : flags_ &= ~ACTIVE;
295 0 : }
296 :
297 0 : void setNeedsArgsObj() {
298 0 : flags_ |= NEEDS_ARGS_OBJ;
299 0 : }
300 :
301 69 : void setModifiesArguments() {
302 69 : flags_ |= MODIFIES_ARGUMENTS;
303 69 : }
304 8 : bool modifiesArguments() {
305 8 : return flags_ & MODIFIES_ARGUMENTS;
306 : }
307 :
308 0 : void setHasDebugInstrumentation() {
309 0 : flags_ |= HAS_DEBUG_INSTRUMENTATION;
310 0 : }
311 0 : bool hasDebugInstrumentation() const {
312 0 : return flags_ & HAS_DEBUG_INSTRUMENTATION;
313 : }
314 :
315 43 : void setIonCompiledOrInlined() {
316 43 : flags_ |= ION_COMPILED_OR_INLINED;
317 43 : }
318 0 : void clearIonCompiledOrInlined() {
319 0 : flags_ &= ~ION_COMPILED_OR_INLINED;
320 0 : }
321 11 : bool ionCompiledOrInlined() const {
322 11 : return flags_ & ION_COMPILED_OR_INLINED;
323 : }
324 :
325 : uint32_t prologueOffset() const {
326 : return prologueOffset_;
327 : }
328 0 : uint8_t* prologueEntryAddr() const {
329 0 : return method_->raw() + prologueOffset_;
330 : }
331 :
332 : uint32_t epilogueOffset() const {
333 : return epilogueOffset_;
334 : }
335 0 : uint8_t* epilogueEntryAddr() const {
336 0 : return method_->raw() + epilogueOffset_;
337 : }
338 :
339 : uint32_t postDebugPrologueOffset() const {
340 : return postDebugPrologueOffset_;
341 : }
342 0 : uint8_t* postDebugPrologueAddr() const {
343 0 : return method_->raw() + postDebugPrologueOffset_;
344 : }
345 :
346 1038900 : BaselineICEntry* icEntryList() {
347 1038900 : return (BaselineICEntry*)(reinterpret_cast<uint8_t*>(this) + icEntriesOffset_);
348 : }
349 627 : uint8_t** yieldEntryList() {
350 627 : return (uint8_t**)(reinterpret_cast<uint8_t*>(this) + yieldEntriesOffset_);
351 : }
352 7874 : PCMappingIndexEntry* pcMappingIndexEntryList() {
353 7874 : return (PCMappingIndexEntry*)(reinterpret_cast<uint8_t*>(this) + pcMappingIndexOffset_);
354 : }
355 4897 : uint8_t* pcMappingData() {
356 4897 : return reinterpret_cast<uint8_t*>(this) + pcMappingOffset_;
357 : }
358 2138 : FallbackICStubSpace* fallbackStubSpace() {
359 2138 : return &fallbackStubSpace_;
360 : }
361 :
362 9379 : JitCode* method() const {
363 9379 : return method_;
364 : }
365 627 : void setMethod(JitCode* code) {
366 627 : MOZ_ASSERT(!method_);
367 627 : method_ = code;
368 627 : }
369 :
370 4 : EnvironmentObject* templateEnvironment() const {
371 4 : return templateEnv_;
372 : }
373 627 : void setTemplateEnvironment(EnvironmentObject* templateEnv) {
374 627 : MOZ_ASSERT(!templateEnv_);
375 627 : templateEnv_ = templateEnv;
376 627 : }
377 :
378 0 : bool containsCodeAddress(uint8_t* addr) const {
379 0 : return method()->raw() <= addr && addr <= method()->raw() + method()->instructionsSize();
380 : }
381 :
382 : BaselineICEntry& icEntry(size_t index);
383 : BaselineICEntry& icEntryFromReturnOffset(CodeOffset returnOffset);
384 : BaselineICEntry& icEntryFromPCOffset(uint32_t pcOffset);
385 : BaselineICEntry& icEntryFromPCOffset(uint32_t pcOffset, BaselineICEntry* prevLookedUpEntry);
386 : BaselineICEntry& callVMEntryFromPCOffset(uint32_t pcOffset);
387 : BaselineICEntry& stackCheckICEntry(bool earlyCheck);
388 : BaselineICEntry& warmupCountICEntry();
389 : BaselineICEntry& icEntryFromReturnAddress(uint8_t* returnAddr);
390 : uint8_t* returnAddressForIC(const BaselineICEntry& ent);
391 :
392 1324532 : size_t numICEntries() const {
393 1324532 : return icEntries_;
394 : }
395 :
396 : void copyICEntries(JSScript* script, const BaselineICEntry* entries, MacroAssembler& masm);
397 : void adoptFallbackStubs(FallbackICStubSpace* stubSpace);
398 :
399 : void copyYieldAndAwaitEntries(JSScript* script, Vector<uint32_t>& yieldAndAwaitOffsets);
400 :
401 : PCMappingIndexEntry& pcMappingIndexEntry(size_t index);
402 : CompactBufferReader pcMappingReader(size_t indexEntry);
403 :
404 16121 : size_t numPCMappingIndexEntries() const {
405 16121 : return pcMappingIndexEntries_;
406 : }
407 :
408 : void copyPCMappingIndexEntries(const PCMappingIndexEntry* entries);
409 : void copyPCMappingEntries(const CompactBufferWriter& entries);
410 :
411 : uint8_t* nativeCodeForPC(JSScript* script, jsbytecode* pc,
412 : PCMappingSlotInfo* slotInfo = nullptr);
413 :
414 : // Return the bytecode offset for a given native code address. Be careful
415 : // when using this method: we don't emit code for some bytecode ops, so
416 : // the result may not be accurate.
417 : jsbytecode* approximatePcForNativeAddress(JSScript* script, uint8_t* nativeAddress);
418 :
419 : MOZ_MUST_USE bool addDependentWasmImport(JSContext* cx, wasm::Instance& instance, uint32_t idx);
420 : void removeDependentWasmImport(wasm::Instance& instance, uint32_t idx);
421 : void unlinkDependentWasmImports(FreeOp* fop);
422 : void clearDependentWasmImports();
423 :
424 : // Toggle debug traps (used for breakpoints and step mode) in the script.
425 : // If |pc| is nullptr, toggle traps for all ops in the script. Else, only
426 : // toggle traps at |pc|.
427 : void toggleDebugTraps(JSScript* script, jsbytecode* pc);
428 :
429 : void toggleProfilerInstrumentation(bool enable);
430 0 : bool isProfilerInstrumentationOn() const {
431 0 : return flags_ & PROFILER_INSTRUMENTATION_ON;
432 : }
433 :
434 : #ifdef JS_TRACE_LOGGING
435 : void initTraceLogger(JSRuntime* runtime, JSScript* script, const Vector<CodeOffset>& offsets);
436 : void toggleTraceLoggerScripts(JSRuntime* runtime, JSScript* script, bool enable);
437 : void toggleTraceLoggerEngine(bool enable);
438 :
439 632 : static size_t offsetOfTraceLoggerScriptEvent() {
440 632 : return offsetof(BaselineScript, traceLoggerScriptEvent_);
441 : }
442 :
443 1258 : uint32_t* traceLoggerToggleOffsets() {
444 1258 : MOZ_ASSERT(traceLoggerToggleOffsetsOffset_);
445 : return reinterpret_cast<uint32_t*>(reinterpret_cast<uint8_t*>(this) +
446 1258 : traceLoggerToggleOffsetsOffset_);
447 : }
448 : #endif
449 :
450 : void noteAccessedGetter(uint32_t pcOffset);
451 : void noteHasDenseAdd(uint32_t pcOffset);
452 :
453 41 : static size_t offsetOfFlags() {
454 41 : return offsetof(BaselineScript, flags_);
455 : }
456 4 : static size_t offsetOfYieldEntriesOffset() {
457 4 : return offsetof(BaselineScript, yieldEntriesOffset_);
458 : }
459 :
460 : static void writeBarrierPre(Zone* zone, BaselineScript* script);
461 :
462 43135 : uint32_t* bytecodeTypeMap() {
463 43135 : MOZ_ASSERT(bytecodeTypeMapOffset_);
464 43135 : return reinterpret_cast<uint32_t*>(reinterpret_cast<uint8_t*>(this) + bytecodeTypeMapOffset_);
465 : }
466 :
467 33 : uint8_t maxInliningDepth() const {
468 33 : return maxInliningDepth_;
469 : }
470 11 : void setMaxInliningDepth(uint32_t depth) {
471 11 : MOZ_ASSERT(depth <= UINT8_MAX);
472 11 : maxInliningDepth_ = depth;
473 11 : }
474 11 : void resetMaxInliningDepth() {
475 11 : maxInliningDepth_ = UINT8_MAX;
476 11 : }
477 :
478 43 : uint16_t inlinedBytecodeLength() const {
479 43 : return inlinedBytecodeLength_;
480 : }
481 4 : void setInlinedBytecodeLength(uint32_t len) {
482 4 : if (len > UINT16_MAX)
483 0 : len = UINT16_MAX;
484 4 : inlinedBytecodeLength_ = len;
485 4 : }
486 :
487 1345 : bool hasPendingIonBuilder() const {
488 1345 : return !!pendingBuilder_;
489 : }
490 :
491 12 : js::jit::IonBuilder* pendingIonBuilder() {
492 12 : MOZ_ASSERT(hasPendingIonBuilder());
493 12 : return pendingBuilder_;
494 : }
495 16 : void setPendingIonBuilder(JSRuntime* maybeRuntime, JSScript* script, js::jit::IonBuilder* builder) {
496 16 : MOZ_ASSERT(script->baselineScript() == this);
497 16 : MOZ_ASSERT(!builder || !hasPendingIonBuilder());
498 :
499 16 : if (script->isIonCompilingOffThread())
500 8 : script->setIonScript(maybeRuntime, ION_PENDING_SCRIPT);
501 :
502 16 : pendingBuilder_ = builder;
503 :
504 : // lazy linking cannot happen during asmjs to ion.
505 16 : clearDependentWasmImports();
506 :
507 16 : script->updateBaselineOrIonRaw(maybeRuntime);
508 16 : }
509 8 : void removePendingIonBuilder(JSScript* script) {
510 8 : setPendingIonBuilder(nullptr, script, nullptr);
511 8 : if (script->maybeIonScript() == ION_PENDING_SCRIPT)
512 8 : script->setIonScript(nullptr, nullptr);
513 8 : }
514 :
515 132 : const ControlFlowGraph* controlFlowGraph() const {
516 132 : return controlFlowGraph_;
517 : }
518 :
519 15 : void setControlFlowGraph(ControlFlowGraph* controlFlowGraph) {
520 15 : controlFlowGraph_ = controlFlowGraph;
521 15 : }
522 :
523 : };
524 : static_assert(sizeof(BaselineScript) % sizeof(uintptr_t) == 0,
525 : "The data attached to the script must be aligned for fast JIT access.");
526 :
527 : inline bool
528 71383 : IsBaselineEnabled(JSContext* cx)
529 : {
530 : #ifdef JS_CODEGEN_NONE
531 : return false;
532 : #else
533 71383 : return cx->options().baseline();
534 : #endif
535 : }
536 :
537 : MethodStatus
538 : CanEnterBaselineMethod(JSContext* cx, RunState& state);
539 :
540 : MethodStatus
541 : CanEnterBaselineAtBranch(JSContext* cx, InterpreterFrame* fp, bool newType);
542 :
543 : JitExecStatus
544 : EnterBaselineMethod(JSContext* cx, RunState& state);
545 :
546 : JitExecStatus
547 : EnterBaselineAtBranch(JSContext* cx, InterpreterFrame* fp, jsbytecode* pc);
548 :
549 : void
550 : FinishDiscardBaselineScript(FreeOp* fop, JSScript* script);
551 :
552 : void
553 : AddSizeOfBaselineData(JSScript* script, mozilla::MallocSizeOf mallocSizeOf, size_t* data,
554 : size_t* fallbackStubs);
555 :
556 : void
557 : ToggleBaselineProfiling(JSRuntime* runtime, bool enable);
558 :
559 : void
560 : ToggleBaselineTraceLoggerScripts(JSRuntime* runtime, bool enable);
561 : void
562 : ToggleBaselineTraceLoggerEngine(JSRuntime* runtime, bool enable);
563 :
564 : struct BaselineBailoutInfo
565 : {
566 : // Pointer into the current C stack, where overwriting will start.
567 : uint8_t* incomingStack;
568 :
569 : // The top and bottom heapspace addresses of the reconstructed stack
570 : // which will be copied to the bottom.
571 : uint8_t* copyStackTop;
572 : uint8_t* copyStackBottom;
573 :
574 : // Fields to store the top-of-stack baseline values that are held
575 : // in registers. The setR0 and setR1 fields are flags indicating
576 : // whether each one is initialized.
577 : uint32_t setR0;
578 : Value valueR0;
579 : uint32_t setR1;
580 : Value valueR1;
581 :
582 : // The value of the frame pointer register on resume.
583 : void* resumeFramePtr;
584 :
585 : // The native code address to resume into.
586 : void* resumeAddr;
587 :
588 : // The bytecode pc where we will resume.
589 : jsbytecode* resumePC;
590 :
591 : // The bytecode pc of try block and fault block.
592 : jsbytecode* tryPC;
593 : jsbytecode* faultPC;
594 :
595 : // If resuming into a TypeMonitor IC chain, this field holds the
596 : // address of the first stub in that chain. If this field is
597 : // set, then the actual jitcode resumed into is the jitcode for
598 : // the first stub, not the resumeAddr above. The resumeAddr
599 : // above, in this case, is pushed onto the stack so that the
600 : // TypeMonitor chain can tail-return into the main jitcode when done.
601 : ICStub* monitorStub;
602 :
603 : // Number of baseline frames to push on the stack.
604 : uint32_t numFrames;
605 :
606 : // If Ion bailed out on a global script before it could perform the global
607 : // declaration conflicts check. In such cases the baseline script is
608 : // resumed at the first pc instead of the prologue, so an extra flag is
609 : // needed to perform the check.
610 : bool checkGlobalDeclarationConflicts;
611 :
612 : // The bailout kind.
613 : BailoutKind bailoutKind;
614 : };
615 :
616 : uint32_t
617 : BailoutIonToBaseline(JSContext* cx, JitActivation* activation, JitFrameIterator& iter,
618 : bool invalidate, BaselineBailoutInfo** bailoutInfo,
619 : const ExceptionBailoutInfo* exceptionInfo);
620 :
621 : // Mark baseline scripts on the stack as active, so that they are not discarded
622 : // during GC.
623 : void
624 : MarkActiveBaselineScripts(Zone* zone);
625 :
626 : MethodStatus
627 : BaselineCompile(JSContext* cx, JSScript* script, bool forceDebugInstrumentation = false);
628 :
629 : } // namespace jit
630 : } // namespace js
631 :
632 : namespace JS {
633 :
634 : template <>
635 : struct DeletePolicy<js::jit::BaselineScript>
636 : {
637 627 : explicit DeletePolicy(JSRuntime* rt) : rt_(rt) {}
638 : void operator()(const js::jit::BaselineScript* script);
639 :
640 : private:
641 : JSRuntime* rt_;
642 : };
643 :
644 : } // namespace JS
645 :
646 : #endif /* jit_BaselineJIT_h */
|