|
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_BaselineIC_h |
|
8 #define jit_BaselineIC_h |
|
9 |
|
10 #ifdef JS_ION |
|
11 |
|
12 #include "mozilla/Assertions.h" |
|
13 |
|
14 #include "jscntxt.h" |
|
15 #include "jscompartment.h" |
|
16 #include "jsgc.h" |
|
17 #include "jsopcode.h" |
|
18 |
|
19 #include "jit/BaselineJIT.h" |
|
20 #include "jit/BaselineRegisters.h" |
|
21 |
|
22 namespace js { |
|
23 namespace jit { |
|
24 |
|
25 // |
|
26 // Baseline Inline Caches are polymorphic caches that aggressively |
|
27 // share their stub code. |
|
28 // |
|
29 // Every polymorphic site contains a linked list of stubs which are |
|
30 // specific to that site. These stubs are composed of a |StubData| |
|
31 // structure that stores parametrization information (e.g. |
|
32 // the shape pointer for a shape-check-and-property-get stub), any |
|
33 // dynamic information (e.g. use counts), a pointer to the stub code, |
|
34 // and a pointer to the next stub state in the linked list. |
|
35 // |
|
36 // Every BaselineScript keeps an table of |CacheDescriptor| data |
|
37 // structures, which store the following: |
|
38 // A pointer to the first StubData in the cache. |
|
39 // The bytecode PC of the relevant IC. |
|
40 // The machine-code PC where the call to the stubcode returns. |
|
41 // |
|
42 // A diagram: |
|
43 // |
|
44 // Control flow Pointers |
|
45 // =======# ----. .----> |
|
46 // # | | |
|
47 // #======> \-----/ |
|
48 // |
|
49 // |
|
50 // .---------------------------------------. |
|
51 // | .-------------------------. | |
|
52 // | | .----. | | |
|
53 // Baseline | | | | | | |
|
54 // JIT Code 0 ^ 1 ^ 2 ^ | | | |
|
55 // +--------------+ .-->+-----+ +-----+ +-----+ | | | |
|
56 // | | #=|==>| |==>| |==>| FB | | | | |
|
57 // | | # | +-----+ +-----+ +-----+ | | | |
|
58 // | | # | # # # | | | |
|
59 // |==============|==# | # # # | | | |
|
60 // |=== IC =======| | # # # | | | |
|
61 // .->|==============|<===|======#=========#=========# | | | |
|
62 // | | | | | | | |
|
63 // | | | | | | | |
|
64 // | | | | | | | |
|
65 // | | | | v | | |
|
66 // | | | | +---------+ | | |
|
67 // | | | | | Fallback| | | |
|
68 // | | | | | Stub | | | |
|
69 // | | | | | Code | | | |
|
70 // | | | | +---------+ | | |
|
71 // | +--------------+ | | | |
|
72 // | |_______ | +---------+ | | |
|
73 // | | | | Stub |<---/ | |
|
74 // | IC | \--. | Code | | |
|
75 // | Descriptor | | +---------+ | |
|
76 // | Table v | | |
|
77 // | +-----------------+ | +---------+ | |
|
78 // \--| Ins | PC | Stub |----/ | Stub |<-------/ |
|
79 // +-----------------+ | Code | |
|
80 // | ... | +---------+ |
|
81 // +-----------------+ |
|
82 // Shared |
|
83 // Stub Code |
|
84 // |
|
85 // |
|
86 // Type ICs |
|
87 // ======== |
|
88 // |
|
89 // Type ICs are otherwise regular ICs that are actually nested within |
|
90 // other IC chains. They serve to optimize locations in the code where the |
|
91 // baseline compiler would have otherwise had to perform a type Monitor operation |
|
92 // (e.g. the result of GetProp, GetElem, etc.), or locations where the baseline |
|
93 // compiler would have had to modify a heap typeset using the type of an input |
|
94 // value (e.g. SetProp, SetElem, etc.) |
|
95 // |
|
96 // There are two kinds of Type ICs: Monitor and Update. |
|
97 // |
|
98 // Note that type stub bodies are no-ops. The stubs only exist for their |
|
99 // guards, and their existence simply signifies that the typeset (implicit) |
|
100 // that is being checked already contains that type. |
|
101 // |
|
102 // TypeMonitor ICs |
|
103 // --------------- |
|
104 // Monitor ICs are shared between stubs in the general IC, and monitor the resulting |
|
105 // types of getter operations (call returns, getprop outputs, etc.) |
|
106 // |
|
107 // +-----------+ +-----------+ +-----------+ +-----------+ |
|
108 // ---->| Stub 1 |---->| Stub 2 |---->| Stub 3 |---->| FB Stub | |
|
109 // +-----------+ +-----------+ +-----------+ +-----------+ |
|
110 // | | | | |
|
111 // |------------------/-----------------/ | |
|
112 // v | |
|
113 // +-----------+ +-----------+ +-----------+ | |
|
114 // | Type 1 |---->| Type 2 |---->| Type FB | | |
|
115 // +-----------+ +-----------+ +-----------+ | |
|
116 // | | | | |
|
117 // <----------/-----------------/------------------/------------------/ |
|
118 // r e t u r n p a t h |
|
119 // |
|
120 // After an optimized IC stub successfully executes, it passes control to the type stub |
|
121 // chain to check the resulting type. If no type stub succeeds, and the monitor fallback |
|
122 // stub is reached, the monitor fallback stub performs a manual monitor, and also adds the |
|
123 // appropriate type stub to the chain. |
|
124 // |
|
125 // The IC's main fallback, in addition to generating new mainline stubs, also generates |
|
126 // type stubs as reflected by its returned value. |
|
127 // |
|
128 // NOTE: The type IC chain returns directly to the mainline code, not back to the |
|
129 // stub it was entered from. Thus, entering a type IC is a matter of a |jump|, not |
|
130 // a |call|. This allows us to safely call a VM Monitor function from within the monitor IC's |
|
131 // fallback chain, since the return address (needed for stack inspection) is preserved. |
|
132 // |
|
133 // |
|
134 // TypeUpdate ICs |
|
135 // -------------- |
|
136 // Update ICs update heap typesets and monitor the input types of setter operations |
|
137 // (setelem, setprop inputs, etc.). Unlike monitor ICs, they are not shared |
|
138 // between stubs on an IC, but instead are kept track of on a per-stub basis. |
|
139 // |
|
140 // This is because the main stubs for the operation will each identify a potentially |
|
141 // different TypeObject to update. New input types must be tracked on a typeobject-to- |
|
142 // typeobject basis. |
|
143 // |
|
144 // Type-update ICs cannot be called in tail position (they must return to the |
|
145 // the stub that called them so that the stub may continue to perform its original |
|
146 // purpose). This means that any VMCall to perform a manual type update from C++ must be |
|
147 // done from within the main IC stub. This necessitates that the stub enter a |
|
148 // "BaselineStub" frame before making the call. |
|
149 // |
|
150 // If the type-update IC chain could itself make the VMCall, then the BaselineStub frame |
|
151 // must be entered before calling the type-update chain, and exited afterward. This |
|
152 // is very expensive for a common case where we expect the type-update fallback to not |
|
153 // be called. To avoid the cost of entering and exiting a BaselineStub frame when |
|
154 // using the type-update IC chain, we design the chain to not perform any VM-calls |
|
155 // in its fallback. |
|
156 // |
|
157 // Instead, the type-update IC chain is responsible for returning 1 or 0, depending |
|
158 // on if a type is represented in the chain or not. The fallback stub simply returns |
|
159 // 0, and all other optimized stubs return 1. |
|
160 // If the chain returns 1, then the IC stub goes ahead and performs its operation. |
|
161 // If the chain returns 0, then the IC stub performs a call to the fallback function |
|
162 // inline (doing the requisite BaselineStub frame enter/exit). |
|
163 // This allows us to avoid the expensive subfram enter/exit in the common case. |
|
164 // |
|
165 // r e t u r n p a t h |
|
166 // <--------------.-----------------.-----------------.-----------------. |
|
167 // | | | | |
|
168 // +-----------+ +-----------+ +-----------+ +-----------+ |
|
169 // ---->| Stub 1 |---->| Stub 2 |---->| Stub 3 |---->| FB Stub | |
|
170 // +-----------+ +-----------+ +-----------+ +-----------+ |
|
171 // | ^ | ^ | ^ |
|
172 // | | | | | | |
|
173 // | | | | | |----------------. |
|
174 // | | | | v |1 |0 |
|
175 // | | | | +-----------+ +-----------+ |
|
176 // | | | | | Type 3.1 |--->| FB 3 | |
|
177 // | | | | +-----------+ +-----------+ |
|
178 // | | | | |
|
179 // | | | \-------------.-----------------. |
|
180 // | | | | | | |
|
181 // | | v |1 |1 |0 |
|
182 // | | +-----------+ +-----------+ +-----------+ |
|
183 // | | | Type 2.1 |---->| Type 2.2 |---->| FB 2 | |
|
184 // | | +-----------+ +-----------+ +-----------+ |
|
185 // | | |
|
186 // | \-------------.-----------------. |
|
187 // | | | | |
|
188 // v |1 |1 |0 |
|
189 // +-----------+ +-----------+ +-----------+ |
|
190 // | Type 1.1 |---->| Type 1.2 |---->| FB 1 | |
|
191 // +-----------+ +-----------+ +-----------+ |
|
192 // |
|
193 |
|
194 class ICStub; |
|
195 class ICFallbackStub; |
|
196 |
|
197 // |
|
198 // An entry in the Baseline IC descriptor table. |
|
199 // |
|
200 class ICEntry |
|
201 { |
|
202 private: |
|
203 // A pointer to the baseline IC stub for this instruction. |
|
204 ICStub *firstStub_; |
|
205 |
|
206 // Offset from the start of the JIT code where the IC |
|
207 // load and call instructions are. |
|
208 uint32_t returnOffset_; |
|
209 |
|
210 // The PC of this IC's bytecode op within the JSScript. |
|
211 uint32_t pcOffset_ : 29; |
|
212 |
|
213 public: |
|
214 enum Kind { |
|
215 // A for-op IC entry. |
|
216 Kind_Op = 0, |
|
217 |
|
218 // A non-op IC entry. |
|
219 Kind_NonOp, |
|
220 |
|
221 // A fake IC entry for returning from a callVM. |
|
222 Kind_CallVM, |
|
223 |
|
224 // A fake IC entry for returning from DebugTrapHandler. |
|
225 Kind_DebugTrap, |
|
226 |
|
227 // A fake IC entry for returning from a callVM to |
|
228 // Debug{Prologue,Epilogue}. |
|
229 Kind_DebugPrologue, |
|
230 Kind_DebugEpilogue |
|
231 }; |
|
232 |
|
233 private: |
|
234 // What this IC is for. |
|
235 Kind kind_ : 3; |
|
236 |
|
237 // Set the kind and asserts that it's sane. |
|
238 void setKind(Kind kind) { |
|
239 kind_ = kind; |
|
240 MOZ_ASSERT(this->kind() == kind); |
|
241 } |
|
242 |
|
243 public: |
|
244 ICEntry(uint32_t pcOffset, Kind kind) |
|
245 : firstStub_(nullptr), returnOffset_(), pcOffset_(pcOffset) |
|
246 { |
|
247 // The offset must fit in at least 29 bits, since we shave off 3 for |
|
248 // the Kind enum. |
|
249 MOZ_ASSERT(pcOffset_ == pcOffset); |
|
250 JS_STATIC_ASSERT(BaselineScript::MAX_JSSCRIPT_LENGTH < 0x1fffffffu); |
|
251 MOZ_ASSERT(pcOffset <= BaselineScript::MAX_JSSCRIPT_LENGTH); |
|
252 setKind(kind); |
|
253 } |
|
254 |
|
255 CodeOffsetLabel returnOffset() const { |
|
256 return CodeOffsetLabel(returnOffset_); |
|
257 } |
|
258 |
|
259 void setReturnOffset(CodeOffsetLabel offset) { |
|
260 JS_ASSERT(offset.offset() <= (size_t) UINT32_MAX); |
|
261 returnOffset_ = (uint32_t) offset.offset(); |
|
262 } |
|
263 |
|
264 void fixupReturnOffset(MacroAssembler &masm) { |
|
265 CodeOffsetLabel offset = returnOffset(); |
|
266 offset.fixup(&masm); |
|
267 JS_ASSERT(offset.offset() <= UINT32_MAX); |
|
268 returnOffset_ = (uint32_t) offset.offset(); |
|
269 } |
|
270 |
|
271 uint32_t pcOffset() const { |
|
272 return pcOffset_; |
|
273 } |
|
274 |
|
275 jsbytecode *pc(JSScript *script) const { |
|
276 return script->offsetToPC(pcOffset_); |
|
277 } |
|
278 |
|
279 Kind kind() const { |
|
280 // MSVC compiles enums as signed. |
|
281 return (Kind)(kind_ & 0x7); |
|
282 } |
|
283 bool isForOp() const { |
|
284 return kind() == Kind_Op; |
|
285 } |
|
286 |
|
287 void setForDebugPrologue() { |
|
288 MOZ_ASSERT(kind() == Kind_CallVM); |
|
289 setKind(Kind_DebugPrologue); |
|
290 } |
|
291 void setForDebugEpilogue() { |
|
292 MOZ_ASSERT(kind() == Kind_CallVM); |
|
293 setKind(Kind_DebugEpilogue); |
|
294 } |
|
295 |
|
296 bool hasStub() const { |
|
297 return firstStub_ != nullptr; |
|
298 } |
|
299 ICStub *firstStub() const { |
|
300 JS_ASSERT(hasStub()); |
|
301 return firstStub_; |
|
302 } |
|
303 |
|
304 ICFallbackStub *fallbackStub() const; |
|
305 |
|
306 void setFirstStub(ICStub *stub) { |
|
307 firstStub_ = stub; |
|
308 } |
|
309 |
|
310 static inline size_t offsetOfFirstStub() { |
|
311 return offsetof(ICEntry, firstStub_); |
|
312 } |
|
313 |
|
314 inline ICStub **addressOfFirstStub() { |
|
315 return &firstStub_; |
|
316 } |
|
317 }; |
|
318 |
|
319 // List of baseline IC stub kinds. |
|
320 #define IC_STUB_KIND_LIST(_) \ |
|
321 _(UseCount_Fallback) \ |
|
322 \ |
|
323 _(Profiler_Fallback) \ |
|
324 _(Profiler_PushFunction) \ |
|
325 \ |
|
326 _(TypeMonitor_Fallback) \ |
|
327 _(TypeMonitor_SingleObject) \ |
|
328 _(TypeMonitor_TypeObject) \ |
|
329 _(TypeMonitor_PrimitiveSet) \ |
|
330 \ |
|
331 _(TypeUpdate_Fallback) \ |
|
332 _(TypeUpdate_SingleObject) \ |
|
333 _(TypeUpdate_TypeObject) \ |
|
334 _(TypeUpdate_PrimitiveSet) \ |
|
335 \ |
|
336 _(This_Fallback) \ |
|
337 \ |
|
338 _(NewArray_Fallback) \ |
|
339 _(NewObject_Fallback) \ |
|
340 \ |
|
341 _(Compare_Fallback) \ |
|
342 _(Compare_Int32) \ |
|
343 _(Compare_Double) \ |
|
344 _(Compare_NumberWithUndefined) \ |
|
345 _(Compare_String) \ |
|
346 _(Compare_Boolean) \ |
|
347 _(Compare_Object) \ |
|
348 _(Compare_ObjectWithUndefined) \ |
|
349 _(Compare_Int32WithBoolean) \ |
|
350 \ |
|
351 _(ToBool_Fallback) \ |
|
352 _(ToBool_Int32) \ |
|
353 _(ToBool_String) \ |
|
354 _(ToBool_NullUndefined) \ |
|
355 _(ToBool_Double) \ |
|
356 _(ToBool_Object) \ |
|
357 \ |
|
358 _(ToNumber_Fallback) \ |
|
359 \ |
|
360 _(BinaryArith_Fallback) \ |
|
361 _(BinaryArith_Int32) \ |
|
362 _(BinaryArith_Double) \ |
|
363 _(BinaryArith_StringConcat) \ |
|
364 _(BinaryArith_StringObjectConcat) \ |
|
365 _(BinaryArith_BooleanWithInt32) \ |
|
366 _(BinaryArith_DoubleWithInt32) \ |
|
367 \ |
|
368 _(UnaryArith_Fallback) \ |
|
369 _(UnaryArith_Int32) \ |
|
370 _(UnaryArith_Double) \ |
|
371 \ |
|
372 _(Call_Fallback) \ |
|
373 _(Call_Scripted) \ |
|
374 _(Call_AnyScripted) \ |
|
375 _(Call_Native) \ |
|
376 _(Call_ScriptedApplyArray) \ |
|
377 _(Call_ScriptedApplyArguments) \ |
|
378 _(Call_ScriptedFunCall) \ |
|
379 \ |
|
380 _(GetElem_Fallback) \ |
|
381 _(GetElem_NativeSlot) \ |
|
382 _(GetElem_NativePrototypeSlot) \ |
|
383 _(GetElem_NativePrototypeCallNative) \ |
|
384 _(GetElem_NativePrototypeCallScripted) \ |
|
385 _(GetElem_String) \ |
|
386 _(GetElem_Dense) \ |
|
387 _(GetElem_TypedArray) \ |
|
388 _(GetElem_Arguments) \ |
|
389 \ |
|
390 _(SetElem_Fallback) \ |
|
391 _(SetElem_Dense) \ |
|
392 _(SetElem_DenseAdd) \ |
|
393 _(SetElem_TypedArray) \ |
|
394 \ |
|
395 _(In_Fallback) \ |
|
396 \ |
|
397 _(GetName_Fallback) \ |
|
398 _(GetName_Global) \ |
|
399 _(GetName_Scope0) \ |
|
400 _(GetName_Scope1) \ |
|
401 _(GetName_Scope2) \ |
|
402 _(GetName_Scope3) \ |
|
403 _(GetName_Scope4) \ |
|
404 _(GetName_Scope5) \ |
|
405 _(GetName_Scope6) \ |
|
406 \ |
|
407 _(BindName_Fallback) \ |
|
408 \ |
|
409 _(GetIntrinsic_Fallback) \ |
|
410 _(GetIntrinsic_Constant) \ |
|
411 \ |
|
412 _(GetProp_Fallback) \ |
|
413 _(GetProp_ArrayLength) \ |
|
414 _(GetProp_TypedArrayLength) \ |
|
415 _(GetProp_Primitive) \ |
|
416 _(GetProp_StringLength) \ |
|
417 _(GetProp_Native) \ |
|
418 _(GetProp_NativePrototype) \ |
|
419 _(GetProp_CallScripted) \ |
|
420 _(GetProp_CallNative) \ |
|
421 _(GetProp_CallNativePrototype)\ |
|
422 _(GetProp_CallDOMProxyNative)\ |
|
423 _(GetProp_CallDOMProxyWithGenerationNative)\ |
|
424 _(GetProp_DOMProxyShadowed) \ |
|
425 _(GetProp_ArgumentsLength) \ |
|
426 \ |
|
427 _(SetProp_Fallback) \ |
|
428 _(SetProp_Native) \ |
|
429 _(SetProp_NativeAdd) \ |
|
430 _(SetProp_CallScripted) \ |
|
431 _(SetProp_CallNative) \ |
|
432 \ |
|
433 _(TableSwitch) \ |
|
434 \ |
|
435 _(IteratorNew_Fallback) \ |
|
436 _(IteratorMore_Fallback) \ |
|
437 _(IteratorMore_Native) \ |
|
438 _(IteratorNext_Fallback) \ |
|
439 _(IteratorNext_Native) \ |
|
440 _(IteratorClose_Fallback) \ |
|
441 \ |
|
442 _(InstanceOf_Fallback) \ |
|
443 \ |
|
444 _(TypeOf_Fallback) \ |
|
445 _(TypeOf_Typed) \ |
|
446 \ |
|
447 _(Rest_Fallback) \ |
|
448 \ |
|
449 _(RetSub_Fallback) \ |
|
450 _(RetSub_Resume) |
|
451 |
|
452 #define FORWARD_DECLARE_STUBS(kindName) class IC##kindName; |
|
453 IC_STUB_KIND_LIST(FORWARD_DECLARE_STUBS) |
|
454 #undef FORWARD_DECLARE_STUBS |
|
455 |
|
456 class ICMonitoredStub; |
|
457 class ICMonitoredFallbackStub; |
|
458 class ICUpdatedStub; |
|
459 |
|
460 // Constant iterator that traverses arbitrary chains of ICStubs. |
|
461 // No requirements are made of the ICStub used to construct this |
|
462 // iterator, aside from that the stub be part of a nullptr-terminated |
|
463 // chain. |
|
464 // The iterator is considered to be at its end once it has been |
|
465 // incremented _past_ the last stub. Thus, if 'atEnd()' returns |
|
466 // true, the '*' and '->' operations are not valid. |
|
467 class ICStubConstIterator |
|
468 { |
|
469 friend class ICStub; |
|
470 friend class ICFallbackStub; |
|
471 |
|
472 private: |
|
473 ICStub *currentStub_; |
|
474 |
|
475 public: |
|
476 ICStubConstIterator(ICStub *currentStub) : currentStub_(currentStub) {} |
|
477 |
|
478 static ICStubConstIterator StartingAt(ICStub *stub) { |
|
479 return ICStubConstIterator(stub); |
|
480 } |
|
481 static ICStubConstIterator End(ICStub *stub) { |
|
482 return ICStubConstIterator(nullptr); |
|
483 } |
|
484 |
|
485 bool operator ==(const ICStubConstIterator &other) const { |
|
486 return currentStub_ == other.currentStub_; |
|
487 } |
|
488 bool operator !=(const ICStubConstIterator &other) const { |
|
489 return !(*this == other); |
|
490 } |
|
491 |
|
492 ICStubConstIterator &operator++(); |
|
493 |
|
494 ICStubConstIterator operator++(int) { |
|
495 ICStubConstIterator oldThis(*this); |
|
496 ++(*this); |
|
497 return oldThis; |
|
498 } |
|
499 |
|
500 ICStub *operator *() const { |
|
501 JS_ASSERT(currentStub_); |
|
502 return currentStub_; |
|
503 } |
|
504 |
|
505 ICStub *operator ->() const { |
|
506 JS_ASSERT(currentStub_); |
|
507 return currentStub_; |
|
508 } |
|
509 |
|
510 bool atEnd() const { |
|
511 return currentStub_ == nullptr; |
|
512 } |
|
513 }; |
|
514 |
|
515 // Iterator that traverses "regular" IC chains that start at an ICEntry |
|
516 // and are terminated with an ICFallbackStub. |
|
517 // |
|
518 // The iterator is considered to be at its end once it is _at_ the |
|
519 // fallback stub. Thus, unlike the ICStubConstIterator, operators |
|
520 // '*' and '->' are valid even if 'atEnd()' returns true - they |
|
521 // will act on the fallback stub. |
|
522 // |
|
523 // This iterator also allows unlinking of stubs being traversed. |
|
524 // Note that 'unlink' does not implicitly advance the iterator - |
|
525 // it must be advanced explicitly using '++'. |
|
526 class ICStubIterator |
|
527 { |
|
528 friend class ICFallbackStub; |
|
529 |
|
530 private: |
|
531 ICEntry *icEntry_; |
|
532 ICFallbackStub *fallbackStub_; |
|
533 ICStub *previousStub_; |
|
534 ICStub *currentStub_; |
|
535 bool unlinked_; |
|
536 |
|
537 ICStubIterator(ICFallbackStub *fallbackStub, bool end=false); |
|
538 public: |
|
539 |
|
540 bool operator ==(const ICStubIterator &other) const { |
|
541 // == should only ever be called on stubs from the same chain. |
|
542 JS_ASSERT(icEntry_ == other.icEntry_); |
|
543 JS_ASSERT(fallbackStub_ == other.fallbackStub_); |
|
544 return currentStub_ == other.currentStub_; |
|
545 } |
|
546 bool operator !=(const ICStubIterator &other) const { |
|
547 return !(*this == other); |
|
548 } |
|
549 |
|
550 ICStubIterator &operator++(); |
|
551 |
|
552 ICStubIterator operator++(int) { |
|
553 ICStubIterator oldThis(*this); |
|
554 ++(*this); |
|
555 return oldThis; |
|
556 } |
|
557 |
|
558 ICStub *operator *() const { |
|
559 return currentStub_; |
|
560 } |
|
561 |
|
562 ICStub *operator ->() const { |
|
563 return currentStub_; |
|
564 } |
|
565 |
|
566 bool atEnd() const { |
|
567 return currentStub_ == (ICStub *) fallbackStub_; |
|
568 } |
|
569 |
|
570 void unlink(JSContext *cx); |
|
571 }; |
|
572 |
|
573 // |
|
574 // Base class for all IC stubs. |
|
575 // |
|
576 class ICStub |
|
577 { |
|
578 friend class ICFallbackStub; |
|
579 |
|
580 public: |
|
581 enum Kind { |
|
582 INVALID = 0, |
|
583 #define DEF_ENUM_KIND(kindName) kindName, |
|
584 IC_STUB_KIND_LIST(DEF_ENUM_KIND) |
|
585 #undef DEF_ENUM_KIND |
|
586 LIMIT |
|
587 }; |
|
588 |
|
589 static inline bool IsValidKind(Kind k) { |
|
590 return (k > INVALID) && (k < LIMIT); |
|
591 } |
|
592 |
|
593 static const char *KindString(Kind k) { |
|
594 switch(k) { |
|
595 #define DEF_KIND_STR(kindName) case kindName: return #kindName; |
|
596 IC_STUB_KIND_LIST(DEF_KIND_STR) |
|
597 #undef DEF_KIND_STR |
|
598 default: |
|
599 MOZ_ASSUME_UNREACHABLE("Invalid kind."); |
|
600 } |
|
601 } |
|
602 |
|
603 enum Trait { |
|
604 Regular = 0x0, |
|
605 Fallback = 0x1, |
|
606 Monitored = 0x2, |
|
607 MonitoredFallback = 0x3, |
|
608 Updated = 0x4 |
|
609 }; |
|
610 |
|
611 void markCode(JSTracer *trc, const char *name); |
|
612 void updateCode(JitCode *stubCode); |
|
613 void trace(JSTracer *trc); |
|
614 |
|
615 protected: |
|
616 // The raw jitcode to call for this stub. |
|
617 uint8_t *stubCode_; |
|
618 |
|
619 // Pointer to next IC stub. This is null for the last IC stub, which should |
|
620 // either be a fallback or inert IC stub. |
|
621 ICStub *next_; |
|
622 |
|
623 // A 16-bit field usable by subtypes of ICStub for subtype-specific small-info |
|
624 uint16_t extra_; |
|
625 |
|
626 // The kind of the stub. |
|
627 // High bit is 'isFallback' flag. |
|
628 // Second high bit is 'isMonitored' flag. |
|
629 Trait trait_ : 3; |
|
630 Kind kind_ : 13; |
|
631 |
|
632 inline ICStub(Kind kind, JitCode *stubCode) |
|
633 : stubCode_(stubCode->raw()), |
|
634 next_(nullptr), |
|
635 extra_(0), |
|
636 trait_(Regular), |
|
637 kind_(kind) |
|
638 { |
|
639 JS_ASSERT(stubCode != nullptr); |
|
640 } |
|
641 |
|
642 inline ICStub(Kind kind, Trait trait, JitCode *stubCode) |
|
643 : stubCode_(stubCode->raw()), |
|
644 next_(nullptr), |
|
645 extra_(0), |
|
646 trait_(trait), |
|
647 kind_(kind) |
|
648 { |
|
649 JS_ASSERT(stubCode != nullptr); |
|
650 } |
|
651 |
|
652 inline Trait trait() const { |
|
653 // Workaround for MSVC reading trait_ as signed value. |
|
654 return (Trait)(trait_ & 0x7); |
|
655 } |
|
656 |
|
657 public: |
|
658 |
|
659 inline Kind kind() const { |
|
660 return static_cast<Kind>(kind_); |
|
661 } |
|
662 |
|
663 inline bool isFallback() const { |
|
664 return trait() == Fallback || trait() == MonitoredFallback; |
|
665 } |
|
666 |
|
667 inline bool isMonitored() const { |
|
668 return trait() == Monitored; |
|
669 } |
|
670 |
|
671 inline bool isUpdated() const { |
|
672 return trait() == Updated; |
|
673 } |
|
674 |
|
675 inline bool isMonitoredFallback() const { |
|
676 return trait() == MonitoredFallback; |
|
677 } |
|
678 |
|
679 inline const ICFallbackStub *toFallbackStub() const { |
|
680 JS_ASSERT(isFallback()); |
|
681 return reinterpret_cast<const ICFallbackStub *>(this); |
|
682 } |
|
683 |
|
684 inline ICFallbackStub *toFallbackStub() { |
|
685 JS_ASSERT(isFallback()); |
|
686 return reinterpret_cast<ICFallbackStub *>(this); |
|
687 } |
|
688 |
|
689 inline const ICMonitoredStub *toMonitoredStub() const { |
|
690 JS_ASSERT(isMonitored()); |
|
691 return reinterpret_cast<const ICMonitoredStub *>(this); |
|
692 } |
|
693 |
|
694 inline ICMonitoredStub *toMonitoredStub() { |
|
695 JS_ASSERT(isMonitored()); |
|
696 return reinterpret_cast<ICMonitoredStub *>(this); |
|
697 } |
|
698 |
|
699 inline const ICMonitoredFallbackStub *toMonitoredFallbackStub() const { |
|
700 JS_ASSERT(isMonitoredFallback()); |
|
701 return reinterpret_cast<const ICMonitoredFallbackStub *>(this); |
|
702 } |
|
703 |
|
704 inline ICMonitoredFallbackStub *toMonitoredFallbackStub() { |
|
705 JS_ASSERT(isMonitoredFallback()); |
|
706 return reinterpret_cast<ICMonitoredFallbackStub *>(this); |
|
707 } |
|
708 |
|
709 inline const ICUpdatedStub *toUpdatedStub() const { |
|
710 JS_ASSERT(isUpdated()); |
|
711 return reinterpret_cast<const ICUpdatedStub *>(this); |
|
712 } |
|
713 |
|
714 inline ICUpdatedStub *toUpdatedStub() { |
|
715 JS_ASSERT(isUpdated()); |
|
716 return reinterpret_cast<ICUpdatedStub *>(this); |
|
717 } |
|
718 |
|
719 #define KIND_METHODS(kindName) \ |
|
720 inline bool is##kindName() const { return kind() == kindName; } \ |
|
721 inline const IC##kindName *to##kindName() const { \ |
|
722 JS_ASSERT(is##kindName()); \ |
|
723 return reinterpret_cast<const IC##kindName *>(this); \ |
|
724 } \ |
|
725 inline IC##kindName *to##kindName() { \ |
|
726 JS_ASSERT(is##kindName()); \ |
|
727 return reinterpret_cast<IC##kindName *>(this); \ |
|
728 } |
|
729 IC_STUB_KIND_LIST(KIND_METHODS) |
|
730 #undef KIND_METHODS |
|
731 |
|
732 inline ICStub *next() const { |
|
733 return next_; |
|
734 } |
|
735 |
|
736 inline bool hasNext() const { |
|
737 return next_ != nullptr; |
|
738 } |
|
739 |
|
740 inline void setNext(ICStub *stub) { |
|
741 // Note: next_ only needs to be changed under the compilation lock for |
|
742 // non-type-monitor/update ICs. |
|
743 next_ = stub; |
|
744 } |
|
745 |
|
746 inline ICStub **addressOfNext() { |
|
747 return &next_; |
|
748 } |
|
749 |
|
750 inline JitCode *jitCode() { |
|
751 return JitCode::FromExecutable(stubCode_); |
|
752 } |
|
753 |
|
754 inline uint8_t *rawStubCode() const { |
|
755 return stubCode_; |
|
756 } |
|
757 |
|
758 // This method is not valid on TypeUpdate stub chains! |
|
759 inline ICFallbackStub *getChainFallback() { |
|
760 ICStub *lastStub = this; |
|
761 while (lastStub->next_) |
|
762 lastStub = lastStub->next_; |
|
763 JS_ASSERT(lastStub->isFallback()); |
|
764 return lastStub->toFallbackStub(); |
|
765 } |
|
766 |
|
767 inline ICStubConstIterator beginHere() { |
|
768 return ICStubConstIterator::StartingAt(this); |
|
769 } |
|
770 |
|
771 static inline size_t offsetOfNext() { |
|
772 return offsetof(ICStub, next_); |
|
773 } |
|
774 |
|
775 static inline size_t offsetOfStubCode() { |
|
776 return offsetof(ICStub, stubCode_); |
|
777 } |
|
778 |
|
779 static inline size_t offsetOfExtra() { |
|
780 return offsetof(ICStub, extra_); |
|
781 } |
|
782 |
|
783 static bool CanMakeCalls(ICStub::Kind kind) { |
|
784 JS_ASSERT(IsValidKind(kind)); |
|
785 switch (kind) { |
|
786 case Call_Fallback: |
|
787 case Call_Scripted: |
|
788 case Call_AnyScripted: |
|
789 case Call_Native: |
|
790 case Call_ScriptedApplyArray: |
|
791 case Call_ScriptedApplyArguments: |
|
792 case Call_ScriptedFunCall: |
|
793 case UseCount_Fallback: |
|
794 case GetElem_NativeSlot: |
|
795 case GetElem_NativePrototypeSlot: |
|
796 case GetElem_NativePrototypeCallNative: |
|
797 case GetElem_NativePrototypeCallScripted: |
|
798 case GetProp_CallScripted: |
|
799 case GetProp_CallNative: |
|
800 case GetProp_CallNativePrototype: |
|
801 case GetProp_CallDOMProxyNative: |
|
802 case GetProp_CallDOMProxyWithGenerationNative: |
|
803 case GetProp_DOMProxyShadowed: |
|
804 case SetProp_CallScripted: |
|
805 case SetProp_CallNative: |
|
806 case RetSub_Fallback: |
|
807 // These two fallback stubs don't actually make non-tail calls, |
|
808 // but the fallback code for the bailout path needs to pop the stub frame |
|
809 // pushed during the bailout. |
|
810 case GetProp_Fallback: |
|
811 case SetProp_Fallback: |
|
812 #if JS_HAS_NO_SUCH_METHOD |
|
813 case GetElem_Dense: |
|
814 case GetElem_Arguments: |
|
815 case GetProp_NativePrototype: |
|
816 case GetProp_Native: |
|
817 #endif |
|
818 return true; |
|
819 default: |
|
820 return false; |
|
821 } |
|
822 } |
|
823 |
|
824 // Optimized stubs get purged on GC. But some stubs can be active on the |
|
825 // stack during GC - specifically the ones that can make calls. To ensure |
|
826 // that these do not get purged, all stubs that can make calls are allocated |
|
827 // in the fallback stub space. |
|
828 bool allocatedInFallbackSpace() const { |
|
829 JS_ASSERT(next()); |
|
830 return CanMakeCalls(kind()); |
|
831 } |
|
832 }; |
|
833 |
|
834 class ICFallbackStub : public ICStub |
|
835 { |
|
836 friend class ICStubConstIterator; |
|
837 protected: |
|
838 // Fallback stubs need these fields to easily add new stubs to |
|
839 // the linked list of stubs for an IC. |
|
840 |
|
841 // The IC entry for this linked list of stubs. |
|
842 ICEntry *icEntry_; |
|
843 |
|
844 // The number of stubs kept in the IC entry. |
|
845 uint32_t numOptimizedStubs_; |
|
846 |
|
847 // A pointer to the location stub pointer that needs to be |
|
848 // changed to add a new "last" stub immediately before the fallback |
|
849 // stub. This'll start out pointing to the icEntry's "firstStub_" |
|
850 // field, and as new stubs are addd, it'll point to the current |
|
851 // last stub's "next_" field. |
|
852 ICStub **lastStubPtrAddr_; |
|
853 |
|
854 ICFallbackStub(Kind kind, JitCode *stubCode) |
|
855 : ICStub(kind, ICStub::Fallback, stubCode), |
|
856 icEntry_(nullptr), |
|
857 numOptimizedStubs_(0), |
|
858 lastStubPtrAddr_(nullptr) {} |
|
859 |
|
860 ICFallbackStub(Kind kind, Trait trait, JitCode *stubCode) |
|
861 : ICStub(kind, trait, stubCode), |
|
862 icEntry_(nullptr), |
|
863 numOptimizedStubs_(0), |
|
864 lastStubPtrAddr_(nullptr) |
|
865 { |
|
866 JS_ASSERT(trait == ICStub::Fallback || |
|
867 trait == ICStub::MonitoredFallback); |
|
868 } |
|
869 |
|
870 public: |
|
871 inline ICEntry *icEntry() const { |
|
872 return icEntry_; |
|
873 } |
|
874 |
|
875 inline size_t numOptimizedStubs() const { |
|
876 return (size_t) numOptimizedStubs_; |
|
877 } |
|
878 |
|
879 // The icEntry and lastStubPtrAddr_ fields can't be initialized when the stub is |
|
880 // created since the stub is created at compile time, and we won't know the IC entry |
|
881 // address until after compile when the BaselineScript is created. This method |
|
882 // allows these fields to be fixed up at that point. |
|
883 void fixupICEntry(ICEntry *icEntry) { |
|
884 JS_ASSERT(icEntry_ == nullptr); |
|
885 JS_ASSERT(lastStubPtrAddr_ == nullptr); |
|
886 icEntry_ = icEntry; |
|
887 lastStubPtrAddr_ = icEntry_->addressOfFirstStub(); |
|
888 } |
|
889 |
|
890 // Add a new stub to the IC chain terminated by this fallback stub. |
|
891 void addNewStub(ICStub *stub) { |
|
892 JS_ASSERT(*lastStubPtrAddr_ == this); |
|
893 JS_ASSERT(stub->next() == nullptr); |
|
894 stub->setNext(this); |
|
895 *lastStubPtrAddr_ = stub; |
|
896 lastStubPtrAddr_ = stub->addressOfNext(); |
|
897 numOptimizedStubs_++; |
|
898 } |
|
899 |
|
900 ICStubConstIterator beginChainConst() const { |
|
901 return ICStubConstIterator(icEntry_->firstStub()); |
|
902 } |
|
903 |
|
904 ICStubIterator beginChain() { |
|
905 return ICStubIterator(this); |
|
906 } |
|
907 |
|
908 bool hasStub(ICStub::Kind kind) const { |
|
909 for (ICStubConstIterator iter = beginChainConst(); !iter.atEnd(); iter++) { |
|
910 if (iter->kind() == kind) |
|
911 return true; |
|
912 } |
|
913 return false; |
|
914 } |
|
915 |
|
916 unsigned numStubsWithKind(ICStub::Kind kind) const { |
|
917 unsigned count = 0; |
|
918 for (ICStubConstIterator iter = beginChainConst(); !iter.atEnd(); iter++) { |
|
919 if (iter->kind() == kind) |
|
920 count++; |
|
921 } |
|
922 return count; |
|
923 } |
|
924 |
|
925 void unlinkStub(Zone *zone, ICStub *prev, ICStub *stub); |
|
926 void unlinkStubsWithKind(JSContext *cx, ICStub::Kind kind); |
|
927 }; |
|
928 |
|
929 // Monitored stubs are IC stubs that feed a single resulting value out to a |
|
930 // type monitor operation. |
|
931 class ICMonitoredStub : public ICStub |
|
932 { |
|
933 protected: |
|
934 // Pointer to the start of the type monitoring stub chain. |
|
935 ICStub *firstMonitorStub_; |
|
936 |
|
937 ICMonitoredStub(Kind kind, JitCode *stubCode, ICStub *firstMonitorStub); |
|
938 |
|
939 public: |
|
940 inline void updateFirstMonitorStub(ICStub *monitorStub) { |
|
941 // This should only be called once: when the first optimized monitor stub |
|
942 // is added to the type monitor IC chain. |
|
943 JS_ASSERT(firstMonitorStub_ && firstMonitorStub_->isTypeMonitor_Fallback()); |
|
944 firstMonitorStub_ = monitorStub; |
|
945 } |
|
946 inline void resetFirstMonitorStub(ICStub *monitorFallback) { |
|
947 JS_ASSERT(monitorFallback->isTypeMonitor_Fallback()); |
|
948 firstMonitorStub_ = monitorFallback; |
|
949 } |
|
950 inline ICStub *firstMonitorStub() const { |
|
951 return firstMonitorStub_; |
|
952 } |
|
953 |
|
954 static inline size_t offsetOfFirstMonitorStub() { |
|
955 return offsetof(ICMonitoredStub, firstMonitorStub_); |
|
956 } |
|
957 }; |
|
958 |
|
959 // Monitored fallback stubs - as the name implies. |
|
960 class ICMonitoredFallbackStub : public ICFallbackStub |
|
961 { |
|
962 protected: |
|
963 // Pointer to the fallback monitor stub. |
|
964 ICTypeMonitor_Fallback *fallbackMonitorStub_; |
|
965 |
|
966 ICMonitoredFallbackStub(Kind kind, JitCode *stubCode) |
|
967 : ICFallbackStub(kind, ICStub::MonitoredFallback, stubCode), |
|
968 fallbackMonitorStub_(nullptr) {} |
|
969 |
|
970 public: |
|
971 bool initMonitoringChain(JSContext *cx, ICStubSpace *space); |
|
972 bool addMonitorStubForValue(JSContext *cx, JSScript *script, HandleValue val); |
|
973 |
|
974 inline ICTypeMonitor_Fallback *fallbackMonitorStub() const { |
|
975 return fallbackMonitorStub_; |
|
976 } |
|
977 |
|
978 static inline size_t offsetOfFallbackMonitorStub() { |
|
979 return offsetof(ICMonitoredFallbackStub, fallbackMonitorStub_); |
|
980 } |
|
981 }; |
|
982 |
|
983 // Updated stubs are IC stubs that use a TypeUpdate IC to track |
|
984 // the status of heap typesets that need to be updated. |
|
985 class ICUpdatedStub : public ICStub |
|
986 { |
|
987 protected: |
|
988 // Pointer to the start of the type updating stub chain. |
|
989 ICStub *firstUpdateStub_; |
|
990 |
|
991 static const uint32_t MAX_OPTIMIZED_STUBS = 8; |
|
992 uint32_t numOptimizedStubs_; |
|
993 |
|
994 ICUpdatedStub(Kind kind, JitCode *stubCode) |
|
995 : ICStub(kind, ICStub::Updated, stubCode), |
|
996 firstUpdateStub_(nullptr), |
|
997 numOptimizedStubs_(0) |
|
998 {} |
|
999 |
|
1000 public: |
|
1001 bool initUpdatingChain(JSContext *cx, ICStubSpace *space); |
|
1002 |
|
1003 bool addUpdateStubForValue(JSContext *cx, HandleScript script, HandleObject obj, HandleId id, |
|
1004 HandleValue val); |
|
1005 |
|
1006 void addOptimizedUpdateStub(ICStub *stub) { |
|
1007 if (firstUpdateStub_->isTypeUpdate_Fallback()) { |
|
1008 stub->setNext(firstUpdateStub_); |
|
1009 firstUpdateStub_ = stub; |
|
1010 } else { |
|
1011 ICStub *iter = firstUpdateStub_; |
|
1012 JS_ASSERT(iter->next() != nullptr); |
|
1013 while (!iter->next()->isTypeUpdate_Fallback()) |
|
1014 iter = iter->next(); |
|
1015 JS_ASSERT(iter->next()->next() == nullptr); |
|
1016 stub->setNext(iter->next()); |
|
1017 iter->setNext(stub); |
|
1018 } |
|
1019 |
|
1020 numOptimizedStubs_++; |
|
1021 } |
|
1022 |
|
1023 inline ICStub *firstUpdateStub() const { |
|
1024 return firstUpdateStub_; |
|
1025 } |
|
1026 |
|
1027 bool hasTypeUpdateStub(ICStub::Kind kind) { |
|
1028 ICStub *stub = firstUpdateStub_; |
|
1029 do { |
|
1030 if (stub->kind() == kind) |
|
1031 return true; |
|
1032 |
|
1033 stub = stub->next(); |
|
1034 } while (stub); |
|
1035 |
|
1036 return false; |
|
1037 } |
|
1038 |
|
1039 inline uint32_t numOptimizedStubs() const { |
|
1040 return numOptimizedStubs_; |
|
1041 } |
|
1042 |
|
1043 static inline size_t offsetOfFirstUpdateStub() { |
|
1044 return offsetof(ICUpdatedStub, firstUpdateStub_); |
|
1045 } |
|
1046 }; |
|
1047 |
|
1048 // Base class for stubcode compilers. |
|
1049 class ICStubCompiler |
|
1050 { |
|
1051 // Prevent GC in the middle of stub compilation. |
|
1052 js::gc::AutoSuppressGC suppressGC; |
|
1053 |
|
1054 |
|
1055 protected: |
|
1056 JSContext *cx; |
|
1057 ICStub::Kind kind; |
|
1058 #ifdef DEBUG |
|
1059 bool entersStubFrame_; |
|
1060 #endif |
|
1061 |
|
1062 // By default the stubcode key is just the kind. |
|
1063 virtual int32_t getKey() const { |
|
1064 return static_cast<int32_t>(kind); |
|
1065 } |
|
1066 |
|
1067 virtual bool generateStubCode(MacroAssembler &masm) = 0; |
|
1068 virtual bool postGenerateStubCode(MacroAssembler &masm, Handle<JitCode *> genCode) { |
|
1069 return true; |
|
1070 } |
|
1071 JitCode *getStubCode(); |
|
1072 |
|
1073 ICStubCompiler(JSContext *cx, ICStub::Kind kind) |
|
1074 : suppressGC(cx), cx(cx), kind(kind) |
|
1075 #ifdef DEBUG |
|
1076 , entersStubFrame_(false) |
|
1077 #endif |
|
1078 {} |
|
1079 |
|
1080 // Emits a tail call to a VMFunction wrapper. |
|
1081 bool tailCallVM(const VMFunction &fun, MacroAssembler &masm); |
|
1082 |
|
1083 // Emits a normal (non-tail) call to a VMFunction wrapper. |
|
1084 bool callVM(const VMFunction &fun, MacroAssembler &masm); |
|
1085 |
|
1086 // Emits a call to a type-update IC, assuming that the value to be |
|
1087 // checked is already in R0. |
|
1088 bool callTypeUpdateIC(MacroAssembler &masm, uint32_t objectOffset); |
|
1089 |
|
1090 // A stub frame is used when a stub wants to call into the VM without |
|
1091 // performing a tail call. This is required for the return address |
|
1092 // to pc mapping to work. |
|
1093 void enterStubFrame(MacroAssembler &masm, Register scratch); |
|
1094 void leaveStubFrame(MacroAssembler &masm, bool calledIntoIon = false); |
|
1095 void leaveStubFrameHead(MacroAssembler &masm, bool calledIntoIon = false); |
|
1096 void leaveStubFrameCommonTail(MacroAssembler &masm); |
|
1097 |
|
1098 // Some stubs need to emit SPS profiler updates. This emits the guarding |
|
1099 // jitcode for those stubs. If profiling is not enabled, jumps to the |
|
1100 // given label. |
|
1101 void guardProfilingEnabled(MacroAssembler &masm, Register scratch, Label *skip); |
|
1102 |
|
1103 // Higher-level helper to emit an update to the profiler pseudo-stack. |
|
1104 void emitProfilingUpdate(MacroAssembler &masm, Register pcIdx, Register scratch, |
|
1105 uint32_t stubPcOffset); |
|
1106 void emitProfilingUpdate(MacroAssembler &masm, GeneralRegisterSet regs, uint32_t stubPcOffset); |
|
1107 |
|
1108 inline GeneralRegisterSet availableGeneralRegs(size_t numInputs) const { |
|
1109 GeneralRegisterSet regs(GeneralRegisterSet::All()); |
|
1110 JS_ASSERT(!regs.has(BaselineStackReg)); |
|
1111 #if defined(JS_CODEGEN_ARM) |
|
1112 JS_ASSERT(!regs.has(BaselineTailCallReg)); |
|
1113 regs.take(BaselineSecondScratchReg); |
|
1114 #elif defined(JS_CODEGEN_MIPS) |
|
1115 JS_ASSERT(!regs.has(BaselineTailCallReg)); |
|
1116 JS_ASSERT(!regs.has(BaselineSecondScratchReg)); |
|
1117 #endif |
|
1118 regs.take(BaselineFrameReg); |
|
1119 regs.take(BaselineStubReg); |
|
1120 #ifdef JS_CODEGEN_X64 |
|
1121 regs.take(ExtractTemp0); |
|
1122 regs.take(ExtractTemp1); |
|
1123 #endif |
|
1124 |
|
1125 switch (numInputs) { |
|
1126 case 0: |
|
1127 break; |
|
1128 case 1: |
|
1129 regs.take(R0); |
|
1130 break; |
|
1131 case 2: |
|
1132 regs.take(R0); |
|
1133 regs.take(R1); |
|
1134 break; |
|
1135 default: |
|
1136 MOZ_ASSUME_UNREACHABLE("Invalid numInputs"); |
|
1137 } |
|
1138 |
|
1139 return regs; |
|
1140 } |
|
1141 |
|
1142 #ifdef JSGC_GENERATIONAL |
|
1143 inline bool emitPostWriteBarrierSlot(MacroAssembler &masm, Register obj, ValueOperand val, |
|
1144 Register scratch, GeneralRegisterSet saveRegs); |
|
1145 #endif |
|
1146 |
|
1147 public: |
|
1148 virtual ICStub *getStub(ICStubSpace *space) = 0; |
|
1149 |
|
1150 ICStubSpace *getStubSpace(JSScript *script) { |
|
1151 if (ICStub::CanMakeCalls(kind)) |
|
1152 return script->baselineScript()->fallbackStubSpace(); |
|
1153 return script->zone()->jitZone()->optimizedStubSpace(); |
|
1154 } |
|
1155 }; |
|
1156 |
|
1157 // Base class for stub compilers that can generate multiple stubcodes. |
|
1158 // These compilers need access to the JSOp they are compiling for. |
|
1159 class ICMultiStubCompiler : public ICStubCompiler |
|
1160 { |
|
1161 protected: |
|
1162 JSOp op; |
|
1163 |
|
1164 // Stub keys for multi-stub kinds are composed of both the kind |
|
1165 // and the op they are compiled for. |
|
1166 virtual int32_t getKey() const { |
|
1167 return static_cast<int32_t>(kind) | (static_cast<int32_t>(op) << 16); |
|
1168 } |
|
1169 |
|
1170 ICMultiStubCompiler(JSContext *cx, ICStub::Kind kind, JSOp op) |
|
1171 : ICStubCompiler(cx, kind), op(op) {} |
|
1172 }; |
|
1173 |
|
1174 // UseCount_Fallback |
|
1175 |
|
1176 // A UseCount IC chain has only the fallback stub. |
|
1177 class ICUseCount_Fallback : public ICFallbackStub |
|
1178 { |
|
1179 friend class ICStubSpace; |
|
1180 |
|
1181 ICUseCount_Fallback(JitCode *stubCode) |
|
1182 : ICFallbackStub(ICStub::UseCount_Fallback, stubCode) |
|
1183 { } |
|
1184 |
|
1185 public: |
|
1186 static inline ICUseCount_Fallback *New(ICStubSpace *space, JitCode *code) { |
|
1187 if (!code) |
|
1188 return nullptr; |
|
1189 return space->allocate<ICUseCount_Fallback>(code); |
|
1190 } |
|
1191 |
|
1192 // Compiler for this stub kind. |
|
1193 class Compiler : public ICStubCompiler { |
|
1194 protected: |
|
1195 bool generateStubCode(MacroAssembler &masm); |
|
1196 |
|
1197 public: |
|
1198 Compiler(JSContext *cx) |
|
1199 : ICStubCompiler(cx, ICStub::UseCount_Fallback) |
|
1200 { } |
|
1201 |
|
1202 ICUseCount_Fallback *getStub(ICStubSpace *space) { |
|
1203 return ICUseCount_Fallback::New(space, getStubCode()); |
|
1204 } |
|
1205 }; |
|
1206 }; |
|
1207 |
|
1208 // Profiler_Fallback |
|
1209 |
|
1210 class ICProfiler_Fallback : public ICFallbackStub |
|
1211 { |
|
1212 friend class ICStubSpace; |
|
1213 |
|
1214 ICProfiler_Fallback(JitCode *stubCode) |
|
1215 : ICFallbackStub(ICStub::Profiler_Fallback, stubCode) |
|
1216 { } |
|
1217 |
|
1218 public: |
|
1219 static inline ICProfiler_Fallback *New(ICStubSpace *space, JitCode *code) { |
|
1220 if (!code) |
|
1221 return nullptr; |
|
1222 return space->allocate<ICProfiler_Fallback>(code); |
|
1223 } |
|
1224 |
|
1225 // Compiler for this stub kind. |
|
1226 class Compiler : public ICStubCompiler { |
|
1227 protected: |
|
1228 bool generateStubCode(MacroAssembler &masm); |
|
1229 |
|
1230 public: |
|
1231 Compiler(JSContext *cx) |
|
1232 : ICStubCompiler(cx, ICStub::Profiler_Fallback) |
|
1233 { } |
|
1234 |
|
1235 ICProfiler_Fallback *getStub(ICStubSpace *space) { |
|
1236 return ICProfiler_Fallback::New(space, getStubCode()); |
|
1237 } |
|
1238 }; |
|
1239 }; |
|
1240 |
|
1241 // Profiler_PushFunction |
|
1242 |
|
1243 class ICProfiler_PushFunction : public ICStub |
|
1244 { |
|
1245 friend class ICStubSpace; |
|
1246 |
|
1247 protected: |
|
1248 const char *str_; |
|
1249 HeapPtrScript script_; |
|
1250 |
|
1251 ICProfiler_PushFunction(JitCode *stubCode, const char *str, HandleScript script); |
|
1252 |
|
1253 public: |
|
1254 static inline ICProfiler_PushFunction *New(ICStubSpace *space, JitCode *code, |
|
1255 const char *str, HandleScript script) |
|
1256 { |
|
1257 if (!code) |
|
1258 return nullptr; |
|
1259 return space->allocate<ICProfiler_PushFunction>(code, str, script); |
|
1260 } |
|
1261 |
|
1262 HeapPtrScript &script() { |
|
1263 return script_; |
|
1264 } |
|
1265 |
|
1266 static size_t offsetOfStr() { |
|
1267 return offsetof(ICProfiler_PushFunction, str_); |
|
1268 } |
|
1269 static size_t offsetOfScript() { |
|
1270 return offsetof(ICProfiler_PushFunction, script_); |
|
1271 } |
|
1272 |
|
1273 // Compiler for this stub kind. |
|
1274 class Compiler : public ICStubCompiler { |
|
1275 protected: |
|
1276 const char *str_; |
|
1277 RootedScript script_; |
|
1278 bool generateStubCode(MacroAssembler &masm); |
|
1279 |
|
1280 public: |
|
1281 Compiler(JSContext *cx, const char *str, HandleScript script) |
|
1282 : ICStubCompiler(cx, ICStub::Profiler_PushFunction), |
|
1283 str_(str), |
|
1284 script_(cx, script) |
|
1285 { } |
|
1286 |
|
1287 ICProfiler_PushFunction *getStub(ICStubSpace *space) { |
|
1288 return ICProfiler_PushFunction::New(space, getStubCode(), str_, script_); |
|
1289 } |
|
1290 }; |
|
1291 }; |
|
1292 |
|
1293 |
|
1294 // TypeCheckPrimitiveSetStub |
|
1295 // Base class for IC stubs (TypeUpdate or TypeMonitor) that check that a given |
|
1296 // value's type falls within a set of primitive types. |
|
1297 |
|
1298 class TypeCheckPrimitiveSetStub : public ICStub |
|
1299 { |
|
1300 friend class ICStubSpace; |
|
1301 protected: |
|
1302 inline static uint16_t TypeToFlag(JSValueType type) { |
|
1303 return 1u << static_cast<unsigned>(type); |
|
1304 } |
|
1305 |
|
1306 inline static uint16_t ValidFlags() { |
|
1307 return ((TypeToFlag(JSVAL_TYPE_OBJECT) << 1) - 1) & ~TypeToFlag(JSVAL_TYPE_MAGIC); |
|
1308 } |
|
1309 |
|
1310 TypeCheckPrimitiveSetStub(Kind kind, JitCode *stubCode, uint16_t flags) |
|
1311 : ICStub(kind, stubCode) |
|
1312 { |
|
1313 JS_ASSERT(kind == TypeMonitor_PrimitiveSet || kind == TypeUpdate_PrimitiveSet); |
|
1314 JS_ASSERT(flags && !(flags & ~ValidFlags())); |
|
1315 extra_ = flags; |
|
1316 } |
|
1317 |
|
1318 TypeCheckPrimitiveSetStub *updateTypesAndCode(uint16_t flags, JitCode *code) { |
|
1319 JS_ASSERT(flags && !(flags & ~ValidFlags())); |
|
1320 if (!code) |
|
1321 return nullptr; |
|
1322 extra_ = flags; |
|
1323 updateCode(code); |
|
1324 return this; |
|
1325 } |
|
1326 |
|
1327 public: |
|
1328 uint16_t typeFlags() const { |
|
1329 return extra_; |
|
1330 } |
|
1331 |
|
1332 bool containsType(JSValueType type) const { |
|
1333 JS_ASSERT(type <= JSVAL_TYPE_OBJECT); |
|
1334 JS_ASSERT(type != JSVAL_TYPE_MAGIC); |
|
1335 return extra_ & TypeToFlag(type); |
|
1336 } |
|
1337 |
|
1338 ICTypeMonitor_PrimitiveSet *toMonitorStub() { |
|
1339 return toTypeMonitor_PrimitiveSet(); |
|
1340 } |
|
1341 |
|
1342 ICTypeUpdate_PrimitiveSet *toUpdateStub() { |
|
1343 return toTypeUpdate_PrimitiveSet(); |
|
1344 } |
|
1345 |
|
1346 class Compiler : public ICStubCompiler { |
|
1347 protected: |
|
1348 TypeCheckPrimitiveSetStub *existingStub_; |
|
1349 uint16_t flags_; |
|
1350 |
|
1351 virtual int32_t getKey() const { |
|
1352 return static_cast<int32_t>(kind) | (static_cast<int32_t>(flags_) << 16); |
|
1353 } |
|
1354 |
|
1355 public: |
|
1356 Compiler(JSContext *cx, Kind kind, TypeCheckPrimitiveSetStub *existingStub, |
|
1357 JSValueType type) |
|
1358 : ICStubCompiler(cx, kind), |
|
1359 existingStub_(existingStub), |
|
1360 flags_((existingStub ? existingStub->typeFlags() : 0) | TypeToFlag(type)) |
|
1361 { |
|
1362 JS_ASSERT_IF(existingStub_, flags_ != existingStub_->typeFlags()); |
|
1363 } |
|
1364 |
|
1365 TypeCheckPrimitiveSetStub *updateStub() { |
|
1366 JS_ASSERT(existingStub_); |
|
1367 return existingStub_->updateTypesAndCode(flags_, getStubCode()); |
|
1368 } |
|
1369 }; |
|
1370 }; |
|
1371 |
|
1372 // TypeMonitor |
|
1373 |
|
1374 // The TypeMonitor fallback stub is not always a regular fallback stub. When |
|
1375 // used for monitoring the values pushed by a bytecode it doesn't hold a |
|
1376 // pointer to the IC entry, but rather back to the main fallback stub for the |
|
1377 // IC (from which a pointer to the IC entry can be retrieved). When monitoring |
|
1378 // the types of 'this', arguments or other values with no associated IC, there |
|
1379 // is no main fallback stub, and the IC entry is referenced directly. |
|
1380 class ICTypeMonitor_Fallback : public ICStub |
|
1381 { |
|
1382 friend class ICStubSpace; |
|
1383 |
|
1384 static const uint32_t MAX_OPTIMIZED_STUBS = 8; |
|
1385 |
|
1386 // Pointer to the main fallback stub for the IC or to the main IC entry, |
|
1387 // depending on hasFallbackStub. |
|
1388 union { |
|
1389 ICMonitoredFallbackStub *mainFallbackStub_; |
|
1390 ICEntry *icEntry_; |
|
1391 }; |
|
1392 |
|
1393 // Pointer to the first monitor stub. |
|
1394 ICStub *firstMonitorStub_; |
|
1395 |
|
1396 // Address of the last monitor stub's field pointing to this |
|
1397 // fallback monitor stub. This will get updated when new |
|
1398 // monitor stubs are created and added. |
|
1399 ICStub **lastMonitorStubPtrAddr_; |
|
1400 |
|
1401 // Count of optimized type monitor stubs in this chain. |
|
1402 uint32_t numOptimizedMonitorStubs_ : 8; |
|
1403 |
|
1404 // Whether this has a fallback stub referring to the IC entry. |
|
1405 bool hasFallbackStub_ : 1; |
|
1406 |
|
1407 // Index of 'this' or argument which is being monitored, or BYTECODE_INDEX |
|
1408 // if this is monitoring the types of values pushed at some bytecode. |
|
1409 uint32_t argumentIndex_ : 23; |
|
1410 |
|
1411 static const uint32_t BYTECODE_INDEX = (1 << 23) - 1; |
|
1412 |
|
1413 ICTypeMonitor_Fallback(JitCode *stubCode, ICMonitoredFallbackStub *mainFallbackStub, |
|
1414 uint32_t argumentIndex) |
|
1415 : ICStub(ICStub::TypeMonitor_Fallback, stubCode), |
|
1416 mainFallbackStub_(mainFallbackStub), |
|
1417 firstMonitorStub_(thisFromCtor()), |
|
1418 lastMonitorStubPtrAddr_(nullptr), |
|
1419 numOptimizedMonitorStubs_(0), |
|
1420 hasFallbackStub_(mainFallbackStub != nullptr), |
|
1421 argumentIndex_(argumentIndex) |
|
1422 { } |
|
1423 |
|
1424 ICTypeMonitor_Fallback *thisFromCtor() { |
|
1425 return this; |
|
1426 } |
|
1427 |
|
1428 void addOptimizedMonitorStub(ICStub *stub) { |
|
1429 stub->setNext(this); |
|
1430 |
|
1431 JS_ASSERT((lastMonitorStubPtrAddr_ != nullptr) == |
|
1432 (numOptimizedMonitorStubs_ || !hasFallbackStub_)); |
|
1433 |
|
1434 if (lastMonitorStubPtrAddr_) |
|
1435 *lastMonitorStubPtrAddr_ = stub; |
|
1436 |
|
1437 if (numOptimizedMonitorStubs_ == 0) { |
|
1438 JS_ASSERT(firstMonitorStub_ == this); |
|
1439 firstMonitorStub_ = stub; |
|
1440 } else { |
|
1441 JS_ASSERT(firstMonitorStub_ != nullptr); |
|
1442 } |
|
1443 |
|
1444 lastMonitorStubPtrAddr_ = stub->addressOfNext(); |
|
1445 numOptimizedMonitorStubs_++; |
|
1446 } |
|
1447 |
|
1448 public: |
|
1449 static inline ICTypeMonitor_Fallback *New( |
|
1450 ICStubSpace *space, JitCode *code, ICMonitoredFallbackStub *mainFbStub, |
|
1451 uint32_t argumentIndex) |
|
1452 { |
|
1453 if (!code) |
|
1454 return nullptr; |
|
1455 return space->allocate<ICTypeMonitor_Fallback>(code, mainFbStub, argumentIndex); |
|
1456 } |
|
1457 |
|
1458 bool hasStub(ICStub::Kind kind) { |
|
1459 ICStub *stub = firstMonitorStub_; |
|
1460 do { |
|
1461 if (stub->kind() == kind) |
|
1462 return true; |
|
1463 |
|
1464 stub = stub->next(); |
|
1465 } while (stub); |
|
1466 |
|
1467 return false; |
|
1468 } |
|
1469 |
|
1470 inline ICFallbackStub *mainFallbackStub() const { |
|
1471 JS_ASSERT(hasFallbackStub_); |
|
1472 return mainFallbackStub_; |
|
1473 } |
|
1474 |
|
1475 inline ICEntry *icEntry() const { |
|
1476 return hasFallbackStub_ ? mainFallbackStub()->icEntry() : icEntry_; |
|
1477 } |
|
1478 |
|
1479 inline ICStub *firstMonitorStub() const { |
|
1480 return firstMonitorStub_; |
|
1481 } |
|
1482 |
|
1483 static inline size_t offsetOfFirstMonitorStub() { |
|
1484 return offsetof(ICTypeMonitor_Fallback, firstMonitorStub_); |
|
1485 } |
|
1486 |
|
1487 inline uint32_t numOptimizedMonitorStubs() const { |
|
1488 return numOptimizedMonitorStubs_; |
|
1489 } |
|
1490 |
|
1491 inline bool monitorsThis() const { |
|
1492 return argumentIndex_ == 0; |
|
1493 } |
|
1494 |
|
1495 inline bool monitorsArgument(uint32_t *pargument) const { |
|
1496 if (argumentIndex_ > 0 && argumentIndex_ < BYTECODE_INDEX) { |
|
1497 *pargument = argumentIndex_ - 1; |
|
1498 return true; |
|
1499 } |
|
1500 return false; |
|
1501 } |
|
1502 |
|
1503 inline bool monitorsBytecode() const { |
|
1504 return argumentIndex_ == BYTECODE_INDEX; |
|
1505 } |
|
1506 |
|
1507 // Fixup the IC entry as for a normal fallback stub, for this/arguments. |
|
1508 void fixupICEntry(ICEntry *icEntry) { |
|
1509 JS_ASSERT(!hasFallbackStub_); |
|
1510 JS_ASSERT(icEntry_ == nullptr); |
|
1511 JS_ASSERT(lastMonitorStubPtrAddr_ == nullptr); |
|
1512 icEntry_ = icEntry; |
|
1513 lastMonitorStubPtrAddr_ = icEntry_->addressOfFirstStub(); |
|
1514 } |
|
1515 |
|
1516 // Create a new monitor stub for the type of the given value, and |
|
1517 // add it to this chain. |
|
1518 bool addMonitorStubForValue(JSContext *cx, JSScript *script, HandleValue val); |
|
1519 |
|
1520 void resetMonitorStubChain(Zone *zone); |
|
1521 |
|
1522 // Compiler for this stub kind. |
|
1523 class Compiler : public ICStubCompiler { |
|
1524 ICMonitoredFallbackStub *mainFallbackStub_; |
|
1525 uint32_t argumentIndex_; |
|
1526 |
|
1527 protected: |
|
1528 bool generateStubCode(MacroAssembler &masm); |
|
1529 |
|
1530 public: |
|
1531 Compiler(JSContext *cx, ICMonitoredFallbackStub *mainFallbackStub) |
|
1532 : ICStubCompiler(cx, ICStub::TypeMonitor_Fallback), |
|
1533 mainFallbackStub_(mainFallbackStub), |
|
1534 argumentIndex_(BYTECODE_INDEX) |
|
1535 { } |
|
1536 |
|
1537 Compiler(JSContext *cx, uint32_t argumentIndex) |
|
1538 : ICStubCompiler(cx, ICStub::TypeMonitor_Fallback), |
|
1539 mainFallbackStub_(nullptr), |
|
1540 argumentIndex_(argumentIndex) |
|
1541 { } |
|
1542 |
|
1543 ICTypeMonitor_Fallback *getStub(ICStubSpace *space) { |
|
1544 return ICTypeMonitor_Fallback::New(space, getStubCode(), mainFallbackStub_, |
|
1545 argumentIndex_); |
|
1546 } |
|
1547 }; |
|
1548 }; |
|
1549 |
|
1550 class ICTypeMonitor_PrimitiveSet : public TypeCheckPrimitiveSetStub |
|
1551 { |
|
1552 friend class ICStubSpace; |
|
1553 |
|
1554 ICTypeMonitor_PrimitiveSet(JitCode *stubCode, uint16_t flags) |
|
1555 : TypeCheckPrimitiveSetStub(TypeMonitor_PrimitiveSet, stubCode, flags) |
|
1556 {} |
|
1557 |
|
1558 public: |
|
1559 static inline ICTypeMonitor_PrimitiveSet *New(ICStubSpace *space, JitCode *code, |
|
1560 uint16_t flags) |
|
1561 { |
|
1562 if (!code) |
|
1563 return nullptr; |
|
1564 return space->allocate<ICTypeMonitor_PrimitiveSet>(code, flags); |
|
1565 } |
|
1566 |
|
1567 class Compiler : public TypeCheckPrimitiveSetStub::Compiler { |
|
1568 protected: |
|
1569 bool generateStubCode(MacroAssembler &masm); |
|
1570 |
|
1571 public: |
|
1572 Compiler(JSContext *cx, ICTypeMonitor_PrimitiveSet *existingStub, JSValueType type) |
|
1573 : TypeCheckPrimitiveSetStub::Compiler(cx, TypeMonitor_PrimitiveSet, existingStub, type) |
|
1574 {} |
|
1575 |
|
1576 ICTypeMonitor_PrimitiveSet *updateStub() { |
|
1577 TypeCheckPrimitiveSetStub *stub = |
|
1578 this->TypeCheckPrimitiveSetStub::Compiler::updateStub(); |
|
1579 if (!stub) |
|
1580 return nullptr; |
|
1581 return stub->toMonitorStub(); |
|
1582 } |
|
1583 |
|
1584 ICTypeMonitor_PrimitiveSet *getStub(ICStubSpace *space) { |
|
1585 JS_ASSERT(!existingStub_); |
|
1586 return ICTypeMonitor_PrimitiveSet::New(space, getStubCode(), flags_); |
|
1587 } |
|
1588 }; |
|
1589 }; |
|
1590 |
|
1591 class ICTypeMonitor_SingleObject : public ICStub |
|
1592 { |
|
1593 friend class ICStubSpace; |
|
1594 |
|
1595 HeapPtrObject obj_; |
|
1596 |
|
1597 ICTypeMonitor_SingleObject(JitCode *stubCode, HandleObject obj); |
|
1598 |
|
1599 public: |
|
1600 static inline ICTypeMonitor_SingleObject *New( |
|
1601 ICStubSpace *space, JitCode *code, HandleObject obj) |
|
1602 { |
|
1603 if (!code) |
|
1604 return nullptr; |
|
1605 return space->allocate<ICTypeMonitor_SingleObject>(code, obj); |
|
1606 } |
|
1607 |
|
1608 HeapPtrObject &object() { |
|
1609 return obj_; |
|
1610 } |
|
1611 |
|
1612 static size_t offsetOfObject() { |
|
1613 return offsetof(ICTypeMonitor_SingleObject, obj_); |
|
1614 } |
|
1615 |
|
1616 class Compiler : public ICStubCompiler { |
|
1617 protected: |
|
1618 HandleObject obj_; |
|
1619 bool generateStubCode(MacroAssembler &masm); |
|
1620 |
|
1621 public: |
|
1622 Compiler(JSContext *cx, HandleObject obj) |
|
1623 : ICStubCompiler(cx, TypeMonitor_SingleObject), |
|
1624 obj_(obj) |
|
1625 { } |
|
1626 |
|
1627 ICTypeMonitor_SingleObject *getStub(ICStubSpace *space) { |
|
1628 return ICTypeMonitor_SingleObject::New(space, getStubCode(), obj_); |
|
1629 } |
|
1630 }; |
|
1631 }; |
|
1632 |
|
1633 class ICTypeMonitor_TypeObject : public ICStub |
|
1634 { |
|
1635 friend class ICStubSpace; |
|
1636 |
|
1637 HeapPtrTypeObject type_; |
|
1638 |
|
1639 ICTypeMonitor_TypeObject(JitCode *stubCode, HandleTypeObject type); |
|
1640 |
|
1641 public: |
|
1642 static inline ICTypeMonitor_TypeObject *New( |
|
1643 ICStubSpace *space, JitCode *code, HandleTypeObject type) |
|
1644 { |
|
1645 if (!code) |
|
1646 return nullptr; |
|
1647 return space->allocate<ICTypeMonitor_TypeObject>(code, type); |
|
1648 } |
|
1649 |
|
1650 HeapPtrTypeObject &type() { |
|
1651 return type_; |
|
1652 } |
|
1653 |
|
1654 static size_t offsetOfType() { |
|
1655 return offsetof(ICTypeMonitor_TypeObject, type_); |
|
1656 } |
|
1657 |
|
1658 class Compiler : public ICStubCompiler { |
|
1659 protected: |
|
1660 HandleTypeObject type_; |
|
1661 bool generateStubCode(MacroAssembler &masm); |
|
1662 |
|
1663 public: |
|
1664 Compiler(JSContext *cx, HandleTypeObject type) |
|
1665 : ICStubCompiler(cx, TypeMonitor_TypeObject), |
|
1666 type_(type) |
|
1667 { } |
|
1668 |
|
1669 ICTypeMonitor_TypeObject *getStub(ICStubSpace *space) { |
|
1670 return ICTypeMonitor_TypeObject::New(space, getStubCode(), type_); |
|
1671 } |
|
1672 }; |
|
1673 }; |
|
1674 |
|
1675 // TypeUpdate |
|
1676 |
|
1677 extern const VMFunction DoTypeUpdateFallbackInfo; |
|
1678 |
|
1679 // The TypeUpdate fallback is not a regular fallback, since it just |
|
1680 // forwards to a different entry point in the main fallback stub. |
|
1681 class ICTypeUpdate_Fallback : public ICStub |
|
1682 { |
|
1683 friend class ICStubSpace; |
|
1684 |
|
1685 ICTypeUpdate_Fallback(JitCode *stubCode) |
|
1686 : ICStub(ICStub::TypeUpdate_Fallback, stubCode) |
|
1687 {} |
|
1688 |
|
1689 public: |
|
1690 static inline ICTypeUpdate_Fallback *New(ICStubSpace *space, JitCode *code) { |
|
1691 if (!code) |
|
1692 return nullptr; |
|
1693 return space->allocate<ICTypeUpdate_Fallback>(code); |
|
1694 } |
|
1695 |
|
1696 // Compiler for this stub kind. |
|
1697 class Compiler : public ICStubCompiler { |
|
1698 protected: |
|
1699 bool generateStubCode(MacroAssembler &masm); |
|
1700 |
|
1701 public: |
|
1702 Compiler(JSContext *cx) |
|
1703 : ICStubCompiler(cx, ICStub::TypeUpdate_Fallback) |
|
1704 { } |
|
1705 |
|
1706 ICTypeUpdate_Fallback *getStub(ICStubSpace *space) { |
|
1707 return ICTypeUpdate_Fallback::New(space, getStubCode()); |
|
1708 } |
|
1709 }; |
|
1710 }; |
|
1711 |
|
1712 class ICTypeUpdate_PrimitiveSet : public TypeCheckPrimitiveSetStub |
|
1713 { |
|
1714 friend class ICStubSpace; |
|
1715 |
|
1716 ICTypeUpdate_PrimitiveSet(JitCode *stubCode, uint16_t flags) |
|
1717 : TypeCheckPrimitiveSetStub(TypeUpdate_PrimitiveSet, stubCode, flags) |
|
1718 {} |
|
1719 |
|
1720 public: |
|
1721 static inline ICTypeUpdate_PrimitiveSet *New(ICStubSpace *space, JitCode *code, |
|
1722 uint16_t flags) |
|
1723 { |
|
1724 if (!code) |
|
1725 return nullptr; |
|
1726 return space->allocate<ICTypeUpdate_PrimitiveSet>(code, flags); |
|
1727 } |
|
1728 |
|
1729 class Compiler : public TypeCheckPrimitiveSetStub::Compiler { |
|
1730 protected: |
|
1731 bool generateStubCode(MacroAssembler &masm); |
|
1732 |
|
1733 public: |
|
1734 Compiler(JSContext *cx, ICTypeUpdate_PrimitiveSet *existingStub, JSValueType type) |
|
1735 : TypeCheckPrimitiveSetStub::Compiler(cx, TypeUpdate_PrimitiveSet, existingStub, type) |
|
1736 {} |
|
1737 |
|
1738 ICTypeUpdate_PrimitiveSet *updateStub() { |
|
1739 TypeCheckPrimitiveSetStub *stub = |
|
1740 this->TypeCheckPrimitiveSetStub::Compiler::updateStub(); |
|
1741 if (!stub) |
|
1742 return nullptr; |
|
1743 return stub->toUpdateStub(); |
|
1744 } |
|
1745 |
|
1746 ICTypeUpdate_PrimitiveSet *getStub(ICStubSpace *space) { |
|
1747 JS_ASSERT(!existingStub_); |
|
1748 return ICTypeUpdate_PrimitiveSet::New(space, getStubCode(), flags_); |
|
1749 } |
|
1750 }; |
|
1751 }; |
|
1752 |
|
1753 // Type update stub to handle a singleton object. |
|
1754 class ICTypeUpdate_SingleObject : public ICStub |
|
1755 { |
|
1756 friend class ICStubSpace; |
|
1757 |
|
1758 HeapPtrObject obj_; |
|
1759 |
|
1760 ICTypeUpdate_SingleObject(JitCode *stubCode, HandleObject obj); |
|
1761 |
|
1762 public: |
|
1763 static inline ICTypeUpdate_SingleObject *New(ICStubSpace *space, JitCode *code, |
|
1764 HandleObject obj) |
|
1765 { |
|
1766 if (!code) |
|
1767 return nullptr; |
|
1768 return space->allocate<ICTypeUpdate_SingleObject>(code, obj); |
|
1769 } |
|
1770 |
|
1771 HeapPtrObject &object() { |
|
1772 return obj_; |
|
1773 } |
|
1774 |
|
1775 static size_t offsetOfObject() { |
|
1776 return offsetof(ICTypeUpdate_SingleObject, obj_); |
|
1777 } |
|
1778 |
|
1779 class Compiler : public ICStubCompiler { |
|
1780 protected: |
|
1781 HandleObject obj_; |
|
1782 bool generateStubCode(MacroAssembler &masm); |
|
1783 |
|
1784 public: |
|
1785 Compiler(JSContext *cx, HandleObject obj) |
|
1786 : ICStubCompiler(cx, TypeUpdate_SingleObject), |
|
1787 obj_(obj) |
|
1788 { } |
|
1789 |
|
1790 ICTypeUpdate_SingleObject *getStub(ICStubSpace *space) { |
|
1791 return ICTypeUpdate_SingleObject::New(space, getStubCode(), obj_); |
|
1792 } |
|
1793 }; |
|
1794 }; |
|
1795 |
|
1796 // Type update stub to handle a single TypeObject. |
|
1797 class ICTypeUpdate_TypeObject : public ICStub |
|
1798 { |
|
1799 friend class ICStubSpace; |
|
1800 |
|
1801 HeapPtrTypeObject type_; |
|
1802 |
|
1803 ICTypeUpdate_TypeObject(JitCode *stubCode, HandleTypeObject type); |
|
1804 |
|
1805 public: |
|
1806 static inline ICTypeUpdate_TypeObject *New(ICStubSpace *space, JitCode *code, |
|
1807 HandleTypeObject type) |
|
1808 { |
|
1809 if (!code) |
|
1810 return nullptr; |
|
1811 return space->allocate<ICTypeUpdate_TypeObject>(code, type); |
|
1812 } |
|
1813 |
|
1814 HeapPtrTypeObject &type() { |
|
1815 return type_; |
|
1816 } |
|
1817 |
|
1818 static size_t offsetOfType() { |
|
1819 return offsetof(ICTypeUpdate_TypeObject, type_); |
|
1820 } |
|
1821 |
|
1822 class Compiler : public ICStubCompiler { |
|
1823 protected: |
|
1824 HandleTypeObject type_; |
|
1825 bool generateStubCode(MacroAssembler &masm); |
|
1826 |
|
1827 public: |
|
1828 Compiler(JSContext *cx, HandleTypeObject type) |
|
1829 : ICStubCompiler(cx, TypeUpdate_TypeObject), |
|
1830 type_(type) |
|
1831 { } |
|
1832 |
|
1833 ICTypeUpdate_TypeObject *getStub(ICStubSpace *space) { |
|
1834 return ICTypeUpdate_TypeObject::New(space, getStubCode(), type_); |
|
1835 } |
|
1836 }; |
|
1837 }; |
|
1838 |
|
1839 // This |
|
1840 // JSOP_THIS |
|
1841 |
|
1842 class ICThis_Fallback : public ICFallbackStub |
|
1843 { |
|
1844 friend class ICStubSpace; |
|
1845 |
|
1846 ICThis_Fallback(JitCode *stubCode) |
|
1847 : ICFallbackStub(ICStub::This_Fallback, stubCode) {} |
|
1848 |
|
1849 public: |
|
1850 static inline ICThis_Fallback *New(ICStubSpace *space, JitCode *code) { |
|
1851 if (!code) |
|
1852 return nullptr; |
|
1853 return space->allocate<ICThis_Fallback>(code); |
|
1854 } |
|
1855 |
|
1856 // Compiler for this stub kind. |
|
1857 class Compiler : public ICStubCompiler { |
|
1858 protected: |
|
1859 bool generateStubCode(MacroAssembler &masm); |
|
1860 |
|
1861 public: |
|
1862 Compiler(JSContext *cx) |
|
1863 : ICStubCompiler(cx, ICStub::This_Fallback) {} |
|
1864 |
|
1865 ICStub *getStub(ICStubSpace *space) { |
|
1866 return ICThis_Fallback::New(space, getStubCode()); |
|
1867 } |
|
1868 }; |
|
1869 }; |
|
1870 |
|
1871 class ICNewArray_Fallback : public ICFallbackStub |
|
1872 { |
|
1873 friend class ICStubSpace; |
|
1874 |
|
1875 HeapPtrObject templateObject_; |
|
1876 |
|
1877 ICNewArray_Fallback(JitCode *stubCode, JSObject *templateObject) |
|
1878 : ICFallbackStub(ICStub::NewArray_Fallback, stubCode), templateObject_(templateObject) |
|
1879 {} |
|
1880 |
|
1881 public: |
|
1882 static inline ICNewArray_Fallback *New(ICStubSpace *space, JitCode *code, |
|
1883 JSObject *templateObject) { |
|
1884 if (!code) |
|
1885 return nullptr; |
|
1886 return space->allocate<ICNewArray_Fallback>(code, templateObject); |
|
1887 } |
|
1888 |
|
1889 class Compiler : public ICStubCompiler { |
|
1890 RootedObject templateObject; |
|
1891 bool generateStubCode(MacroAssembler &masm); |
|
1892 |
|
1893 public: |
|
1894 Compiler(JSContext *cx, JSObject *templateObject) |
|
1895 : ICStubCompiler(cx, ICStub::NewArray_Fallback), |
|
1896 templateObject(cx, templateObject) |
|
1897 {} |
|
1898 |
|
1899 ICStub *getStub(ICStubSpace *space) { |
|
1900 return ICNewArray_Fallback::New(space, getStubCode(), templateObject); |
|
1901 } |
|
1902 }; |
|
1903 |
|
1904 HeapPtrObject &templateObject() { |
|
1905 return templateObject_; |
|
1906 } |
|
1907 }; |
|
1908 |
|
1909 class ICNewObject_Fallback : public ICFallbackStub |
|
1910 { |
|
1911 friend class ICStubSpace; |
|
1912 |
|
1913 HeapPtrObject templateObject_; |
|
1914 |
|
1915 ICNewObject_Fallback(JitCode *stubCode, JSObject *templateObject) |
|
1916 : ICFallbackStub(ICStub::NewObject_Fallback, stubCode), templateObject_(templateObject) |
|
1917 {} |
|
1918 |
|
1919 public: |
|
1920 static inline ICNewObject_Fallback *New(ICStubSpace *space, JitCode *code, |
|
1921 JSObject *templateObject) { |
|
1922 if (!code) |
|
1923 return nullptr; |
|
1924 return space->allocate<ICNewObject_Fallback>(code, templateObject); |
|
1925 } |
|
1926 |
|
1927 class Compiler : public ICStubCompiler { |
|
1928 RootedObject templateObject; |
|
1929 bool generateStubCode(MacroAssembler &masm); |
|
1930 |
|
1931 public: |
|
1932 Compiler(JSContext *cx, JSObject *templateObject) |
|
1933 : ICStubCompiler(cx, ICStub::NewObject_Fallback), |
|
1934 templateObject(cx, templateObject) |
|
1935 {} |
|
1936 |
|
1937 ICStub *getStub(ICStubSpace *space) { |
|
1938 return ICNewObject_Fallback::New(space, getStubCode(), templateObject); |
|
1939 } |
|
1940 }; |
|
1941 |
|
1942 HeapPtrObject &templateObject() { |
|
1943 return templateObject_; |
|
1944 } |
|
1945 }; |
|
1946 |
|
1947 // Compare |
|
1948 // JSOP_LT |
|
1949 // JSOP_GT |
|
1950 |
|
1951 class ICCompare_Fallback : public ICFallbackStub |
|
1952 { |
|
1953 friend class ICStubSpace; |
|
1954 |
|
1955 ICCompare_Fallback(JitCode *stubCode) |
|
1956 : ICFallbackStub(ICStub::Compare_Fallback, stubCode) {} |
|
1957 |
|
1958 public: |
|
1959 static const uint32_t MAX_OPTIMIZED_STUBS = 8; |
|
1960 |
|
1961 static inline ICCompare_Fallback *New(ICStubSpace *space, JitCode *code) { |
|
1962 if (!code) |
|
1963 return nullptr; |
|
1964 return space->allocate<ICCompare_Fallback>(code); |
|
1965 } |
|
1966 |
|
1967 // Compiler for this stub kind. |
|
1968 class Compiler : public ICStubCompiler { |
|
1969 protected: |
|
1970 bool generateStubCode(MacroAssembler &masm); |
|
1971 |
|
1972 public: |
|
1973 Compiler(JSContext *cx) |
|
1974 : ICStubCompiler(cx, ICStub::Compare_Fallback) {} |
|
1975 |
|
1976 ICStub *getStub(ICStubSpace *space) { |
|
1977 return ICCompare_Fallback::New(space, getStubCode()); |
|
1978 } |
|
1979 }; |
|
1980 }; |
|
1981 |
|
1982 class ICCompare_Int32 : public ICStub |
|
1983 { |
|
1984 friend class ICStubSpace; |
|
1985 |
|
1986 ICCompare_Int32(JitCode *stubCode) |
|
1987 : ICStub(ICStub::Compare_Int32, stubCode) {} |
|
1988 |
|
1989 public: |
|
1990 static inline ICCompare_Int32 *New(ICStubSpace *space, JitCode *code) { |
|
1991 if (!code) |
|
1992 return nullptr; |
|
1993 return space->allocate<ICCompare_Int32>(code); |
|
1994 } |
|
1995 |
|
1996 // Compiler for this stub kind. |
|
1997 class Compiler : public ICMultiStubCompiler { |
|
1998 protected: |
|
1999 bool generateStubCode(MacroAssembler &masm); |
|
2000 |
|
2001 public: |
|
2002 Compiler(JSContext *cx, JSOp op) |
|
2003 : ICMultiStubCompiler(cx, ICStub::Compare_Int32, op) {} |
|
2004 |
|
2005 ICStub *getStub(ICStubSpace *space) { |
|
2006 return ICCompare_Int32::New(space, getStubCode()); |
|
2007 } |
|
2008 }; |
|
2009 }; |
|
2010 |
|
2011 class ICCompare_Double : public ICStub |
|
2012 { |
|
2013 friend class ICStubSpace; |
|
2014 |
|
2015 ICCompare_Double(JitCode *stubCode) |
|
2016 : ICStub(ICStub::Compare_Double, stubCode) |
|
2017 {} |
|
2018 |
|
2019 public: |
|
2020 static inline ICCompare_Double *New(ICStubSpace *space, JitCode *code) { |
|
2021 if (!code) |
|
2022 return nullptr; |
|
2023 return space->allocate<ICCompare_Double>(code); |
|
2024 } |
|
2025 |
|
2026 class Compiler : public ICMultiStubCompiler { |
|
2027 protected: |
|
2028 bool generateStubCode(MacroAssembler &masm); |
|
2029 |
|
2030 public: |
|
2031 Compiler(JSContext *cx, JSOp op) |
|
2032 : ICMultiStubCompiler(cx, ICStub::Compare_Double, op) |
|
2033 {} |
|
2034 |
|
2035 ICStub *getStub(ICStubSpace *space) { |
|
2036 return ICCompare_Double::New(space, getStubCode()); |
|
2037 } |
|
2038 }; |
|
2039 }; |
|
2040 |
|
2041 class ICCompare_NumberWithUndefined : public ICStub |
|
2042 { |
|
2043 friend class ICStubSpace; |
|
2044 |
|
2045 ICCompare_NumberWithUndefined(JitCode *stubCode, bool lhsIsUndefined) |
|
2046 : ICStub(ICStub::Compare_NumberWithUndefined, stubCode) |
|
2047 { |
|
2048 extra_ = lhsIsUndefined; |
|
2049 } |
|
2050 |
|
2051 public: |
|
2052 static inline ICCompare_NumberWithUndefined *New(ICStubSpace *space, JitCode *code, bool lhsIsUndefined) { |
|
2053 if (!code) |
|
2054 return nullptr; |
|
2055 return space->allocate<ICCompare_NumberWithUndefined>(code, lhsIsUndefined); |
|
2056 } |
|
2057 |
|
2058 bool lhsIsUndefined() { |
|
2059 return extra_; |
|
2060 } |
|
2061 |
|
2062 class Compiler : public ICMultiStubCompiler { |
|
2063 protected: |
|
2064 bool generateStubCode(MacroAssembler &masm); |
|
2065 |
|
2066 bool lhsIsUndefined; |
|
2067 |
|
2068 public: |
|
2069 Compiler(JSContext *cx, JSOp op, bool lhsIsUndefined) |
|
2070 : ICMultiStubCompiler(cx, ICStub::Compare_NumberWithUndefined, op), |
|
2071 lhsIsUndefined(lhsIsUndefined) |
|
2072 {} |
|
2073 |
|
2074 virtual int32_t getKey() const { |
|
2075 return static_cast<int32_t>(kind) |
|
2076 | (static_cast<int32_t>(op) << 16) |
|
2077 | (static_cast<int32_t>(lhsIsUndefined) << 24); |
|
2078 } |
|
2079 |
|
2080 ICStub *getStub(ICStubSpace *space) { |
|
2081 return ICCompare_NumberWithUndefined::New(space, getStubCode(), lhsIsUndefined); |
|
2082 } |
|
2083 }; |
|
2084 }; |
|
2085 |
|
2086 class ICCompare_String : public ICStub |
|
2087 { |
|
2088 friend class ICStubSpace; |
|
2089 |
|
2090 ICCompare_String(JitCode *stubCode) |
|
2091 : ICStub(ICStub::Compare_String, stubCode) |
|
2092 {} |
|
2093 |
|
2094 public: |
|
2095 static inline ICCompare_String *New(ICStubSpace *space, JitCode *code) { |
|
2096 if (!code) |
|
2097 return nullptr; |
|
2098 return space->allocate<ICCompare_String>(code); |
|
2099 } |
|
2100 |
|
2101 class Compiler : public ICMultiStubCompiler { |
|
2102 protected: |
|
2103 bool generateStubCode(MacroAssembler &masm); |
|
2104 |
|
2105 public: |
|
2106 Compiler(JSContext *cx, JSOp op) |
|
2107 : ICMultiStubCompiler(cx, ICStub::Compare_String, op) |
|
2108 {} |
|
2109 |
|
2110 ICStub *getStub(ICStubSpace *space) { |
|
2111 return ICCompare_String::New(space, getStubCode()); |
|
2112 } |
|
2113 }; |
|
2114 }; |
|
2115 |
|
2116 class ICCompare_Boolean : public ICStub |
|
2117 { |
|
2118 friend class ICStubSpace; |
|
2119 |
|
2120 ICCompare_Boolean(JitCode *stubCode) |
|
2121 : ICStub(ICStub::Compare_Boolean, stubCode) |
|
2122 {} |
|
2123 |
|
2124 public: |
|
2125 static inline ICCompare_Boolean *New(ICStubSpace *space, JitCode *code) { |
|
2126 if (!code) |
|
2127 return nullptr; |
|
2128 return space->allocate<ICCompare_Boolean>(code); |
|
2129 } |
|
2130 |
|
2131 class Compiler : public ICMultiStubCompiler { |
|
2132 protected: |
|
2133 bool generateStubCode(MacroAssembler &masm); |
|
2134 |
|
2135 public: |
|
2136 Compiler(JSContext *cx, JSOp op) |
|
2137 : ICMultiStubCompiler(cx, ICStub::Compare_Boolean, op) |
|
2138 {} |
|
2139 |
|
2140 ICStub *getStub(ICStubSpace *space) { |
|
2141 return ICCompare_Boolean::New(space, getStubCode()); |
|
2142 } |
|
2143 }; |
|
2144 }; |
|
2145 |
|
2146 class ICCompare_Object : public ICStub |
|
2147 { |
|
2148 friend class ICStubSpace; |
|
2149 |
|
2150 ICCompare_Object(JitCode *stubCode) |
|
2151 : ICStub(ICStub::Compare_Object, stubCode) |
|
2152 {} |
|
2153 |
|
2154 public: |
|
2155 static inline ICCompare_Object *New(ICStubSpace *space, JitCode *code) { |
|
2156 if (!code) |
|
2157 return nullptr; |
|
2158 return space->allocate<ICCompare_Object>(code); |
|
2159 } |
|
2160 |
|
2161 class Compiler : public ICMultiStubCompiler { |
|
2162 protected: |
|
2163 bool generateStubCode(MacroAssembler &masm); |
|
2164 |
|
2165 public: |
|
2166 Compiler(JSContext *cx, JSOp op) |
|
2167 : ICMultiStubCompiler(cx, ICStub::Compare_Object, op) |
|
2168 {} |
|
2169 |
|
2170 ICStub *getStub(ICStubSpace *space) { |
|
2171 return ICCompare_Object::New(space, getStubCode()); |
|
2172 } |
|
2173 }; |
|
2174 }; |
|
2175 |
|
2176 class ICCompare_ObjectWithUndefined : public ICStub |
|
2177 { |
|
2178 friend class ICStubSpace; |
|
2179 |
|
2180 ICCompare_ObjectWithUndefined(JitCode *stubCode) |
|
2181 : ICStub(ICStub::Compare_ObjectWithUndefined, stubCode) |
|
2182 {} |
|
2183 |
|
2184 public: |
|
2185 static inline ICCompare_ObjectWithUndefined *New(ICStubSpace *space, JitCode *code) { |
|
2186 if (!code) |
|
2187 return nullptr; |
|
2188 return space->allocate<ICCompare_ObjectWithUndefined>(code); |
|
2189 } |
|
2190 |
|
2191 class Compiler : public ICMultiStubCompiler { |
|
2192 protected: |
|
2193 bool generateStubCode(MacroAssembler &masm); |
|
2194 |
|
2195 bool lhsIsUndefined; |
|
2196 bool compareWithNull; |
|
2197 |
|
2198 public: |
|
2199 Compiler(JSContext *cx, JSOp op, bool lhsIsUndefined, bool compareWithNull) |
|
2200 : ICMultiStubCompiler(cx, ICStub::Compare_ObjectWithUndefined, op), |
|
2201 lhsIsUndefined(lhsIsUndefined), |
|
2202 compareWithNull(compareWithNull) |
|
2203 {} |
|
2204 |
|
2205 virtual int32_t getKey() const { |
|
2206 return static_cast<int32_t>(kind) |
|
2207 | (static_cast<int32_t>(op) << 16) |
|
2208 | (static_cast<int32_t>(lhsIsUndefined) << 24) |
|
2209 | (static_cast<int32_t>(compareWithNull) << 25); |
|
2210 } |
|
2211 |
|
2212 ICStub *getStub(ICStubSpace *space) { |
|
2213 return ICCompare_ObjectWithUndefined::New(space, getStubCode()); |
|
2214 } |
|
2215 }; |
|
2216 }; |
|
2217 |
|
2218 class ICCompare_Int32WithBoolean : public ICStub |
|
2219 { |
|
2220 friend class ICStubSpace; |
|
2221 |
|
2222 ICCompare_Int32WithBoolean(JitCode *stubCode, bool lhsIsInt32) |
|
2223 : ICStub(ICStub::Compare_Int32WithBoolean, stubCode) |
|
2224 { |
|
2225 extra_ = lhsIsInt32; |
|
2226 } |
|
2227 |
|
2228 public: |
|
2229 static inline ICCompare_Int32WithBoolean *New(ICStubSpace *space, JitCode *code, |
|
2230 bool lhsIsInt32) |
|
2231 { |
|
2232 if (!code) |
|
2233 return nullptr; |
|
2234 return space->allocate<ICCompare_Int32WithBoolean>(code, lhsIsInt32); |
|
2235 } |
|
2236 |
|
2237 bool lhsIsInt32() const { |
|
2238 return extra_; |
|
2239 } |
|
2240 |
|
2241 // Compiler for this stub kind. |
|
2242 class Compiler : public ICStubCompiler { |
|
2243 protected: |
|
2244 JSOp op_; |
|
2245 bool lhsIsInt32_; |
|
2246 bool generateStubCode(MacroAssembler &masm); |
|
2247 |
|
2248 virtual int32_t getKey() const { |
|
2249 return (static_cast<int32_t>(kind) | (static_cast<int32_t>(op_) << 16) | |
|
2250 (static_cast<int32_t>(lhsIsInt32_) << 24)); |
|
2251 } |
|
2252 |
|
2253 public: |
|
2254 Compiler(JSContext *cx, JSOp op, bool lhsIsInt32) |
|
2255 : ICStubCompiler(cx, ICStub::Compare_Int32WithBoolean), |
|
2256 op_(op), |
|
2257 lhsIsInt32_(lhsIsInt32) |
|
2258 {} |
|
2259 |
|
2260 ICStub *getStub(ICStubSpace *space) { |
|
2261 return ICCompare_Int32WithBoolean::New(space, getStubCode(), lhsIsInt32_); |
|
2262 } |
|
2263 }; |
|
2264 }; |
|
2265 |
|
2266 // ToBool |
|
2267 // JSOP_IFNE |
|
2268 |
|
2269 class ICToBool_Fallback : public ICFallbackStub |
|
2270 { |
|
2271 friend class ICStubSpace; |
|
2272 |
|
2273 ICToBool_Fallback(JitCode *stubCode) |
|
2274 : ICFallbackStub(ICStub::ToBool_Fallback, stubCode) {} |
|
2275 |
|
2276 public: |
|
2277 static const uint32_t MAX_OPTIMIZED_STUBS = 8; |
|
2278 |
|
2279 static inline ICToBool_Fallback *New(ICStubSpace *space, JitCode *code) { |
|
2280 if (!code) |
|
2281 return nullptr; |
|
2282 return space->allocate<ICToBool_Fallback>(code); |
|
2283 } |
|
2284 |
|
2285 // Compiler for this stub kind. |
|
2286 class Compiler : public ICStubCompiler { |
|
2287 protected: |
|
2288 bool generateStubCode(MacroAssembler &masm); |
|
2289 |
|
2290 public: |
|
2291 Compiler(JSContext *cx) |
|
2292 : ICStubCompiler(cx, ICStub::ToBool_Fallback) {} |
|
2293 |
|
2294 ICStub *getStub(ICStubSpace *space) { |
|
2295 return ICToBool_Fallback::New(space, getStubCode()); |
|
2296 } |
|
2297 }; |
|
2298 }; |
|
2299 |
|
2300 class ICToBool_Int32 : public ICStub |
|
2301 { |
|
2302 friend class ICStubSpace; |
|
2303 |
|
2304 ICToBool_Int32(JitCode *stubCode) |
|
2305 : ICStub(ICStub::ToBool_Int32, stubCode) {} |
|
2306 |
|
2307 public: |
|
2308 static inline ICToBool_Int32 *New(ICStubSpace *space, JitCode *code) { |
|
2309 if (!code) |
|
2310 return nullptr; |
|
2311 return space->allocate<ICToBool_Int32>(code); |
|
2312 } |
|
2313 |
|
2314 // Compiler for this stub kind. |
|
2315 class Compiler : public ICStubCompiler { |
|
2316 protected: |
|
2317 bool generateStubCode(MacroAssembler &masm); |
|
2318 |
|
2319 public: |
|
2320 Compiler(JSContext *cx) |
|
2321 : ICStubCompiler(cx, ICStub::ToBool_Int32) {} |
|
2322 |
|
2323 ICStub *getStub(ICStubSpace *space) { |
|
2324 return ICToBool_Int32::New(space, getStubCode()); |
|
2325 } |
|
2326 }; |
|
2327 }; |
|
2328 |
|
2329 class ICToBool_String : public ICStub |
|
2330 { |
|
2331 friend class ICStubSpace; |
|
2332 |
|
2333 ICToBool_String(JitCode *stubCode) |
|
2334 : ICStub(ICStub::ToBool_String, stubCode) {} |
|
2335 |
|
2336 public: |
|
2337 static inline ICToBool_String *New(ICStubSpace *space, JitCode *code) { |
|
2338 if (!code) |
|
2339 return nullptr; |
|
2340 return space->allocate<ICToBool_String>(code); |
|
2341 } |
|
2342 |
|
2343 // Compiler for this stub kind. |
|
2344 class Compiler : public ICStubCompiler { |
|
2345 protected: |
|
2346 bool generateStubCode(MacroAssembler &masm); |
|
2347 |
|
2348 public: |
|
2349 Compiler(JSContext *cx) |
|
2350 : ICStubCompiler(cx, ICStub::ToBool_String) {} |
|
2351 |
|
2352 ICStub *getStub(ICStubSpace *space) { |
|
2353 return ICToBool_String::New(space, getStubCode()); |
|
2354 } |
|
2355 }; |
|
2356 }; |
|
2357 |
|
2358 class ICToBool_NullUndefined : public ICStub |
|
2359 { |
|
2360 friend class ICStubSpace; |
|
2361 |
|
2362 ICToBool_NullUndefined(JitCode *stubCode) |
|
2363 : ICStub(ICStub::ToBool_NullUndefined, stubCode) {} |
|
2364 |
|
2365 public: |
|
2366 static inline ICToBool_NullUndefined *New(ICStubSpace *space, JitCode *code) { |
|
2367 if (!code) |
|
2368 return nullptr; |
|
2369 return space->allocate<ICToBool_NullUndefined>(code); |
|
2370 } |
|
2371 |
|
2372 // Compiler for this stub kind. |
|
2373 class Compiler : public ICStubCompiler { |
|
2374 protected: |
|
2375 bool generateStubCode(MacroAssembler &masm); |
|
2376 |
|
2377 public: |
|
2378 Compiler(JSContext *cx) |
|
2379 : ICStubCompiler(cx, ICStub::ToBool_NullUndefined) {} |
|
2380 |
|
2381 ICStub *getStub(ICStubSpace *space) { |
|
2382 return ICToBool_NullUndefined::New(space, getStubCode()); |
|
2383 } |
|
2384 }; |
|
2385 }; |
|
2386 |
|
2387 class ICToBool_Double : public ICStub |
|
2388 { |
|
2389 friend class ICStubSpace; |
|
2390 |
|
2391 ICToBool_Double(JitCode *stubCode) |
|
2392 : ICStub(ICStub::ToBool_Double, stubCode) {} |
|
2393 |
|
2394 public: |
|
2395 static inline ICToBool_Double *New(ICStubSpace *space, JitCode *code) { |
|
2396 if (!code) |
|
2397 return nullptr; |
|
2398 return space->allocate<ICToBool_Double>(code); |
|
2399 } |
|
2400 |
|
2401 // Compiler for this stub kind. |
|
2402 class Compiler : public ICStubCompiler { |
|
2403 protected: |
|
2404 bool generateStubCode(MacroAssembler &masm); |
|
2405 |
|
2406 public: |
|
2407 Compiler(JSContext *cx) |
|
2408 : ICStubCompiler(cx, ICStub::ToBool_Double) {} |
|
2409 |
|
2410 ICStub *getStub(ICStubSpace *space) { |
|
2411 return ICToBool_Double::New(space, getStubCode()); |
|
2412 } |
|
2413 }; |
|
2414 }; |
|
2415 |
|
2416 class ICToBool_Object : public ICStub |
|
2417 { |
|
2418 friend class ICStubSpace; |
|
2419 |
|
2420 ICToBool_Object(JitCode *stubCode) |
|
2421 : ICStub(ICStub::ToBool_Object, stubCode) {} |
|
2422 |
|
2423 public: |
|
2424 static inline ICToBool_Object *New(ICStubSpace *space, JitCode *code) { |
|
2425 if (!code) |
|
2426 return nullptr; |
|
2427 return space->allocate<ICToBool_Object>(code); |
|
2428 } |
|
2429 |
|
2430 // Compiler for this stub kind. |
|
2431 class Compiler : public ICStubCompiler { |
|
2432 protected: |
|
2433 bool generateStubCode(MacroAssembler &masm); |
|
2434 |
|
2435 public: |
|
2436 Compiler(JSContext *cx) |
|
2437 : ICStubCompiler(cx, ICStub::ToBool_Object) {} |
|
2438 |
|
2439 ICStub *getStub(ICStubSpace *space) { |
|
2440 return ICToBool_Object::New(space, getStubCode()); |
|
2441 } |
|
2442 }; |
|
2443 }; |
|
2444 |
|
2445 // ToNumber |
|
2446 // JSOP_POS |
|
2447 |
|
2448 class ICToNumber_Fallback : public ICFallbackStub |
|
2449 { |
|
2450 friend class ICStubSpace; |
|
2451 |
|
2452 ICToNumber_Fallback(JitCode *stubCode) |
|
2453 : ICFallbackStub(ICStub::ToNumber_Fallback, stubCode) {} |
|
2454 |
|
2455 public: |
|
2456 static inline ICToNumber_Fallback *New(ICStubSpace *space, JitCode *code) { |
|
2457 if (!code) |
|
2458 return nullptr; |
|
2459 return space->allocate<ICToNumber_Fallback>(code); |
|
2460 } |
|
2461 |
|
2462 // Compiler for this stub kind. |
|
2463 class Compiler : public ICStubCompiler { |
|
2464 protected: |
|
2465 bool generateStubCode(MacroAssembler &masm); |
|
2466 |
|
2467 public: |
|
2468 Compiler(JSContext *cx) |
|
2469 : ICStubCompiler(cx, ICStub::ToNumber_Fallback) {} |
|
2470 |
|
2471 ICStub *getStub(ICStubSpace *space) { |
|
2472 return ICToNumber_Fallback::New(space, getStubCode()); |
|
2473 } |
|
2474 }; |
|
2475 }; |
|
2476 |
|
2477 // BinaryArith |
|
2478 // JSOP_ADD |
|
2479 // JSOP_BITAND, JSOP_BITXOR, JSOP_BITOR |
|
2480 // JSOP_LSH, JSOP_RSH, JSOP_URSH |
|
2481 |
|
2482 class ICBinaryArith_Fallback : public ICFallbackStub |
|
2483 { |
|
2484 friend class ICStubSpace; |
|
2485 |
|
2486 ICBinaryArith_Fallback(JitCode *stubCode) |
|
2487 : ICFallbackStub(BinaryArith_Fallback, stubCode) |
|
2488 { |
|
2489 extra_ = 0; |
|
2490 } |
|
2491 |
|
2492 static const uint16_t SAW_DOUBLE_RESULT_BIT = 0x1; |
|
2493 static const uint16_t UNOPTIMIZABLE_OPERANDS_BIT = 0x2; |
|
2494 |
|
2495 public: |
|
2496 static const uint32_t MAX_OPTIMIZED_STUBS = 8; |
|
2497 |
|
2498 static inline ICBinaryArith_Fallback *New(ICStubSpace *space, JitCode *code) { |
|
2499 if (!code) |
|
2500 return nullptr; |
|
2501 return space->allocate<ICBinaryArith_Fallback>(code); |
|
2502 } |
|
2503 |
|
2504 bool sawDoubleResult() const { |
|
2505 return extra_ & SAW_DOUBLE_RESULT_BIT; |
|
2506 } |
|
2507 void setSawDoubleResult() { |
|
2508 extra_ |= SAW_DOUBLE_RESULT_BIT; |
|
2509 } |
|
2510 bool hadUnoptimizableOperands() const { |
|
2511 return extra_ & UNOPTIMIZABLE_OPERANDS_BIT; |
|
2512 } |
|
2513 void noteUnoptimizableOperands() { |
|
2514 extra_ |= UNOPTIMIZABLE_OPERANDS_BIT; |
|
2515 } |
|
2516 |
|
2517 // Compiler for this stub kind. |
|
2518 class Compiler : public ICStubCompiler { |
|
2519 protected: |
|
2520 bool generateStubCode(MacroAssembler &masm); |
|
2521 |
|
2522 public: |
|
2523 Compiler(JSContext *cx) |
|
2524 : ICStubCompiler(cx, ICStub::BinaryArith_Fallback) {} |
|
2525 |
|
2526 ICStub *getStub(ICStubSpace *space) { |
|
2527 return ICBinaryArith_Fallback::New(space, getStubCode()); |
|
2528 } |
|
2529 }; |
|
2530 }; |
|
2531 |
|
2532 class ICBinaryArith_Int32 : public ICStub |
|
2533 { |
|
2534 friend class ICStubSpace; |
|
2535 |
|
2536 ICBinaryArith_Int32(JitCode *stubCode, bool allowDouble) |
|
2537 : ICStub(BinaryArith_Int32, stubCode) |
|
2538 { |
|
2539 extra_ = allowDouble; |
|
2540 } |
|
2541 |
|
2542 public: |
|
2543 static inline ICBinaryArith_Int32 *New(ICStubSpace *space, JitCode *code, bool allowDouble) { |
|
2544 if (!code) |
|
2545 return nullptr; |
|
2546 return space->allocate<ICBinaryArith_Int32>(code, allowDouble); |
|
2547 } |
|
2548 bool allowDouble() const { |
|
2549 return extra_; |
|
2550 } |
|
2551 |
|
2552 // Compiler for this stub kind. |
|
2553 class Compiler : public ICStubCompiler { |
|
2554 protected: |
|
2555 JSOp op_; |
|
2556 bool allowDouble_; |
|
2557 |
|
2558 bool generateStubCode(MacroAssembler &masm); |
|
2559 |
|
2560 // Stub keys shift-stubs need to encode the kind, the JSOp and if we allow doubles. |
|
2561 virtual int32_t getKey() const { |
|
2562 return (static_cast<int32_t>(kind) | (static_cast<int32_t>(op_) << 16) | |
|
2563 (static_cast<int32_t>(allowDouble_) << 24)); |
|
2564 } |
|
2565 |
|
2566 public: |
|
2567 Compiler(JSContext *cx, JSOp op, bool allowDouble) |
|
2568 : ICStubCompiler(cx, ICStub::BinaryArith_Int32), |
|
2569 op_(op), allowDouble_(allowDouble) {} |
|
2570 |
|
2571 ICStub *getStub(ICStubSpace *space) { |
|
2572 return ICBinaryArith_Int32::New(space, getStubCode(), allowDouble_); |
|
2573 } |
|
2574 }; |
|
2575 }; |
|
2576 |
|
2577 class ICBinaryArith_StringConcat : public ICStub |
|
2578 { |
|
2579 friend class ICStubSpace; |
|
2580 |
|
2581 ICBinaryArith_StringConcat(JitCode *stubCode) |
|
2582 : ICStub(BinaryArith_StringConcat, stubCode) |
|
2583 {} |
|
2584 |
|
2585 public: |
|
2586 static inline ICBinaryArith_StringConcat *New(ICStubSpace *space, JitCode *code) { |
|
2587 if (!code) |
|
2588 return nullptr; |
|
2589 return space->allocate<ICBinaryArith_StringConcat>(code); |
|
2590 } |
|
2591 |
|
2592 class Compiler : public ICStubCompiler { |
|
2593 protected: |
|
2594 bool generateStubCode(MacroAssembler &masm); |
|
2595 |
|
2596 public: |
|
2597 Compiler(JSContext *cx) |
|
2598 : ICStubCompiler(cx, ICStub::BinaryArith_StringConcat) |
|
2599 {} |
|
2600 |
|
2601 ICStub *getStub(ICStubSpace *space) { |
|
2602 return ICBinaryArith_StringConcat::New(space, getStubCode()); |
|
2603 } |
|
2604 }; |
|
2605 }; |
|
2606 |
|
2607 class ICBinaryArith_StringObjectConcat : public ICStub |
|
2608 { |
|
2609 friend class ICStubSpace; |
|
2610 |
|
2611 ICBinaryArith_StringObjectConcat(JitCode *stubCode, bool lhsIsString) |
|
2612 : ICStub(BinaryArith_StringObjectConcat, stubCode) |
|
2613 { |
|
2614 extra_ = lhsIsString; |
|
2615 } |
|
2616 |
|
2617 public: |
|
2618 static inline ICBinaryArith_StringObjectConcat *New(ICStubSpace *space, JitCode *code, |
|
2619 bool lhsIsString) { |
|
2620 if (!code) |
|
2621 return nullptr; |
|
2622 return space->allocate<ICBinaryArith_StringObjectConcat>(code, lhsIsString); |
|
2623 } |
|
2624 |
|
2625 bool lhsIsString() const { |
|
2626 return extra_; |
|
2627 } |
|
2628 |
|
2629 class Compiler : public ICStubCompiler { |
|
2630 protected: |
|
2631 bool lhsIsString_; |
|
2632 bool generateStubCode(MacroAssembler &masm); |
|
2633 |
|
2634 virtual int32_t getKey() const { |
|
2635 return static_cast<int32_t>(kind) | (static_cast<int32_t>(lhsIsString_) << 16); |
|
2636 } |
|
2637 |
|
2638 public: |
|
2639 Compiler(JSContext *cx, bool lhsIsString) |
|
2640 : ICStubCompiler(cx, ICStub::BinaryArith_StringObjectConcat), |
|
2641 lhsIsString_(lhsIsString) |
|
2642 {} |
|
2643 |
|
2644 ICStub *getStub(ICStubSpace *space) { |
|
2645 return ICBinaryArith_StringObjectConcat::New(space, getStubCode(), lhsIsString_); |
|
2646 } |
|
2647 }; |
|
2648 }; |
|
2649 |
|
2650 class ICBinaryArith_Double : public ICStub |
|
2651 { |
|
2652 friend class ICStubSpace; |
|
2653 |
|
2654 ICBinaryArith_Double(JitCode *stubCode) |
|
2655 : ICStub(BinaryArith_Double, stubCode) |
|
2656 {} |
|
2657 |
|
2658 public: |
|
2659 static inline ICBinaryArith_Double *New(ICStubSpace *space, JitCode *code) { |
|
2660 if (!code) |
|
2661 return nullptr; |
|
2662 return space->allocate<ICBinaryArith_Double>(code); |
|
2663 } |
|
2664 |
|
2665 class Compiler : public ICMultiStubCompiler { |
|
2666 protected: |
|
2667 bool generateStubCode(MacroAssembler &masm); |
|
2668 |
|
2669 public: |
|
2670 Compiler(JSContext *cx, JSOp op) |
|
2671 : ICMultiStubCompiler(cx, ICStub::BinaryArith_Double, op) |
|
2672 {} |
|
2673 |
|
2674 ICStub *getStub(ICStubSpace *space) { |
|
2675 return ICBinaryArith_Double::New(space, getStubCode()); |
|
2676 } |
|
2677 }; |
|
2678 }; |
|
2679 |
|
2680 class ICBinaryArith_BooleanWithInt32 : public ICStub |
|
2681 { |
|
2682 friend class ICStubSpace; |
|
2683 |
|
2684 ICBinaryArith_BooleanWithInt32(JitCode *stubCode, bool lhsIsBool, bool rhsIsBool) |
|
2685 : ICStub(BinaryArith_BooleanWithInt32, stubCode) |
|
2686 { |
|
2687 JS_ASSERT(lhsIsBool || rhsIsBool); |
|
2688 extra_ = 0; |
|
2689 if (lhsIsBool) |
|
2690 extra_ |= 1; |
|
2691 if (rhsIsBool) |
|
2692 extra_ |= 2; |
|
2693 } |
|
2694 |
|
2695 public: |
|
2696 static inline ICBinaryArith_BooleanWithInt32 *New(ICStubSpace *space, JitCode *code, |
|
2697 bool lhsIsBool, bool rhsIsBool) { |
|
2698 if (!code) |
|
2699 return nullptr; |
|
2700 return space->allocate<ICBinaryArith_BooleanWithInt32>(code, lhsIsBool, rhsIsBool); |
|
2701 } |
|
2702 |
|
2703 bool lhsIsBoolean() const { |
|
2704 return extra_ & 1; |
|
2705 } |
|
2706 |
|
2707 bool rhsIsBoolean() const { |
|
2708 return extra_ & 2; |
|
2709 } |
|
2710 |
|
2711 class Compiler : public ICStubCompiler { |
|
2712 protected: |
|
2713 JSOp op_; |
|
2714 bool lhsIsBool_; |
|
2715 bool rhsIsBool_; |
|
2716 bool generateStubCode(MacroAssembler &masm); |
|
2717 |
|
2718 virtual int32_t getKey() const { |
|
2719 return static_cast<int32_t>(kind) | (static_cast<int32_t>(op_) << 16) | |
|
2720 (static_cast<int32_t>(lhsIsBool_) << 24) | |
|
2721 (static_cast<int32_t>(rhsIsBool_) << 25); |
|
2722 } |
|
2723 |
|
2724 public: |
|
2725 Compiler(JSContext *cx, JSOp op, bool lhsIsBool, bool rhsIsBool) |
|
2726 : ICStubCompiler(cx, ICStub::BinaryArith_BooleanWithInt32), |
|
2727 op_(op), lhsIsBool_(lhsIsBool), rhsIsBool_(rhsIsBool) |
|
2728 { |
|
2729 JS_ASSERT(op_ == JSOP_ADD || op_ == JSOP_SUB || op_ == JSOP_BITOR || |
|
2730 op_ == JSOP_BITAND || op_ == JSOP_BITXOR); |
|
2731 JS_ASSERT(lhsIsBool_ || rhsIsBool_); |
|
2732 } |
|
2733 |
|
2734 ICStub *getStub(ICStubSpace *space) { |
|
2735 return ICBinaryArith_BooleanWithInt32::New(space, getStubCode(), |
|
2736 lhsIsBool_, rhsIsBool_); |
|
2737 } |
|
2738 }; |
|
2739 }; |
|
2740 |
|
2741 class ICBinaryArith_DoubleWithInt32 : public ICStub |
|
2742 { |
|
2743 friend class ICStubSpace; |
|
2744 |
|
2745 ICBinaryArith_DoubleWithInt32(JitCode *stubCode, bool lhsIsDouble) |
|
2746 : ICStub(BinaryArith_DoubleWithInt32, stubCode) |
|
2747 { |
|
2748 extra_ = lhsIsDouble; |
|
2749 } |
|
2750 |
|
2751 public: |
|
2752 static inline ICBinaryArith_DoubleWithInt32 *New(ICStubSpace *space, JitCode *code, |
|
2753 bool lhsIsDouble) { |
|
2754 if (!code) |
|
2755 return nullptr; |
|
2756 return space->allocate<ICBinaryArith_DoubleWithInt32>(code, lhsIsDouble); |
|
2757 } |
|
2758 |
|
2759 bool lhsIsDouble() const { |
|
2760 return extra_; |
|
2761 } |
|
2762 |
|
2763 class Compiler : public ICMultiStubCompiler { |
|
2764 protected: |
|
2765 bool lhsIsDouble_; |
|
2766 bool generateStubCode(MacroAssembler &masm); |
|
2767 |
|
2768 virtual int32_t getKey() const { |
|
2769 return static_cast<int32_t>(kind) | (static_cast<int32_t>(op) << 16) | |
|
2770 (static_cast<int32_t>(lhsIsDouble_) << 24); |
|
2771 } |
|
2772 |
|
2773 public: |
|
2774 Compiler(JSContext *cx, JSOp op, bool lhsIsDouble) |
|
2775 : ICMultiStubCompiler(cx, ICStub::BinaryArith_DoubleWithInt32, op), |
|
2776 lhsIsDouble_(lhsIsDouble) |
|
2777 {} |
|
2778 |
|
2779 ICStub *getStub(ICStubSpace *space) { |
|
2780 return ICBinaryArith_DoubleWithInt32::New(space, getStubCode(), lhsIsDouble_); |
|
2781 } |
|
2782 }; |
|
2783 }; |
|
2784 |
|
2785 // UnaryArith |
|
2786 // JSOP_BITNOT |
|
2787 // JSOP_NEG |
|
2788 |
|
2789 class ICUnaryArith_Fallback : public ICFallbackStub |
|
2790 { |
|
2791 friend class ICStubSpace; |
|
2792 |
|
2793 ICUnaryArith_Fallback(JitCode *stubCode) |
|
2794 : ICFallbackStub(UnaryArith_Fallback, stubCode) |
|
2795 { |
|
2796 extra_ = 0; |
|
2797 } |
|
2798 |
|
2799 public: |
|
2800 static const uint32_t MAX_OPTIMIZED_STUBS = 8; |
|
2801 |
|
2802 static inline ICUnaryArith_Fallback *New(ICStubSpace *space, JitCode *code) { |
|
2803 if (!code) |
|
2804 return nullptr; |
|
2805 return space->allocate<ICUnaryArith_Fallback>(code); |
|
2806 } |
|
2807 |
|
2808 bool sawDoubleResult() { |
|
2809 return extra_; |
|
2810 } |
|
2811 void setSawDoubleResult() { |
|
2812 extra_ = 1; |
|
2813 } |
|
2814 |
|
2815 // Compiler for this stub kind. |
|
2816 class Compiler : public ICStubCompiler { |
|
2817 protected: |
|
2818 bool generateStubCode(MacroAssembler &masm); |
|
2819 |
|
2820 public: |
|
2821 Compiler(JSContext *cx) |
|
2822 : ICStubCompiler(cx, ICStub::UnaryArith_Fallback) |
|
2823 {} |
|
2824 |
|
2825 ICStub *getStub(ICStubSpace *space) { |
|
2826 return ICUnaryArith_Fallback::New(space, getStubCode()); |
|
2827 } |
|
2828 }; |
|
2829 }; |
|
2830 |
|
2831 class ICUnaryArith_Int32 : public ICStub |
|
2832 { |
|
2833 friend class ICStubSpace; |
|
2834 |
|
2835 ICUnaryArith_Int32(JitCode *stubCode) |
|
2836 : ICStub(UnaryArith_Int32, stubCode) |
|
2837 {} |
|
2838 |
|
2839 public: |
|
2840 static inline ICUnaryArith_Int32 *New(ICStubSpace *space, JitCode *code) { |
|
2841 if (!code) |
|
2842 return nullptr; |
|
2843 return space->allocate<ICUnaryArith_Int32>(code); |
|
2844 } |
|
2845 |
|
2846 class Compiler : public ICMultiStubCompiler { |
|
2847 protected: |
|
2848 bool generateStubCode(MacroAssembler &masm); |
|
2849 |
|
2850 public: |
|
2851 Compiler(JSContext *cx, JSOp op) |
|
2852 : ICMultiStubCompiler(cx, ICStub::UnaryArith_Int32, op) |
|
2853 {} |
|
2854 |
|
2855 ICStub *getStub(ICStubSpace *space) { |
|
2856 return ICUnaryArith_Int32::New(space, getStubCode()); |
|
2857 } |
|
2858 }; |
|
2859 }; |
|
2860 |
|
2861 class ICUnaryArith_Double : public ICStub |
|
2862 { |
|
2863 friend class ICStubSpace; |
|
2864 |
|
2865 ICUnaryArith_Double(JitCode *stubCode) |
|
2866 : ICStub(UnaryArith_Double, stubCode) |
|
2867 {} |
|
2868 |
|
2869 public: |
|
2870 static inline ICUnaryArith_Double *New(ICStubSpace *space, JitCode *code) { |
|
2871 if (!code) |
|
2872 return nullptr; |
|
2873 return space->allocate<ICUnaryArith_Double>(code); |
|
2874 } |
|
2875 |
|
2876 class Compiler : public ICMultiStubCompiler { |
|
2877 protected: |
|
2878 bool generateStubCode(MacroAssembler &masm); |
|
2879 |
|
2880 public: |
|
2881 Compiler(JSContext *cx, JSOp op) |
|
2882 : ICMultiStubCompiler(cx, ICStub::UnaryArith_Double, op) |
|
2883 {} |
|
2884 |
|
2885 ICStub *getStub(ICStubSpace *space) { |
|
2886 return ICUnaryArith_Double::New(space, getStubCode()); |
|
2887 } |
|
2888 }; |
|
2889 }; |
|
2890 |
|
2891 // GetElem |
|
2892 // JSOP_GETELEM |
|
2893 |
|
2894 class ICGetElem_Fallback : public ICMonitoredFallbackStub |
|
2895 { |
|
2896 friend class ICStubSpace; |
|
2897 |
|
2898 ICGetElem_Fallback(JitCode *stubCode) |
|
2899 : ICMonitoredFallbackStub(ICStub::GetElem_Fallback, stubCode) |
|
2900 { } |
|
2901 |
|
2902 static const uint16_t EXTRA_NON_NATIVE = 0x1; |
|
2903 static const uint16_t EXTRA_NEGATIVE_INDEX = 0x2; |
|
2904 |
|
2905 public: |
|
2906 static const uint32_t MAX_OPTIMIZED_STUBS = 16; |
|
2907 |
|
2908 static inline ICGetElem_Fallback *New(ICStubSpace *space, JitCode *code) { |
|
2909 if (!code) |
|
2910 return nullptr; |
|
2911 return space->allocate<ICGetElem_Fallback>(code); |
|
2912 } |
|
2913 |
|
2914 void noteNonNativeAccess() { |
|
2915 extra_ |= EXTRA_NON_NATIVE; |
|
2916 } |
|
2917 bool hasNonNativeAccess() const { |
|
2918 return extra_ & EXTRA_NON_NATIVE; |
|
2919 } |
|
2920 |
|
2921 void noteNegativeIndex() { |
|
2922 extra_ |= EXTRA_NEGATIVE_INDEX; |
|
2923 } |
|
2924 bool hasNegativeIndex() const { |
|
2925 return extra_ & EXTRA_NEGATIVE_INDEX; |
|
2926 } |
|
2927 |
|
2928 // Compiler for this stub kind. |
|
2929 class Compiler : public ICStubCompiler { |
|
2930 protected: |
|
2931 bool generateStubCode(MacroAssembler &masm); |
|
2932 |
|
2933 public: |
|
2934 Compiler(JSContext *cx) |
|
2935 : ICStubCompiler(cx, ICStub::GetElem_Fallback) |
|
2936 { } |
|
2937 |
|
2938 ICStub *getStub(ICStubSpace *space) { |
|
2939 ICGetElem_Fallback *stub = ICGetElem_Fallback::New(space, getStubCode()); |
|
2940 if (!stub) |
|
2941 return nullptr; |
|
2942 if (!stub->initMonitoringChain(cx, space)) |
|
2943 return nullptr; |
|
2944 return stub; |
|
2945 } |
|
2946 }; |
|
2947 }; |
|
2948 |
|
2949 class ICGetElemNativeStub : public ICMonitoredStub |
|
2950 { |
|
2951 public: |
|
2952 enum AccessType { FixedSlot = 0, DynamicSlot, NativeGetter, ScriptedGetter }; |
|
2953 |
|
2954 protected: |
|
2955 HeapPtrShape shape_; |
|
2956 HeapPtrPropertyName name_; |
|
2957 |
|
2958 static const unsigned NEEDS_ATOMIZE_SHIFT = 0; |
|
2959 static const uint16_t NEEDS_ATOMIZE_MASK = 0x1; |
|
2960 |
|
2961 static const unsigned ACCESSTYPE_SHIFT = 1; |
|
2962 static const uint16_t ACCESSTYPE_MASK = 0x3; |
|
2963 |
|
2964 ICGetElemNativeStub(ICStub::Kind kind, JitCode *stubCode, ICStub *firstMonitorStub, |
|
2965 HandleShape shape, HandlePropertyName name, AccessType acctype, |
|
2966 bool needsAtomize); |
|
2967 |
|
2968 ~ICGetElemNativeStub(); |
|
2969 |
|
2970 public: |
|
2971 HeapPtrShape &shape() { |
|
2972 return shape_; |
|
2973 } |
|
2974 static size_t offsetOfShape() { |
|
2975 return offsetof(ICGetElemNativeStub, shape_); |
|
2976 } |
|
2977 |
|
2978 HeapPtrPropertyName &name() { |
|
2979 return name_; |
|
2980 } |
|
2981 static size_t offsetOfName() { |
|
2982 return offsetof(ICGetElemNativeStub, name_); |
|
2983 } |
|
2984 |
|
2985 AccessType accessType() const { |
|
2986 return static_cast<AccessType>((extra_ >> ACCESSTYPE_SHIFT) & ACCESSTYPE_MASK); |
|
2987 } |
|
2988 |
|
2989 bool needsAtomize() const { |
|
2990 return (extra_ >> NEEDS_ATOMIZE_SHIFT) & NEEDS_ATOMIZE_MASK; |
|
2991 } |
|
2992 }; |
|
2993 |
|
2994 class ICGetElemNativeSlotStub : public ICGetElemNativeStub |
|
2995 { |
|
2996 protected: |
|
2997 uint32_t offset_; |
|
2998 |
|
2999 ICGetElemNativeSlotStub(ICStub::Kind kind, JitCode *stubCode, ICStub *firstMonitorStub, |
|
3000 HandleShape shape, HandlePropertyName name, |
|
3001 AccessType acctype, bool needsAtomize, uint32_t offset) |
|
3002 : ICGetElemNativeStub(kind, stubCode, firstMonitorStub, shape, name, acctype, needsAtomize), |
|
3003 offset_(offset) |
|
3004 { |
|
3005 JS_ASSERT(kind == GetElem_NativeSlot || kind == GetElem_NativePrototypeSlot); |
|
3006 JS_ASSERT(acctype == FixedSlot || acctype == DynamicSlot); |
|
3007 } |
|
3008 |
|
3009 public: |
|
3010 uint32_t offset() const { |
|
3011 return offset_; |
|
3012 } |
|
3013 |
|
3014 static size_t offsetOfOffset() { |
|
3015 return offsetof(ICGetElemNativeSlotStub, offset_); |
|
3016 } |
|
3017 }; |
|
3018 |
|
3019 class ICGetElemNativeGetterStub : public ICGetElemNativeStub |
|
3020 { |
|
3021 protected: |
|
3022 HeapPtrFunction getter_; |
|
3023 uint32_t pcOffset_; |
|
3024 |
|
3025 ICGetElemNativeGetterStub(ICStub::Kind kind, JitCode *stubCode, ICStub *firstMonitorStub, |
|
3026 HandleShape shape, HandlePropertyName name, AccessType acctype, |
|
3027 bool needsAtomize, HandleFunction getter, uint32_t pcOffset); |
|
3028 |
|
3029 public: |
|
3030 HeapPtrFunction &getter() { |
|
3031 return getter_; |
|
3032 } |
|
3033 static size_t offsetOfGetter() { |
|
3034 return offsetof(ICGetElemNativeGetterStub, getter_); |
|
3035 } |
|
3036 |
|
3037 static size_t offsetOfPCOffset() { |
|
3038 return offsetof(ICGetElemNativeGetterStub, pcOffset_); |
|
3039 } |
|
3040 }; |
|
3041 |
|
3042 class ICGetElem_NativeSlot : public ICGetElemNativeSlotStub |
|
3043 { |
|
3044 friend class ICStubSpace; |
|
3045 ICGetElem_NativeSlot(JitCode *stubCode, ICStub *firstMonitorStub, |
|
3046 HandleShape shape, HandlePropertyName name, |
|
3047 AccessType acctype, bool needsAtomize, uint32_t offset) |
|
3048 : ICGetElemNativeSlotStub(ICStub::GetElem_NativeSlot, stubCode, firstMonitorStub, shape, |
|
3049 name, acctype, needsAtomize, offset) |
|
3050 {} |
|
3051 |
|
3052 public: |
|
3053 static inline ICGetElem_NativeSlot *New(ICStubSpace *space, JitCode *code, |
|
3054 ICStub *firstMonitorStub, |
|
3055 HandleShape shape, HandlePropertyName name, |
|
3056 AccessType acctype, bool needsAtomize, uint32_t offset) |
|
3057 { |
|
3058 if (!code) |
|
3059 return nullptr; |
|
3060 return space->allocate<ICGetElem_NativeSlot>(code, firstMonitorStub, shape, name, |
|
3061 acctype, needsAtomize, offset); |
|
3062 } |
|
3063 }; |
|
3064 |
|
3065 class ICGetElem_NativePrototypeSlot : public ICGetElemNativeSlotStub |
|
3066 { |
|
3067 friend class ICStubSpace; |
|
3068 HeapPtrObject holder_; |
|
3069 HeapPtrShape holderShape_; |
|
3070 |
|
3071 ICGetElem_NativePrototypeSlot(JitCode *stubCode, ICStub *firstMonitorStub, |
|
3072 HandleShape shape, HandlePropertyName name, |
|
3073 AccessType acctype, bool needsAtomize, uint32_t offset, |
|
3074 HandleObject holder, HandleShape holderShape); |
|
3075 |
|
3076 public: |
|
3077 static inline ICGetElem_NativePrototypeSlot *New(ICStubSpace *space, JitCode *code, |
|
3078 ICStub *firstMonitorStub, |
|
3079 HandleShape shape, HandlePropertyName name, |
|
3080 AccessType acctype, bool needsAtomize, |
|
3081 uint32_t offset, HandleObject holder, |
|
3082 HandleShape holderShape) |
|
3083 { |
|
3084 if (!code) |
|
3085 return nullptr; |
|
3086 return space->allocate<ICGetElem_NativePrototypeSlot>( |
|
3087 code, firstMonitorStub, shape, name, acctype, needsAtomize, offset, holder, |
|
3088 holderShape); |
|
3089 } |
|
3090 |
|
3091 HeapPtrObject &holder() { |
|
3092 return holder_; |
|
3093 } |
|
3094 static size_t offsetOfHolder() { |
|
3095 return offsetof(ICGetElem_NativePrototypeSlot, holder_); |
|
3096 } |
|
3097 |
|
3098 HeapPtrShape &holderShape() { |
|
3099 return holderShape_; |
|
3100 } |
|
3101 static size_t offsetOfHolderShape() { |
|
3102 return offsetof(ICGetElem_NativePrototypeSlot, holderShape_); |
|
3103 } |
|
3104 }; |
|
3105 |
|
3106 class ICGetElemNativePrototypeCallStub : public ICGetElemNativeGetterStub |
|
3107 { |
|
3108 friend class ICStubSpace; |
|
3109 HeapPtrObject holder_; |
|
3110 HeapPtrShape holderShape_; |
|
3111 |
|
3112 protected: |
|
3113 ICGetElemNativePrototypeCallStub(ICStub::Kind kind, JitCode *stubCode, ICStub *firstMonitorStub, |
|
3114 HandleShape shape, HandlePropertyName name, |
|
3115 AccessType acctype, bool needsAtomize, HandleFunction getter, |
|
3116 uint32_t pcOffset, HandleObject holder, |
|
3117 HandleShape holderShape); |
|
3118 |
|
3119 public: |
|
3120 HeapPtrObject &holder() { |
|
3121 return holder_; |
|
3122 } |
|
3123 static size_t offsetOfHolder() { |
|
3124 return offsetof(ICGetElemNativePrototypeCallStub, holder_); |
|
3125 } |
|
3126 |
|
3127 HeapPtrShape &holderShape() { |
|
3128 return holderShape_; |
|
3129 } |
|
3130 static size_t offsetOfHolderShape() { |
|
3131 return offsetof(ICGetElemNativePrototypeCallStub, holderShape_); |
|
3132 } |
|
3133 }; |
|
3134 |
|
3135 class ICGetElem_NativePrototypeCallNative : public ICGetElemNativePrototypeCallStub |
|
3136 { |
|
3137 friend class ICStubSpace; |
|
3138 |
|
3139 ICGetElem_NativePrototypeCallNative(JitCode *stubCode, ICStub *firstMonitorStub, |
|
3140 HandleShape shape, HandlePropertyName name, |
|
3141 AccessType acctype, bool needsAtomize, |
|
3142 HandleFunction getter, uint32_t pcOffset, |
|
3143 HandleObject holder, HandleShape holderShape) |
|
3144 : ICGetElemNativePrototypeCallStub(GetElem_NativePrototypeCallNative, |
|
3145 stubCode, firstMonitorStub, shape, name, |
|
3146 acctype, needsAtomize, getter, pcOffset, holder, |
|
3147 holderShape) |
|
3148 {} |
|
3149 |
|
3150 public: |
|
3151 static inline ICGetElem_NativePrototypeCallNative *New( |
|
3152 ICStubSpace *space, JitCode *code, ICStub *firstMonitorStub, |
|
3153 HandleShape shape, HandlePropertyName name, AccessType acctype, |
|
3154 bool needsAtomize, HandleFunction getter, uint32_t pcOffset, |
|
3155 HandleObject holder, HandleShape holderShape) |
|
3156 { |
|
3157 if (!code) |
|
3158 return nullptr; |
|
3159 return space->allocate<ICGetElem_NativePrototypeCallNative>( |
|
3160 code, firstMonitorStub, shape, name, acctype, needsAtomize, getter, |
|
3161 pcOffset, holder, holderShape); |
|
3162 } |
|
3163 }; |
|
3164 |
|
3165 class ICGetElem_NativePrototypeCallScripted : public ICGetElemNativePrototypeCallStub |
|
3166 { |
|
3167 friend class ICStubSpace; |
|
3168 |
|
3169 ICGetElem_NativePrototypeCallScripted(JitCode *stubCode, ICStub *firstMonitorStub, |
|
3170 HandleShape shape, HandlePropertyName name, |
|
3171 AccessType acctype, bool needsAtomize, |
|
3172 HandleFunction getter, uint32_t pcOffset, |
|
3173 HandleObject holder, HandleShape holderShape) |
|
3174 : ICGetElemNativePrototypeCallStub(GetElem_NativePrototypeCallScripted, |
|
3175 stubCode, firstMonitorStub, shape, name, |
|
3176 acctype, needsAtomize, getter, pcOffset, holder, |
|
3177 holderShape) |
|
3178 {} |
|
3179 |
|
3180 public: |
|
3181 static inline ICGetElem_NativePrototypeCallScripted *New( |
|
3182 ICStubSpace *space, JitCode *code, ICStub *firstMonitorStub, |
|
3183 HandleShape shape, HandlePropertyName name, AccessType acctype, |
|
3184 bool needsAtomize, HandleFunction getter, uint32_t pcOffset, |
|
3185 HandleObject holder, HandleShape holderShape) |
|
3186 { |
|
3187 if (!code) |
|
3188 return nullptr; |
|
3189 return space->allocate<ICGetElem_NativePrototypeCallScripted>( |
|
3190 code, firstMonitorStub, shape, name, acctype, needsAtomize, getter, |
|
3191 pcOffset, holder, holderShape); |
|
3192 } |
|
3193 }; |
|
3194 |
|
3195 // Compiler for GetElem_NativeSlot and GetElem_NativePrototypeSlot stubs. |
|
3196 class ICGetElemNativeCompiler : public ICStubCompiler |
|
3197 { |
|
3198 bool isCallElem_; |
|
3199 ICStub *firstMonitorStub_; |
|
3200 HandleObject obj_; |
|
3201 HandleObject holder_; |
|
3202 HandlePropertyName name_; |
|
3203 ICGetElemNativeStub::AccessType acctype_; |
|
3204 bool needsAtomize_; |
|
3205 uint32_t offset_; |
|
3206 HandleFunction getter_; |
|
3207 uint32_t pcOffset_; |
|
3208 |
|
3209 bool emitCallNative(MacroAssembler &masm, Register objReg); |
|
3210 bool emitCallScripted(MacroAssembler &masm, Register objReg); |
|
3211 bool generateStubCode(MacroAssembler &masm); |
|
3212 |
|
3213 protected: |
|
3214 virtual int32_t getKey() const { |
|
3215 #if JS_HAS_NO_SUCH_METHOD |
|
3216 return static_cast<int32_t>(kind) | |
|
3217 (static_cast<int32_t>(isCallElem_) << 16) | |
|
3218 (static_cast<int32_t>(needsAtomize_) << 17) | |
|
3219 (static_cast<int32_t>(acctype_) << 18); |
|
3220 #else |
|
3221 return static_cast<int32_t>(kind) | (static_cast<int32_t>(needsAtomize_) << 16) | |
|
3222 (static_cast<int32_t>(acctype_) << 17); |
|
3223 #endif |
|
3224 } |
|
3225 |
|
3226 public: |
|
3227 ICGetElemNativeCompiler(JSContext *cx, ICStub::Kind kind, bool isCallElem, |
|
3228 ICStub *firstMonitorStub, HandleObject obj, HandleObject holder, |
|
3229 HandlePropertyName name, ICGetElemNativeStub::AccessType acctype, |
|
3230 bool needsAtomize, uint32_t offset) |
|
3231 : ICStubCompiler(cx, kind), |
|
3232 isCallElem_(isCallElem), |
|
3233 firstMonitorStub_(firstMonitorStub), |
|
3234 obj_(obj), |
|
3235 holder_(holder), |
|
3236 name_(name), |
|
3237 acctype_(acctype), |
|
3238 needsAtomize_(needsAtomize), |
|
3239 offset_(offset), |
|
3240 getter_(js::NullPtr()), |
|
3241 pcOffset_(0) |
|
3242 {} |
|
3243 |
|
3244 ICGetElemNativeCompiler(JSContext *cx, ICStub::Kind kind, ICStub *firstMonitorStub, |
|
3245 HandleObject obj, HandleObject holder, HandlePropertyName name, |
|
3246 ICGetElemNativeStub::AccessType acctype, bool needsAtomize, |
|
3247 HandleFunction getter, uint32_t pcOffset, bool isCallElem) |
|
3248 : ICStubCompiler(cx, kind), |
|
3249 isCallElem_(false), |
|
3250 firstMonitorStub_(firstMonitorStub), |
|
3251 obj_(obj), |
|
3252 holder_(holder), |
|
3253 name_(name), |
|
3254 acctype_(acctype), |
|
3255 needsAtomize_(needsAtomize), |
|
3256 offset_(0), |
|
3257 getter_(getter), |
|
3258 pcOffset_(pcOffset) |
|
3259 {} |
|
3260 |
|
3261 ICStub *getStub(ICStubSpace *space) { |
|
3262 RootedShape shape(cx, obj_->lastProperty()); |
|
3263 if (kind == ICStub::GetElem_NativeSlot) { |
|
3264 JS_ASSERT(obj_ == holder_); |
|
3265 return ICGetElem_NativeSlot::New( |
|
3266 space, getStubCode(), firstMonitorStub_, shape, name_, acctype_, needsAtomize_, |
|
3267 offset_); |
|
3268 } |
|
3269 |
|
3270 JS_ASSERT(obj_ != holder_); |
|
3271 RootedShape holderShape(cx, holder_->lastProperty()); |
|
3272 if (kind == ICStub::GetElem_NativePrototypeSlot) { |
|
3273 return ICGetElem_NativePrototypeSlot::New( |
|
3274 space, getStubCode(), firstMonitorStub_, shape, name_, acctype_, needsAtomize_, |
|
3275 offset_, holder_, holderShape); |
|
3276 } |
|
3277 |
|
3278 if (kind == ICStub::GetElem_NativePrototypeCallNative) { |
|
3279 return ICGetElem_NativePrototypeCallNative::New( |
|
3280 space, getStubCode(), firstMonitorStub_, shape, name_, acctype_, needsAtomize_, |
|
3281 getter_, pcOffset_, holder_, holderShape); |
|
3282 } |
|
3283 |
|
3284 JS_ASSERT(kind == ICStub::GetElem_NativePrototypeCallScripted); |
|
3285 if (kind == ICStub::GetElem_NativePrototypeCallScripted) { |
|
3286 return ICGetElem_NativePrototypeCallScripted::New( |
|
3287 space, getStubCode(), firstMonitorStub_, shape, name_, acctype_, needsAtomize_, |
|
3288 getter_, pcOffset_, holder_, holderShape); |
|
3289 } |
|
3290 |
|
3291 MOZ_ASSUME_UNREACHABLE("Invalid kind."); |
|
3292 return nullptr; |
|
3293 } |
|
3294 }; |
|
3295 |
|
3296 class ICGetElem_String : public ICStub |
|
3297 { |
|
3298 friend class ICStubSpace; |
|
3299 |
|
3300 ICGetElem_String(JitCode *stubCode) |
|
3301 : ICStub(ICStub::GetElem_String, stubCode) {} |
|
3302 |
|
3303 public: |
|
3304 static inline ICGetElem_String *New(ICStubSpace *space, JitCode *code) { |
|
3305 if (!code) |
|
3306 return nullptr; |
|
3307 return space->allocate<ICGetElem_String>(code); |
|
3308 } |
|
3309 |
|
3310 // Compiler for this stub kind. |
|
3311 class Compiler : public ICStubCompiler { |
|
3312 protected: |
|
3313 bool generateStubCode(MacroAssembler &masm); |
|
3314 |
|
3315 public: |
|
3316 Compiler(JSContext *cx) |
|
3317 : ICStubCompiler(cx, ICStub::GetElem_String) {} |
|
3318 |
|
3319 ICStub *getStub(ICStubSpace *space) { |
|
3320 return ICGetElem_String::New(space, getStubCode()); |
|
3321 } |
|
3322 }; |
|
3323 }; |
|
3324 |
|
3325 class ICGetElem_Dense : public ICMonitoredStub |
|
3326 { |
|
3327 friend class ICStubSpace; |
|
3328 |
|
3329 HeapPtrShape shape_; |
|
3330 |
|
3331 ICGetElem_Dense(JitCode *stubCode, ICStub *firstMonitorStub, HandleShape shape); |
|
3332 |
|
3333 public: |
|
3334 static inline ICGetElem_Dense *New(ICStubSpace *space, JitCode *code, |
|
3335 ICStub *firstMonitorStub, HandleShape shape) |
|
3336 { |
|
3337 if (!code) |
|
3338 return nullptr; |
|
3339 return space->allocate<ICGetElem_Dense>(code, firstMonitorStub, shape); |
|
3340 } |
|
3341 |
|
3342 static size_t offsetOfShape() { |
|
3343 return offsetof(ICGetElem_Dense, shape_); |
|
3344 } |
|
3345 |
|
3346 HeapPtrShape &shape() { |
|
3347 return shape_; |
|
3348 } |
|
3349 |
|
3350 class Compiler : public ICStubCompiler { |
|
3351 ICStub *firstMonitorStub_; |
|
3352 RootedShape shape_; |
|
3353 bool isCallElem_; |
|
3354 |
|
3355 protected: |
|
3356 bool generateStubCode(MacroAssembler &masm); |
|
3357 |
|
3358 virtual int32_t getKey() const { |
|
3359 #if JS_HAS_NO_SUCH_METHOD |
|
3360 return static_cast<int32_t>(kind) | (static_cast<int32_t>(isCallElem_) << 16); |
|
3361 #else |
|
3362 return static_cast<int32_t>(kind); |
|
3363 #endif |
|
3364 } |
|
3365 |
|
3366 public: |
|
3367 Compiler(JSContext *cx, ICStub *firstMonitorStub, Shape *shape, bool isCallElem) |
|
3368 : ICStubCompiler(cx, ICStub::GetElem_Dense), |
|
3369 firstMonitorStub_(firstMonitorStub), |
|
3370 shape_(cx, shape), |
|
3371 isCallElem_(isCallElem) |
|
3372 {} |
|
3373 |
|
3374 ICStub *getStub(ICStubSpace *space) { |
|
3375 return ICGetElem_Dense::New(space, getStubCode(), firstMonitorStub_, shape_); |
|
3376 } |
|
3377 }; |
|
3378 }; |
|
3379 |
|
3380 class ICGetElem_TypedArray : public ICStub |
|
3381 { |
|
3382 friend class ICStubSpace; |
|
3383 |
|
3384 protected: // Protected to silence Clang warning. |
|
3385 HeapPtrShape shape_; |
|
3386 |
|
3387 ICGetElem_TypedArray(JitCode *stubCode, HandleShape shape, uint32_t type); |
|
3388 |
|
3389 public: |
|
3390 static inline ICGetElem_TypedArray *New(ICStubSpace *space, JitCode *code, |
|
3391 HandleShape shape, uint32_t type) |
|
3392 { |
|
3393 if (!code) |
|
3394 return nullptr; |
|
3395 return space->allocate<ICGetElem_TypedArray>(code, shape, type); |
|
3396 } |
|
3397 |
|
3398 static size_t offsetOfShape() { |
|
3399 return offsetof(ICGetElem_TypedArray, shape_); |
|
3400 } |
|
3401 |
|
3402 HeapPtrShape &shape() { |
|
3403 return shape_; |
|
3404 } |
|
3405 |
|
3406 class Compiler : public ICStubCompiler { |
|
3407 RootedShape shape_; |
|
3408 uint32_t type_; |
|
3409 |
|
3410 protected: |
|
3411 bool generateStubCode(MacroAssembler &masm); |
|
3412 |
|
3413 virtual int32_t getKey() const { |
|
3414 return static_cast<int32_t>(kind) | (static_cast<int32_t>(type_) << 16); |
|
3415 } |
|
3416 |
|
3417 public: |
|
3418 Compiler(JSContext *cx, Shape *shape, uint32_t type) |
|
3419 : ICStubCompiler(cx, ICStub::GetElem_TypedArray), |
|
3420 shape_(cx, shape), |
|
3421 type_(type) |
|
3422 {} |
|
3423 |
|
3424 ICStub *getStub(ICStubSpace *space) { |
|
3425 return ICGetElem_TypedArray::New(space, getStubCode(), shape_, type_); |
|
3426 } |
|
3427 }; |
|
3428 }; |
|
3429 |
|
3430 class ICGetElem_Arguments : public ICMonitoredStub |
|
3431 { |
|
3432 friend class ICStubSpace; |
|
3433 public: |
|
3434 enum Which { Normal, Strict, Magic }; |
|
3435 |
|
3436 private: |
|
3437 ICGetElem_Arguments(JitCode *stubCode, ICStub *firstMonitorStub, Which which) |
|
3438 : ICMonitoredStub(ICStub::GetElem_Arguments, stubCode, firstMonitorStub) |
|
3439 { |
|
3440 extra_ = static_cast<uint16_t>(which); |
|
3441 } |
|
3442 |
|
3443 public: |
|
3444 static inline ICGetElem_Arguments *New(ICStubSpace *space, JitCode *code, |
|
3445 ICStub *firstMonitorStub, Which which) |
|
3446 { |
|
3447 if (!code) |
|
3448 return nullptr; |
|
3449 return space->allocate<ICGetElem_Arguments>(code, firstMonitorStub, which); |
|
3450 } |
|
3451 |
|
3452 Which which() const { |
|
3453 return static_cast<Which>(extra_); |
|
3454 } |
|
3455 |
|
3456 class Compiler : public ICStubCompiler { |
|
3457 ICStub *firstMonitorStub_; |
|
3458 Which which_; |
|
3459 bool isCallElem_; |
|
3460 |
|
3461 protected: |
|
3462 bool generateStubCode(MacroAssembler &masm); |
|
3463 |
|
3464 virtual int32_t getKey() const { |
|
3465 #if JS_HAS_NO_SUCH_METHOD |
|
3466 return static_cast<int32_t>(kind) | |
|
3467 static_cast<int32_t>(isCallElem_ << 16) | |
|
3468 (static_cast<int32_t>(which_) << 17); |
|
3469 #else |
|
3470 return static_cast<int32_t>(kind) | (static_cast<int32_t>(which_) << 16); |
|
3471 #endif |
|
3472 } |
|
3473 |
|
3474 public: |
|
3475 Compiler(JSContext *cx, ICStub *firstMonitorStub, Which which, bool isCallElem) |
|
3476 : ICStubCompiler(cx, ICStub::GetElem_Arguments), |
|
3477 firstMonitorStub_(firstMonitorStub), |
|
3478 which_(which), |
|
3479 isCallElem_(isCallElem) |
|
3480 {} |
|
3481 |
|
3482 ICStub *getStub(ICStubSpace *space) { |
|
3483 return ICGetElem_Arguments::New(space, getStubCode(), firstMonitorStub_, which_); |
|
3484 } |
|
3485 }; |
|
3486 }; |
|
3487 |
|
3488 // SetElem |
|
3489 // JSOP_SETELEM |
|
3490 // JSOP_INITELEM |
|
3491 |
|
3492 class ICSetElem_Fallback : public ICFallbackStub |
|
3493 { |
|
3494 friend class ICStubSpace; |
|
3495 |
|
3496 ICSetElem_Fallback(JitCode *stubCode) |
|
3497 : ICFallbackStub(ICStub::SetElem_Fallback, stubCode) |
|
3498 { } |
|
3499 |
|
3500 public: |
|
3501 static const uint32_t MAX_OPTIMIZED_STUBS = 8; |
|
3502 |
|
3503 static inline ICSetElem_Fallback *New(ICStubSpace *space, JitCode *code) { |
|
3504 if (!code) |
|
3505 return nullptr; |
|
3506 return space->allocate<ICSetElem_Fallback>(code); |
|
3507 } |
|
3508 |
|
3509 void noteArrayWriteHole() { |
|
3510 extra_ = 1; |
|
3511 } |
|
3512 bool hasArrayWriteHole() const { |
|
3513 return extra_; |
|
3514 } |
|
3515 |
|
3516 // Compiler for this stub kind. |
|
3517 class Compiler : public ICStubCompiler { |
|
3518 protected: |
|
3519 bool generateStubCode(MacroAssembler &masm); |
|
3520 |
|
3521 public: |
|
3522 Compiler(JSContext *cx) |
|
3523 : ICStubCompiler(cx, ICStub::SetElem_Fallback) |
|
3524 { } |
|
3525 |
|
3526 ICStub *getStub(ICStubSpace *space) { |
|
3527 return ICSetElem_Fallback::New(space, getStubCode()); |
|
3528 } |
|
3529 }; |
|
3530 }; |
|
3531 |
|
3532 class ICSetElem_Dense : public ICUpdatedStub |
|
3533 { |
|
3534 friend class ICStubSpace; |
|
3535 |
|
3536 HeapPtrShape shape_; |
|
3537 HeapPtrTypeObject type_; |
|
3538 |
|
3539 ICSetElem_Dense(JitCode *stubCode, HandleShape shape, HandleTypeObject type); |
|
3540 |
|
3541 public: |
|
3542 static inline ICSetElem_Dense *New(ICStubSpace *space, JitCode *code, HandleShape shape, |
|
3543 HandleTypeObject type) { |
|
3544 if (!code) |
|
3545 return nullptr; |
|
3546 return space->allocate<ICSetElem_Dense>(code, shape, type); |
|
3547 } |
|
3548 |
|
3549 static size_t offsetOfShape() { |
|
3550 return offsetof(ICSetElem_Dense, shape_); |
|
3551 } |
|
3552 static size_t offsetOfType() { |
|
3553 return offsetof(ICSetElem_Dense, type_); |
|
3554 } |
|
3555 |
|
3556 HeapPtrShape &shape() { |
|
3557 return shape_; |
|
3558 } |
|
3559 HeapPtrTypeObject &type() { |
|
3560 return type_; |
|
3561 } |
|
3562 |
|
3563 class Compiler : public ICStubCompiler { |
|
3564 RootedShape shape_; |
|
3565 |
|
3566 // Compiler is only live on stack during compilation, it should |
|
3567 // outlive any RootedTypeObject it's passed. So it can just |
|
3568 // use the handle. |
|
3569 HandleTypeObject type_; |
|
3570 |
|
3571 bool generateStubCode(MacroAssembler &masm); |
|
3572 |
|
3573 public: |
|
3574 Compiler(JSContext *cx, Shape *shape, HandleTypeObject type) |
|
3575 : ICStubCompiler(cx, ICStub::SetElem_Dense), |
|
3576 shape_(cx, shape), |
|
3577 type_(type) |
|
3578 {} |
|
3579 |
|
3580 ICUpdatedStub *getStub(ICStubSpace *space) { |
|
3581 ICSetElem_Dense *stub = ICSetElem_Dense::New(space, getStubCode(), shape_, type_); |
|
3582 if (!stub || !stub->initUpdatingChain(cx, space)) |
|
3583 return nullptr; |
|
3584 return stub; |
|
3585 } |
|
3586 }; |
|
3587 }; |
|
3588 |
|
3589 template <size_t ProtoChainDepth> class ICSetElem_DenseAddImpl; |
|
3590 |
|
3591 class ICSetElem_DenseAdd : public ICUpdatedStub |
|
3592 { |
|
3593 friend class ICStubSpace; |
|
3594 |
|
3595 public: |
|
3596 static const size_t MAX_PROTO_CHAIN_DEPTH = 4; |
|
3597 |
|
3598 protected: |
|
3599 HeapPtrTypeObject type_; |
|
3600 |
|
3601 ICSetElem_DenseAdd(JitCode *stubCode, types::TypeObject *type, size_t protoChainDepth); |
|
3602 |
|
3603 public: |
|
3604 static size_t offsetOfType() { |
|
3605 return offsetof(ICSetElem_DenseAdd, type_); |
|
3606 } |
|
3607 |
|
3608 HeapPtrTypeObject &type() { |
|
3609 return type_; |
|
3610 } |
|
3611 size_t protoChainDepth() const { |
|
3612 MOZ_ASSERT(extra_ <= MAX_PROTO_CHAIN_DEPTH); |
|
3613 return extra_; |
|
3614 } |
|
3615 |
|
3616 template <size_t ProtoChainDepth> |
|
3617 ICSetElem_DenseAddImpl<ProtoChainDepth> *toImplUnchecked() { |
|
3618 return static_cast<ICSetElem_DenseAddImpl<ProtoChainDepth> *>(this); |
|
3619 } |
|
3620 |
|
3621 template <size_t ProtoChainDepth> |
|
3622 ICSetElem_DenseAddImpl<ProtoChainDepth> *toImpl() { |
|
3623 JS_ASSERT(ProtoChainDepth == protoChainDepth()); |
|
3624 return toImplUnchecked<ProtoChainDepth>(); |
|
3625 } |
|
3626 }; |
|
3627 |
|
3628 template <size_t ProtoChainDepth> |
|
3629 class ICSetElem_DenseAddImpl : public ICSetElem_DenseAdd |
|
3630 { |
|
3631 friend class ICStubSpace; |
|
3632 |
|
3633 static const size_t NumShapes = ProtoChainDepth + 1; |
|
3634 mozilla::Array<HeapPtrShape, NumShapes> shapes_; |
|
3635 |
|
3636 ICSetElem_DenseAddImpl(JitCode *stubCode, types::TypeObject *type, |
|
3637 const AutoShapeVector *shapes) |
|
3638 : ICSetElem_DenseAdd(stubCode, type, ProtoChainDepth) |
|
3639 { |
|
3640 JS_ASSERT(shapes->length() == NumShapes); |
|
3641 for (size_t i = 0; i < NumShapes; i++) |
|
3642 shapes_[i].init((*shapes)[i]); |
|
3643 } |
|
3644 |
|
3645 public: |
|
3646 static inline ICSetElem_DenseAddImpl *New(ICStubSpace *space, JitCode *code, |
|
3647 types::TypeObject *type, |
|
3648 const AutoShapeVector *shapes) |
|
3649 { |
|
3650 if (!code) |
|
3651 return nullptr; |
|
3652 return space->allocate<ICSetElem_DenseAddImpl<ProtoChainDepth> >(code, type, shapes); |
|
3653 } |
|
3654 |
|
3655 void traceShapes(JSTracer *trc) { |
|
3656 for (size_t i = 0; i < NumShapes; i++) |
|
3657 MarkShape(trc, &shapes_[i], "baseline-setelem-denseadd-stub-shape"); |
|
3658 } |
|
3659 Shape *shape(size_t i) const { |
|
3660 JS_ASSERT(i < NumShapes); |
|
3661 return shapes_[i]; |
|
3662 } |
|
3663 static size_t offsetOfShape(size_t idx) { |
|
3664 return offsetof(ICSetElem_DenseAddImpl, shapes_) + idx * sizeof(HeapPtrShape); |
|
3665 } |
|
3666 }; |
|
3667 |
|
3668 class ICSetElemDenseAddCompiler : public ICStubCompiler { |
|
3669 RootedObject obj_; |
|
3670 size_t protoChainDepth_; |
|
3671 |
|
3672 bool generateStubCode(MacroAssembler &masm); |
|
3673 |
|
3674 protected: |
|
3675 virtual int32_t getKey() const { |
|
3676 return static_cast<int32_t>(kind) | (static_cast<int32_t>(protoChainDepth_) << 16); |
|
3677 } |
|
3678 |
|
3679 public: |
|
3680 ICSetElemDenseAddCompiler(JSContext *cx, HandleObject obj, size_t protoChainDepth) |
|
3681 : ICStubCompiler(cx, ICStub::SetElem_DenseAdd), |
|
3682 obj_(cx, obj), |
|
3683 protoChainDepth_(protoChainDepth) |
|
3684 {} |
|
3685 |
|
3686 template <size_t ProtoChainDepth> |
|
3687 ICUpdatedStub *getStubSpecific(ICStubSpace *space, const AutoShapeVector *shapes); |
|
3688 |
|
3689 ICUpdatedStub *getStub(ICStubSpace *space); |
|
3690 }; |
|
3691 |
|
3692 class ICSetElem_TypedArray : public ICStub |
|
3693 { |
|
3694 friend class ICStubSpace; |
|
3695 |
|
3696 protected: // Protected to silence Clang warning. |
|
3697 HeapPtrShape shape_; |
|
3698 |
|
3699 ICSetElem_TypedArray(JitCode *stubCode, HandleShape shape, uint32_t type, |
|
3700 bool expectOutOfBounds); |
|
3701 |
|
3702 public: |
|
3703 static inline ICSetElem_TypedArray *New(ICStubSpace *space, JitCode *code, |
|
3704 HandleShape shape, uint32_t type, |
|
3705 bool expectOutOfBounds) |
|
3706 { |
|
3707 if (!code) |
|
3708 return nullptr; |
|
3709 return space->allocate<ICSetElem_TypedArray>(code, shape, type, expectOutOfBounds); |
|
3710 } |
|
3711 |
|
3712 uint32_t type() const { |
|
3713 return extra_ & 0xff; |
|
3714 } |
|
3715 |
|
3716 bool expectOutOfBounds() const { |
|
3717 return (extra_ >> 8) & 1; |
|
3718 } |
|
3719 |
|
3720 static size_t offsetOfShape() { |
|
3721 return offsetof(ICSetElem_TypedArray, shape_); |
|
3722 } |
|
3723 |
|
3724 HeapPtrShape &shape() { |
|
3725 return shape_; |
|
3726 } |
|
3727 |
|
3728 class Compiler : public ICStubCompiler { |
|
3729 RootedShape shape_; |
|
3730 uint32_t type_; |
|
3731 bool expectOutOfBounds_; |
|
3732 |
|
3733 protected: |
|
3734 bool generateStubCode(MacroAssembler &masm); |
|
3735 |
|
3736 virtual int32_t getKey() const { |
|
3737 return static_cast<int32_t>(kind) | (static_cast<int32_t>(type_) << 16) | |
|
3738 (static_cast<int32_t>(expectOutOfBounds_) << 24); |
|
3739 } |
|
3740 |
|
3741 public: |
|
3742 Compiler(JSContext *cx, Shape *shape, uint32_t type, bool expectOutOfBounds) |
|
3743 : ICStubCompiler(cx, ICStub::SetElem_TypedArray), |
|
3744 shape_(cx, shape), |
|
3745 type_(type), |
|
3746 expectOutOfBounds_(expectOutOfBounds) |
|
3747 {} |
|
3748 |
|
3749 ICStub *getStub(ICStubSpace *space) { |
|
3750 return ICSetElem_TypedArray::New(space, getStubCode(), shape_, type_, |
|
3751 expectOutOfBounds_); |
|
3752 } |
|
3753 }; |
|
3754 }; |
|
3755 |
|
3756 // In |
|
3757 // JSOP_IN |
|
3758 class ICIn_Fallback : public ICFallbackStub |
|
3759 { |
|
3760 friend class ICStubSpace; |
|
3761 |
|
3762 ICIn_Fallback(JitCode *stubCode) |
|
3763 : ICFallbackStub(ICStub::In_Fallback, stubCode) |
|
3764 { } |
|
3765 |
|
3766 public: |
|
3767 static inline ICIn_Fallback *New(ICStubSpace *space, JitCode *code) { |
|
3768 if (!code) |
|
3769 return nullptr; |
|
3770 return space->allocate<ICIn_Fallback>(code); |
|
3771 } |
|
3772 |
|
3773 class Compiler : public ICStubCompiler { |
|
3774 protected: |
|
3775 bool generateStubCode(MacroAssembler &masm); |
|
3776 |
|
3777 public: |
|
3778 Compiler(JSContext *cx) |
|
3779 : ICStubCompiler(cx, ICStub::In_Fallback) |
|
3780 { } |
|
3781 |
|
3782 ICStub *getStub(ICStubSpace *space) { |
|
3783 return ICIn_Fallback::New(space, getStubCode()); |
|
3784 } |
|
3785 }; |
|
3786 }; |
|
3787 |
|
3788 // GetName |
|
3789 // JSOP_NAME |
|
3790 // JSOP_GETGNAME |
|
3791 class ICGetName_Fallback : public ICMonitoredFallbackStub |
|
3792 { |
|
3793 friend class ICStubSpace; |
|
3794 |
|
3795 ICGetName_Fallback(JitCode *stubCode) |
|
3796 : ICMonitoredFallbackStub(ICStub::GetName_Fallback, stubCode) |
|
3797 { } |
|
3798 |
|
3799 public: |
|
3800 static const uint32_t MAX_OPTIMIZED_STUBS = 8; |
|
3801 |
|
3802 static inline ICGetName_Fallback *New(ICStubSpace *space, JitCode *code) { |
|
3803 if (!code) |
|
3804 return nullptr; |
|
3805 return space->allocate<ICGetName_Fallback>(code); |
|
3806 } |
|
3807 |
|
3808 class Compiler : public ICStubCompiler { |
|
3809 protected: |
|
3810 bool generateStubCode(MacroAssembler &masm); |
|
3811 |
|
3812 public: |
|
3813 Compiler(JSContext *cx) |
|
3814 : ICStubCompiler(cx, ICStub::GetName_Fallback) |
|
3815 { } |
|
3816 |
|
3817 ICStub *getStub(ICStubSpace *space) { |
|
3818 ICGetName_Fallback *stub = ICGetName_Fallback::New(space, getStubCode()); |
|
3819 if (!stub || !stub->initMonitoringChain(cx, space)) |
|
3820 return nullptr; |
|
3821 return stub; |
|
3822 } |
|
3823 }; |
|
3824 }; |
|
3825 |
|
3826 // Optimized GETGNAME/CALLGNAME stub. |
|
3827 class ICGetName_Global : public ICMonitoredStub |
|
3828 { |
|
3829 friend class ICStubSpace; |
|
3830 |
|
3831 protected: // Protected to silence Clang warning. |
|
3832 HeapPtrShape shape_; |
|
3833 uint32_t slot_; |
|
3834 |
|
3835 ICGetName_Global(JitCode *stubCode, ICStub *firstMonitorStub, HandleShape shape, uint32_t slot); |
|
3836 |
|
3837 public: |
|
3838 static inline ICGetName_Global *New(ICStubSpace *space, JitCode *code, ICStub *firstMonitorStub, |
|
3839 HandleShape shape, uint32_t slot) |
|
3840 { |
|
3841 if (!code) |
|
3842 return nullptr; |
|
3843 return space->allocate<ICGetName_Global>(code, firstMonitorStub, shape, slot); |
|
3844 } |
|
3845 |
|
3846 HeapPtrShape &shape() { |
|
3847 return shape_; |
|
3848 } |
|
3849 static size_t offsetOfShape() { |
|
3850 return offsetof(ICGetName_Global, shape_); |
|
3851 } |
|
3852 static size_t offsetOfSlot() { |
|
3853 return offsetof(ICGetName_Global, slot_); |
|
3854 } |
|
3855 |
|
3856 class Compiler : public ICStubCompiler { |
|
3857 ICStub *firstMonitorStub_; |
|
3858 RootedShape shape_; |
|
3859 uint32_t slot_; |
|
3860 |
|
3861 protected: |
|
3862 bool generateStubCode(MacroAssembler &masm); |
|
3863 |
|
3864 public: |
|
3865 Compiler(JSContext *cx, ICStub *firstMonitorStub, Shape *shape, uint32_t slot) |
|
3866 : ICStubCompiler(cx, ICStub::GetName_Global), |
|
3867 firstMonitorStub_(firstMonitorStub), |
|
3868 shape_(cx, shape), |
|
3869 slot_(slot) |
|
3870 {} |
|
3871 |
|
3872 ICStub *getStub(ICStubSpace *space) { |
|
3873 return ICGetName_Global::New(space, getStubCode(), firstMonitorStub_, shape_, slot_); |
|
3874 } |
|
3875 }; |
|
3876 }; |
|
3877 |
|
3878 // Optimized GETNAME/CALLNAME stub, making a variable number of hops to get an |
|
3879 // 'own' property off some scope object. Unlike GETPROP on an object's |
|
3880 // prototype, there is no teleporting optimization to take advantage of and |
|
3881 // shape checks are required all along the scope chain. |
|
3882 template <size_t NumHops> |
|
3883 class ICGetName_Scope : public ICMonitoredStub |
|
3884 { |
|
3885 friend class ICStubSpace; |
|
3886 |
|
3887 static const size_t MAX_HOPS = 6; |
|
3888 |
|
3889 mozilla::Array<HeapPtrShape, NumHops + 1> shapes_; |
|
3890 uint32_t offset_; |
|
3891 |
|
3892 ICGetName_Scope(JitCode *stubCode, ICStub *firstMonitorStub, |
|
3893 AutoShapeVector *shapes, uint32_t offset); |
|
3894 |
|
3895 static Kind GetStubKind() { |
|
3896 return (Kind) (GetName_Scope0 + NumHops); |
|
3897 } |
|
3898 |
|
3899 public: |
|
3900 static inline ICGetName_Scope *New(ICStubSpace *space, JitCode *code, ICStub *firstMonitorStub, |
|
3901 AutoShapeVector *shapes, uint32_t offset) |
|
3902 { |
|
3903 if (!code) |
|
3904 return nullptr; |
|
3905 return space->allocate<ICGetName_Scope<NumHops> >(code, firstMonitorStub, shapes, offset); |
|
3906 } |
|
3907 |
|
3908 void traceScopes(JSTracer *trc) { |
|
3909 for (size_t i = 0; i < NumHops + 1; i++) |
|
3910 MarkShape(trc, &shapes_[i], "baseline-scope-stub-shape"); |
|
3911 } |
|
3912 |
|
3913 static size_t offsetOfShape(size_t index) { |
|
3914 JS_ASSERT(index <= NumHops); |
|
3915 return offsetof(ICGetName_Scope, shapes_) + (index * sizeof(HeapPtrShape)); |
|
3916 } |
|
3917 static size_t offsetOfOffset() { |
|
3918 return offsetof(ICGetName_Scope, offset_); |
|
3919 } |
|
3920 |
|
3921 class Compiler : public ICStubCompiler { |
|
3922 ICStub *firstMonitorStub_; |
|
3923 AutoShapeVector *shapes_; |
|
3924 bool isFixedSlot_; |
|
3925 uint32_t offset_; |
|
3926 |
|
3927 protected: |
|
3928 bool generateStubCode(MacroAssembler &masm); |
|
3929 |
|
3930 protected: |
|
3931 virtual int32_t getKey() const { |
|
3932 return static_cast<int32_t>(kind) | (static_cast<int32_t>(isFixedSlot_) << 16); |
|
3933 } |
|
3934 |
|
3935 public: |
|
3936 Compiler(JSContext *cx, ICStub *firstMonitorStub, |
|
3937 AutoShapeVector *shapes, bool isFixedSlot, uint32_t offset) |
|
3938 : ICStubCompiler(cx, GetStubKind()), |
|
3939 firstMonitorStub_(firstMonitorStub), |
|
3940 shapes_(shapes), |
|
3941 isFixedSlot_(isFixedSlot), |
|
3942 offset_(offset) |
|
3943 { |
|
3944 } |
|
3945 |
|
3946 ICStub *getStub(ICStubSpace *space) { |
|
3947 return ICGetName_Scope::New(space, getStubCode(), firstMonitorStub_, shapes_, offset_); |
|
3948 } |
|
3949 }; |
|
3950 }; |
|
3951 |
|
3952 // BindName |
|
3953 // JSOP_BINDNAME |
|
3954 class ICBindName_Fallback : public ICFallbackStub |
|
3955 { |
|
3956 friend class ICStubSpace; |
|
3957 |
|
3958 ICBindName_Fallback(JitCode *stubCode) |
|
3959 : ICFallbackStub(ICStub::BindName_Fallback, stubCode) |
|
3960 { } |
|
3961 |
|
3962 public: |
|
3963 static inline ICBindName_Fallback *New(ICStubSpace *space, JitCode *code) { |
|
3964 if (!code) |
|
3965 return nullptr; |
|
3966 return space->allocate<ICBindName_Fallback>(code); |
|
3967 } |
|
3968 |
|
3969 class Compiler : public ICStubCompiler { |
|
3970 protected: |
|
3971 bool generateStubCode(MacroAssembler &masm); |
|
3972 |
|
3973 public: |
|
3974 Compiler(JSContext *cx) |
|
3975 : ICStubCompiler(cx, ICStub::BindName_Fallback) |
|
3976 { } |
|
3977 |
|
3978 ICStub *getStub(ICStubSpace *space) { |
|
3979 return ICBindName_Fallback::New(space, getStubCode()); |
|
3980 } |
|
3981 }; |
|
3982 }; |
|
3983 |
|
3984 // GetIntrinsic |
|
3985 // JSOP_GETINTRINSIC |
|
3986 class ICGetIntrinsic_Fallback : public ICMonitoredFallbackStub |
|
3987 { |
|
3988 friend class ICStubSpace; |
|
3989 |
|
3990 ICGetIntrinsic_Fallback(JitCode *stubCode) |
|
3991 : ICMonitoredFallbackStub(ICStub::GetIntrinsic_Fallback, stubCode) |
|
3992 { } |
|
3993 |
|
3994 public: |
|
3995 static inline ICGetIntrinsic_Fallback *New(ICStubSpace *space, JitCode *code) { |
|
3996 if (!code) |
|
3997 return nullptr; |
|
3998 return space->allocate<ICGetIntrinsic_Fallback>(code); |
|
3999 } |
|
4000 |
|
4001 class Compiler : public ICStubCompiler { |
|
4002 protected: |
|
4003 bool generateStubCode(MacroAssembler &masm); |
|
4004 |
|
4005 public: |
|
4006 Compiler(JSContext *cx) |
|
4007 : ICStubCompiler(cx, ICStub::GetIntrinsic_Fallback) |
|
4008 { } |
|
4009 |
|
4010 ICStub *getStub(ICStubSpace *space) { |
|
4011 ICGetIntrinsic_Fallback *stub = ICGetIntrinsic_Fallback::New(space, getStubCode()); |
|
4012 if (!stub || !stub->initMonitoringChain(cx, space)) |
|
4013 return nullptr; |
|
4014 return stub; |
|
4015 } |
|
4016 }; |
|
4017 }; |
|
4018 |
|
4019 // Stub that loads the constant result of a GETINTRINSIC operation. |
|
4020 class ICGetIntrinsic_Constant : public ICStub |
|
4021 { |
|
4022 friend class ICStubSpace; |
|
4023 |
|
4024 HeapValue value_; |
|
4025 |
|
4026 ICGetIntrinsic_Constant(JitCode *stubCode, HandleValue value); |
|
4027 ~ICGetIntrinsic_Constant(); |
|
4028 |
|
4029 public: |
|
4030 static inline ICGetIntrinsic_Constant *New(ICStubSpace *space, JitCode *code, |
|
4031 HandleValue value) |
|
4032 { |
|
4033 if (!code) |
|
4034 return nullptr; |
|
4035 return space->allocate<ICGetIntrinsic_Constant>(code, value); |
|
4036 } |
|
4037 |
|
4038 HeapValue &value() { |
|
4039 return value_; |
|
4040 } |
|
4041 static size_t offsetOfValue() { |
|
4042 return offsetof(ICGetIntrinsic_Constant, value_); |
|
4043 } |
|
4044 |
|
4045 class Compiler : public ICStubCompiler { |
|
4046 bool generateStubCode(MacroAssembler &masm); |
|
4047 |
|
4048 HandleValue value_; |
|
4049 |
|
4050 public: |
|
4051 Compiler(JSContext *cx, HandleValue value) |
|
4052 : ICStubCompiler(cx, ICStub::GetIntrinsic_Constant), |
|
4053 value_(value) |
|
4054 {} |
|
4055 |
|
4056 ICStub *getStub(ICStubSpace *space) { |
|
4057 return ICGetIntrinsic_Constant::New(space, getStubCode(), value_); |
|
4058 } |
|
4059 }; |
|
4060 }; |
|
4061 |
|
4062 class ICGetProp_Fallback : public ICMonitoredFallbackStub |
|
4063 { |
|
4064 friend class ICStubSpace; |
|
4065 |
|
4066 ICGetProp_Fallback(JitCode *stubCode) |
|
4067 : ICMonitoredFallbackStub(ICStub::GetProp_Fallback, stubCode) |
|
4068 { } |
|
4069 |
|
4070 public: |
|
4071 static const uint32_t MAX_OPTIMIZED_STUBS = 8; |
|
4072 |
|
4073 static inline ICGetProp_Fallback *New(ICStubSpace *space, JitCode *code) { |
|
4074 if (!code) |
|
4075 return nullptr; |
|
4076 return space->allocate<ICGetProp_Fallback>(code); |
|
4077 } |
|
4078 |
|
4079 static const size_t UNOPTIMIZABLE_ACCESS_BIT = 0; |
|
4080 static const size_t ACCESSED_GETTER_BIT = 1; |
|
4081 |
|
4082 void noteUnoptimizableAccess() { |
|
4083 extra_ |= (1u << UNOPTIMIZABLE_ACCESS_BIT); |
|
4084 } |
|
4085 bool hadUnoptimizableAccess() const { |
|
4086 return extra_ & (1u << UNOPTIMIZABLE_ACCESS_BIT); |
|
4087 } |
|
4088 |
|
4089 void noteAccessedGetter() { |
|
4090 extra_ |= (1u << ACCESSED_GETTER_BIT); |
|
4091 } |
|
4092 bool hasAccessedGetter() const { |
|
4093 return extra_ & (1u << ACCESSED_GETTER_BIT); |
|
4094 } |
|
4095 |
|
4096 class Compiler : public ICStubCompiler { |
|
4097 protected: |
|
4098 uint32_t returnFromIonOffset_; |
|
4099 uint32_t returnFromStubOffset_; |
|
4100 bool generateStubCode(MacroAssembler &masm); |
|
4101 bool postGenerateStubCode(MacroAssembler &masm, Handle<JitCode *> code); |
|
4102 |
|
4103 public: |
|
4104 Compiler(JSContext *cx) |
|
4105 : ICStubCompiler(cx, ICStub::GetProp_Fallback) |
|
4106 { } |
|
4107 |
|
4108 ICStub *getStub(ICStubSpace *space) { |
|
4109 ICGetProp_Fallback *stub = ICGetProp_Fallback::New(space, getStubCode()); |
|
4110 if (!stub || !stub->initMonitoringChain(cx, space)) |
|
4111 return nullptr; |
|
4112 return stub; |
|
4113 } |
|
4114 }; |
|
4115 }; |
|
4116 |
|
4117 // Stub for accessing a dense array's length. |
|
4118 class ICGetProp_ArrayLength : public ICStub |
|
4119 { |
|
4120 friend class ICStubSpace; |
|
4121 |
|
4122 ICGetProp_ArrayLength(JitCode *stubCode) |
|
4123 : ICStub(GetProp_ArrayLength, stubCode) |
|
4124 {} |
|
4125 |
|
4126 public: |
|
4127 static inline ICGetProp_ArrayLength *New(ICStubSpace *space, JitCode *code) { |
|
4128 if (!code) |
|
4129 return nullptr; |
|
4130 return space->allocate<ICGetProp_ArrayLength>(code); |
|
4131 } |
|
4132 |
|
4133 class Compiler : public ICStubCompiler { |
|
4134 bool generateStubCode(MacroAssembler &masm); |
|
4135 |
|
4136 public: |
|
4137 Compiler(JSContext *cx) |
|
4138 : ICStubCompiler(cx, ICStub::GetProp_ArrayLength) |
|
4139 {} |
|
4140 |
|
4141 ICStub *getStub(ICStubSpace *space) { |
|
4142 return ICGetProp_ArrayLength::New(space, getStubCode()); |
|
4143 } |
|
4144 }; |
|
4145 }; |
|
4146 |
|
4147 // Stub for accessing a typed array's length. |
|
4148 class ICGetProp_TypedArrayLength : public ICStub |
|
4149 { |
|
4150 friend class ICStubSpace; |
|
4151 |
|
4152 ICGetProp_TypedArrayLength(JitCode *stubCode) |
|
4153 : ICStub(GetProp_TypedArrayLength, stubCode) |
|
4154 {} |
|
4155 |
|
4156 public: |
|
4157 static inline ICGetProp_TypedArrayLength *New(ICStubSpace *space, JitCode *code) { |
|
4158 if (!code) |
|
4159 return nullptr; |
|
4160 return space->allocate<ICGetProp_TypedArrayLength>(code); |
|
4161 } |
|
4162 |
|
4163 class Compiler : public ICStubCompiler { |
|
4164 bool generateStubCode(MacroAssembler &masm); |
|
4165 |
|
4166 public: |
|
4167 Compiler(JSContext *cx) |
|
4168 : ICStubCompiler(cx, ICStub::GetProp_TypedArrayLength) |
|
4169 {} |
|
4170 |
|
4171 ICStub *getStub(ICStubSpace *space) { |
|
4172 return ICGetProp_TypedArrayLength::New(space, getStubCode()); |
|
4173 } |
|
4174 }; |
|
4175 }; |
|
4176 |
|
4177 // Stub for accessing a property on a primitive's prototype. |
|
4178 class ICGetProp_Primitive : public ICMonitoredStub |
|
4179 { |
|
4180 friend class ICStubSpace; |
|
4181 |
|
4182 protected: // Protected to silence Clang warning. |
|
4183 // Shape of String.prototype/Number.prototype to check for. |
|
4184 HeapPtrShape protoShape_; |
|
4185 |
|
4186 // Fixed or dynamic slot offset. |
|
4187 uint32_t offset_; |
|
4188 |
|
4189 ICGetProp_Primitive(JitCode *stubCode, ICStub *firstMonitorStub, |
|
4190 HandleShape protoShape, uint32_t offset); |
|
4191 |
|
4192 public: |
|
4193 static inline ICGetProp_Primitive *New(ICStubSpace *space, JitCode *code, ICStub *firstMonitorStub, |
|
4194 HandleShape protoShape, uint32_t offset) |
|
4195 { |
|
4196 if (!code) |
|
4197 return nullptr; |
|
4198 return space->allocate<ICGetProp_Primitive>(code, firstMonitorStub, protoShape, offset); |
|
4199 } |
|
4200 |
|
4201 HeapPtrShape &protoShape() { |
|
4202 return protoShape_; |
|
4203 } |
|
4204 static size_t offsetOfProtoShape() { |
|
4205 return offsetof(ICGetProp_Primitive, protoShape_); |
|
4206 } |
|
4207 |
|
4208 static size_t offsetOfOffset() { |
|
4209 return offsetof(ICGetProp_Primitive, offset_); |
|
4210 } |
|
4211 |
|
4212 class Compiler : public ICStubCompiler { |
|
4213 ICStub *firstMonitorStub_; |
|
4214 JSValueType primitiveType_; |
|
4215 RootedObject prototype_; |
|
4216 bool isFixedSlot_; |
|
4217 uint32_t offset_; |
|
4218 |
|
4219 bool generateStubCode(MacroAssembler &masm); |
|
4220 |
|
4221 protected: |
|
4222 virtual int32_t getKey() const { |
|
4223 static_assert(sizeof(JSValueType) == 1, "JSValueType should fit in one byte"); |
|
4224 return static_cast<int32_t>(kind) |
|
4225 | (static_cast<int32_t>(isFixedSlot_) << 16) |
|
4226 | (static_cast<int32_t>(primitiveType_) << 24); |
|
4227 } |
|
4228 |
|
4229 public: |
|
4230 Compiler(JSContext *cx, ICStub *firstMonitorStub, JSValueType primitiveType, |
|
4231 HandleObject prototype, bool isFixedSlot, uint32_t offset) |
|
4232 : ICStubCompiler(cx, ICStub::GetProp_Primitive), |
|
4233 firstMonitorStub_(firstMonitorStub), |
|
4234 primitiveType_(primitiveType), |
|
4235 prototype_(cx, prototype), |
|
4236 isFixedSlot_(isFixedSlot), |
|
4237 offset_(offset) |
|
4238 {} |
|
4239 |
|
4240 ICStub *getStub(ICStubSpace *space) { |
|
4241 RootedShape protoShape(cx, prototype_->lastProperty()); |
|
4242 return ICGetProp_Primitive::New(space, getStubCode(), firstMonitorStub_, |
|
4243 protoShape, offset_); |
|
4244 } |
|
4245 }; |
|
4246 }; |
|
4247 |
|
4248 // Stub for accessing a string's length. |
|
4249 class ICGetProp_StringLength : public ICStub |
|
4250 { |
|
4251 friend class ICStubSpace; |
|
4252 |
|
4253 ICGetProp_StringLength(JitCode *stubCode) |
|
4254 : ICStub(GetProp_StringLength, stubCode) |
|
4255 {} |
|
4256 |
|
4257 public: |
|
4258 static inline ICGetProp_StringLength *New(ICStubSpace *space, JitCode *code) { |
|
4259 if (!code) |
|
4260 return nullptr; |
|
4261 return space->allocate<ICGetProp_StringLength>(code); |
|
4262 } |
|
4263 |
|
4264 class Compiler : public ICStubCompiler { |
|
4265 bool generateStubCode(MacroAssembler &masm); |
|
4266 |
|
4267 public: |
|
4268 Compiler(JSContext *cx) |
|
4269 : ICStubCompiler(cx, ICStub::GetProp_StringLength) |
|
4270 {} |
|
4271 |
|
4272 ICStub *getStub(ICStubSpace *space) { |
|
4273 return ICGetProp_StringLength::New(space, getStubCode()); |
|
4274 } |
|
4275 }; |
|
4276 }; |
|
4277 |
|
4278 // Base class for GetProp_Native and GetProp_NativePrototype stubs. |
|
4279 class ICGetPropNativeStub : public ICMonitoredStub |
|
4280 { |
|
4281 // Object shape (lastProperty). |
|
4282 HeapPtrShape shape_; |
|
4283 |
|
4284 // Fixed or dynamic slot offset. |
|
4285 uint32_t offset_; |
|
4286 |
|
4287 protected: |
|
4288 ICGetPropNativeStub(ICStub::Kind kind, JitCode *stubCode, ICStub *firstMonitorStub, |
|
4289 HandleShape shape, uint32_t offset); |
|
4290 |
|
4291 public: |
|
4292 HeapPtrShape &shape() { |
|
4293 return shape_; |
|
4294 } |
|
4295 uint32_t offset() const { |
|
4296 return offset_; |
|
4297 } |
|
4298 static size_t offsetOfShape() { |
|
4299 return offsetof(ICGetPropNativeStub, shape_); |
|
4300 } |
|
4301 static size_t offsetOfOffset() { |
|
4302 return offsetof(ICGetPropNativeStub, offset_); |
|
4303 } |
|
4304 }; |
|
4305 |
|
4306 // Stub for accessing an own property on a native object. |
|
4307 class ICGetProp_Native : public ICGetPropNativeStub |
|
4308 { |
|
4309 friend class ICStubSpace; |
|
4310 |
|
4311 ICGetProp_Native(JitCode *stubCode, ICStub *firstMonitorStub, HandleShape shape, |
|
4312 uint32_t offset) |
|
4313 : ICGetPropNativeStub(GetProp_Native, stubCode, firstMonitorStub, shape, offset) |
|
4314 {} |
|
4315 |
|
4316 public: |
|
4317 static inline ICGetProp_Native *New(ICStubSpace *space, JitCode *code, |
|
4318 ICStub *firstMonitorStub, HandleShape shape, |
|
4319 uint32_t offset) |
|
4320 { |
|
4321 if (!code) |
|
4322 return nullptr; |
|
4323 return space->allocate<ICGetProp_Native>(code, firstMonitorStub, shape, offset); |
|
4324 } |
|
4325 }; |
|
4326 |
|
4327 // Stub for accessing a property on a native object's prototype. Note that due to |
|
4328 // the shape teleporting optimization, we only have to guard on the object's shape |
|
4329 // and the holder's shape. |
|
4330 class ICGetProp_NativePrototype : public ICGetPropNativeStub |
|
4331 { |
|
4332 friend class ICStubSpace; |
|
4333 |
|
4334 protected: |
|
4335 // Holder and its shape. |
|
4336 HeapPtrObject holder_; |
|
4337 HeapPtrShape holderShape_; |
|
4338 |
|
4339 ICGetProp_NativePrototype(JitCode *stubCode, ICStub *firstMonitorStub, HandleShape shape, |
|
4340 uint32_t offset, HandleObject holder, HandleShape holderShape); |
|
4341 |
|
4342 public: |
|
4343 static inline ICGetProp_NativePrototype *New(ICStubSpace *space, JitCode *code, |
|
4344 ICStub *firstMonitorStub, HandleShape shape, |
|
4345 uint32_t offset, HandleObject holder, |
|
4346 HandleShape holderShape) |
|
4347 { |
|
4348 if (!code) |
|
4349 return nullptr; |
|
4350 return space->allocate<ICGetProp_NativePrototype>(code, firstMonitorStub, shape, offset, |
|
4351 holder, holderShape); |
|
4352 } |
|
4353 |
|
4354 public: |
|
4355 HeapPtrObject &holder() { |
|
4356 return holder_; |
|
4357 } |
|
4358 HeapPtrShape &holderShape() { |
|
4359 return holderShape_; |
|
4360 } |
|
4361 static size_t offsetOfHolder() { |
|
4362 return offsetof(ICGetProp_NativePrototype, holder_); |
|
4363 } |
|
4364 static size_t offsetOfHolderShape() { |
|
4365 return offsetof(ICGetProp_NativePrototype, holderShape_); |
|
4366 } |
|
4367 }; |
|
4368 |
|
4369 |
|
4370 // Compiler for GetProp_Native and GetProp_NativePrototype stubs. |
|
4371 class ICGetPropNativeCompiler : public ICStubCompiler |
|
4372 { |
|
4373 bool isCallProp_; |
|
4374 ICStub *firstMonitorStub_; |
|
4375 HandleObject obj_; |
|
4376 HandleObject holder_; |
|
4377 HandlePropertyName propName_; |
|
4378 bool isFixedSlot_; |
|
4379 uint32_t offset_; |
|
4380 |
|
4381 bool generateStubCode(MacroAssembler &masm); |
|
4382 |
|
4383 protected: |
|
4384 virtual int32_t getKey() const { |
|
4385 #if JS_HAS_NO_SUCH_METHOD |
|
4386 return static_cast<int32_t>(kind) | |
|
4387 (static_cast<int32_t>(isCallProp_) << 16) | |
|
4388 (static_cast<int32_t>(isFixedSlot_) << 17); |
|
4389 #else |
|
4390 return static_cast<int32_t>(kind) | (static_cast<int32_t>(isFixedSlot_) << 16); |
|
4391 #endif |
|
4392 } |
|
4393 |
|
4394 public: |
|
4395 ICGetPropNativeCompiler(JSContext *cx, ICStub::Kind kind, bool isCallProp, |
|
4396 ICStub *firstMonitorStub, HandleObject obj, HandleObject holder, |
|
4397 HandlePropertyName propName, bool isFixedSlot, uint32_t offset) |
|
4398 : ICStubCompiler(cx, kind), |
|
4399 isCallProp_(isCallProp), |
|
4400 firstMonitorStub_(firstMonitorStub), |
|
4401 obj_(obj), |
|
4402 holder_(holder), |
|
4403 propName_(propName), |
|
4404 isFixedSlot_(isFixedSlot), |
|
4405 offset_(offset) |
|
4406 {} |
|
4407 |
|
4408 ICStub *getStub(ICStubSpace *space) { |
|
4409 RootedShape shape(cx, obj_->lastProperty()); |
|
4410 if (kind == ICStub::GetProp_Native) { |
|
4411 JS_ASSERT(obj_ == holder_); |
|
4412 return ICGetProp_Native::New(space, getStubCode(), firstMonitorStub_, shape, offset_); |
|
4413 } |
|
4414 |
|
4415 JS_ASSERT(obj_ != holder_); |
|
4416 JS_ASSERT(kind == ICStub::GetProp_NativePrototype); |
|
4417 RootedShape holderShape(cx, holder_->lastProperty()); |
|
4418 return ICGetProp_NativePrototype::New(space, getStubCode(), firstMonitorStub_, shape, |
|
4419 offset_, holder_, holderShape); |
|
4420 } |
|
4421 }; |
|
4422 |
|
4423 class ICGetPropCallGetter : public ICMonitoredStub |
|
4424 { |
|
4425 friend class ICStubSpace; |
|
4426 |
|
4427 protected: |
|
4428 // We don't strictly need this for own property getters, but we need it to do |
|
4429 // Ion optimizations, so we should keep it around. |
|
4430 HeapPtrObject holder_; |
|
4431 |
|
4432 HeapPtrShape holderShape_; |
|
4433 |
|
4434 // Function to call. |
|
4435 HeapPtrFunction getter_; |
|
4436 |
|
4437 // PC offset of call |
|
4438 uint32_t pcOffset_; |
|
4439 |
|
4440 ICGetPropCallGetter(Kind kind, JitCode *stubCode, ICStub *firstMonitorStub, HandleObject holder, |
|
4441 HandleShape holderShape, HandleFunction getter, uint32_t pcOffset); |
|
4442 |
|
4443 public: |
|
4444 HeapPtrObject &holder() { |
|
4445 return holder_; |
|
4446 } |
|
4447 HeapPtrShape &holderShape() { |
|
4448 return holderShape_; |
|
4449 } |
|
4450 HeapPtrFunction &getter() { |
|
4451 return getter_; |
|
4452 } |
|
4453 |
|
4454 static size_t offsetOfHolder() { |
|
4455 return offsetof(ICGetPropCallGetter, holder_); |
|
4456 } |
|
4457 static size_t offsetOfHolderShape() { |
|
4458 return offsetof(ICGetPropCallGetter, holderShape_); |
|
4459 } |
|
4460 static size_t offsetOfGetter() { |
|
4461 return offsetof(ICGetPropCallGetter, getter_); |
|
4462 } |
|
4463 static size_t offsetOfPCOffset() { |
|
4464 return offsetof(ICGetPropCallGetter, pcOffset_); |
|
4465 } |
|
4466 |
|
4467 class Compiler : public ICStubCompiler { |
|
4468 protected: |
|
4469 ICStub *firstMonitorStub_; |
|
4470 RootedObject holder_; |
|
4471 RootedFunction getter_; |
|
4472 uint32_t pcOffset_; |
|
4473 |
|
4474 public: |
|
4475 Compiler(JSContext *cx, ICStub::Kind kind, ICStub *firstMonitorStub, |
|
4476 HandleObject holder, HandleFunction getter, uint32_t pcOffset) |
|
4477 : ICStubCompiler(cx, kind), |
|
4478 firstMonitorStub_(firstMonitorStub), |
|
4479 holder_(cx, holder), |
|
4480 getter_(cx, getter), |
|
4481 pcOffset_(pcOffset) |
|
4482 { |
|
4483 JS_ASSERT(kind == ICStub::GetProp_CallScripted || |
|
4484 kind == ICStub::GetProp_CallNative || |
|
4485 kind == ICStub::GetProp_CallNativePrototype); |
|
4486 } |
|
4487 }; |
|
4488 }; |
|
4489 |
|
4490 // Stub for calling a getter (native or scripted) on a native object when the getter is kept on |
|
4491 // the proto-chain. |
|
4492 class ICGetPropCallPrototypeGetter : public ICGetPropCallGetter |
|
4493 { |
|
4494 friend class ICStubSpace; |
|
4495 |
|
4496 protected: |
|
4497 // shape of receiver object. |
|
4498 HeapPtrShape receiverShape_; |
|
4499 |
|
4500 ICGetPropCallPrototypeGetter(Kind kind, JitCode *stubCode, ICStub *firstMonitorStub, |
|
4501 HandleShape receiverShape, |
|
4502 HandleObject holder, HandleShape holderShape, |
|
4503 HandleFunction getter, uint32_t pcOffset); |
|
4504 |
|
4505 public: |
|
4506 HeapPtrShape &receiverShape() { |
|
4507 return receiverShape_; |
|
4508 } |
|
4509 |
|
4510 static size_t offsetOfReceiverShape() { |
|
4511 return offsetof(ICGetPropCallPrototypeGetter, receiverShape_); |
|
4512 } |
|
4513 |
|
4514 class Compiler : public ICGetPropCallGetter::Compiler { |
|
4515 protected: |
|
4516 RootedObject receiver_; |
|
4517 |
|
4518 public: |
|
4519 Compiler(JSContext *cx, ICStub::Kind kind, ICStub *firstMonitorStub, |
|
4520 HandleObject obj, HandleObject holder, HandleFunction getter, uint32_t pcOffset) |
|
4521 : ICGetPropCallGetter::Compiler(cx, kind, firstMonitorStub, holder, getter, pcOffset), |
|
4522 receiver_(cx, obj) |
|
4523 { |
|
4524 JS_ASSERT(kind == ICStub::GetProp_CallScripted || |
|
4525 kind == ICStub::GetProp_CallNativePrototype); |
|
4526 } |
|
4527 }; |
|
4528 }; |
|
4529 |
|
4530 // Stub for calling a scripted getter on a native object when the getter is kept on the |
|
4531 // proto-chain. |
|
4532 class ICGetProp_CallScripted : public ICGetPropCallPrototypeGetter |
|
4533 { |
|
4534 friend class ICStubSpace; |
|
4535 |
|
4536 protected: |
|
4537 ICGetProp_CallScripted(JitCode *stubCode, ICStub *firstMonitorStub, |
|
4538 HandleShape receiverShape, HandleObject holder, HandleShape holderShape, |
|
4539 HandleFunction getter, uint32_t pcOffset) |
|
4540 : ICGetPropCallPrototypeGetter(GetProp_CallScripted, stubCode, firstMonitorStub, |
|
4541 receiverShape, holder, holderShape, getter, pcOffset) |
|
4542 {} |
|
4543 |
|
4544 public: |
|
4545 static inline ICGetProp_CallScripted *New( |
|
4546 ICStubSpace *space, JitCode *code, ICStub *firstMonitorStub, |
|
4547 HandleShape receiverShape, HandleObject holder, HandleShape holderShape, |
|
4548 HandleFunction getter, uint32_t pcOffset) |
|
4549 { |
|
4550 if (!code) |
|
4551 return nullptr; |
|
4552 return space->allocate<ICGetProp_CallScripted>(code, firstMonitorStub, |
|
4553 receiverShape, holder, holderShape, getter, |
|
4554 pcOffset); |
|
4555 } |
|
4556 |
|
4557 class Compiler : public ICGetPropCallPrototypeGetter::Compiler { |
|
4558 protected: |
|
4559 bool generateStubCode(MacroAssembler &masm); |
|
4560 |
|
4561 public: |
|
4562 Compiler(JSContext *cx, ICStub *firstMonitorStub, HandleObject obj, |
|
4563 HandleObject holder, HandleFunction getter, uint32_t pcOffset) |
|
4564 : ICGetPropCallPrototypeGetter::Compiler(cx, ICStub::GetProp_CallScripted, |
|
4565 firstMonitorStub, obj, holder, |
|
4566 getter, pcOffset) |
|
4567 {} |
|
4568 |
|
4569 ICStub *getStub(ICStubSpace *space) { |
|
4570 RootedShape receiverShape(cx, receiver_->lastProperty()); |
|
4571 RootedShape holderShape(cx, holder_->lastProperty()); |
|
4572 return ICGetProp_CallScripted::New(space, getStubCode(), firstMonitorStub_, receiverShape, |
|
4573 holder_, holderShape, getter_, pcOffset_); |
|
4574 } |
|
4575 }; |
|
4576 }; |
|
4577 |
|
4578 // Stub for calling an own native getter on a native object. |
|
4579 class ICGetProp_CallNative : public ICGetPropCallGetter |
|
4580 { |
|
4581 friend class ICStubSpace; |
|
4582 |
|
4583 protected: |
|
4584 |
|
4585 ICGetProp_CallNative(JitCode *stubCode, ICStub *firstMonitorStub, HandleObject obj, |
|
4586 HandleShape shape, HandleFunction getter, uint32_t pcOffset) |
|
4587 : ICGetPropCallGetter(GetProp_CallNative, stubCode, firstMonitorStub, obj, shape, |
|
4588 getter, pcOffset) |
|
4589 { } |
|
4590 |
|
4591 public: |
|
4592 static inline ICGetProp_CallNative *New(ICStubSpace *space, JitCode *code, |
|
4593 ICStub *firstMonitorStub, HandleObject obj, |
|
4594 HandleShape shape, HandleFunction getter, |
|
4595 uint32_t pcOffset) |
|
4596 { |
|
4597 if (!code) |
|
4598 return nullptr; |
|
4599 return space->allocate<ICGetProp_CallNative>(code, firstMonitorStub, obj, shape, |
|
4600 getter, pcOffset); |
|
4601 } |
|
4602 |
|
4603 class Compiler : public ICGetPropCallGetter::Compiler |
|
4604 { |
|
4605 bool inputDefinitelyObject_; |
|
4606 protected: |
|
4607 bool generateStubCode(MacroAssembler &masm); |
|
4608 |
|
4609 virtual int32_t getKey() const { |
|
4610 return static_cast<int32_t>(kind) | |
|
4611 (static_cast<int32_t>(inputDefinitelyObject_) << 16); |
|
4612 } |
|
4613 |
|
4614 public: |
|
4615 Compiler(JSContext *cx, ICStub *firstMonitorStub, HandleObject obj, |
|
4616 HandleFunction getter, uint32_t pcOffset, bool inputDefinitelyObject = false) |
|
4617 : ICGetPropCallGetter::Compiler(cx, ICStub::GetProp_CallNative, firstMonitorStub, |
|
4618 obj, getter, pcOffset), |
|
4619 inputDefinitelyObject_(inputDefinitelyObject) |
|
4620 {} |
|
4621 |
|
4622 ICStub *getStub(ICStubSpace *space) { |
|
4623 RootedShape shape(cx, holder_->lastProperty()); |
|
4624 return ICGetProp_CallNative::New(space, getStubCode(), firstMonitorStub_, holder_, |
|
4625 shape, getter_, pcOffset_); |
|
4626 } |
|
4627 }; |
|
4628 }; |
|
4629 |
|
4630 // Stub for calling an native getter on a native object when the getter is kept on the proto-chain. |
|
4631 class ICGetProp_CallNativePrototype : public ICGetPropCallPrototypeGetter |
|
4632 { |
|
4633 friend class ICStubSpace; |
|
4634 |
|
4635 protected: |
|
4636 ICGetProp_CallNativePrototype(JitCode *stubCode, ICStub *firstMonitorStub, |
|
4637 HandleShape receiverShape, HandleObject holder, HandleShape holderShape, |
|
4638 HandleFunction getter, uint32_t pcOffset) |
|
4639 : ICGetPropCallPrototypeGetter(GetProp_CallNativePrototype, stubCode, firstMonitorStub, |
|
4640 receiverShape, holder, holderShape, getter, pcOffset) |
|
4641 {} |
|
4642 |
|
4643 public: |
|
4644 static inline ICGetProp_CallNativePrototype *New( |
|
4645 ICStubSpace *space, JitCode *code, ICStub *firstMonitorStub, |
|
4646 HandleShape receiverShape, HandleObject holder, HandleShape holderShape, |
|
4647 HandleFunction getter, uint32_t pcOffset) |
|
4648 { |
|
4649 if (!code) |
|
4650 return nullptr; |
|
4651 return space->allocate<ICGetProp_CallNativePrototype>(code, firstMonitorStub, |
|
4652 receiverShape, holder, holderShape, |
|
4653 getter, pcOffset); |
|
4654 } |
|
4655 |
|
4656 class Compiler : public ICGetPropCallPrototypeGetter::Compiler { |
|
4657 protected: |
|
4658 bool generateStubCode(MacroAssembler &masm); |
|
4659 |
|
4660 public: |
|
4661 Compiler(JSContext *cx, ICStub *firstMonitorStub, HandleObject obj, |
|
4662 HandleObject holder, HandleFunction getter, uint32_t pcOffset) |
|
4663 : ICGetPropCallPrototypeGetter::Compiler(cx, ICStub::GetProp_CallNativePrototype, |
|
4664 firstMonitorStub, obj, holder, |
|
4665 getter, pcOffset) |
|
4666 {} |
|
4667 |
|
4668 ICStub *getStub(ICStubSpace *space) { |
|
4669 RootedShape receiverShape(cx, receiver_->lastProperty()); |
|
4670 RootedShape holderShape(cx, holder_->lastProperty()); |
|
4671 return ICGetProp_CallNativePrototype::New(space, getStubCode(), firstMonitorStub_, receiverShape, |
|
4672 holder_, holderShape, getter_, pcOffset_); |
|
4673 } |
|
4674 }; |
|
4675 }; |
|
4676 |
|
4677 class ICGetPropCallDOMProxyNativeStub : public ICMonitoredStub |
|
4678 { |
|
4679 friend class ICStubSpace; |
|
4680 protected: |
|
4681 // Shape of the DOMProxy |
|
4682 HeapPtrShape shape_; |
|
4683 |
|
4684 // Proxy handler to check against. |
|
4685 BaseProxyHandler *proxyHandler_; |
|
4686 |
|
4687 // Object shape of expected expando object. (nullptr if no expando object should be there) |
|
4688 HeapPtrShape expandoShape_; |
|
4689 |
|
4690 // Holder and its shape. |
|
4691 HeapPtrObject holder_; |
|
4692 HeapPtrShape holderShape_; |
|
4693 |
|
4694 // Function to call. |
|
4695 HeapPtrFunction getter_; |
|
4696 |
|
4697 // PC offset of call |
|
4698 uint32_t pcOffset_; |
|
4699 |
|
4700 ICGetPropCallDOMProxyNativeStub(ICStub::Kind kind, JitCode *stubCode, |
|
4701 ICStub *firstMonitorStub, HandleShape shape, |
|
4702 BaseProxyHandler *proxyHandler, HandleShape expandoShape, |
|
4703 HandleObject holder, HandleShape holderShape, |
|
4704 HandleFunction getter, uint32_t pcOffset); |
|
4705 |
|
4706 public: |
|
4707 HeapPtrShape &shape() { |
|
4708 return shape_; |
|
4709 } |
|
4710 HeapPtrShape &expandoShape() { |
|
4711 return expandoShape_; |
|
4712 } |
|
4713 HeapPtrObject &holder() { |
|
4714 return holder_; |
|
4715 } |
|
4716 HeapPtrShape &holderShape() { |
|
4717 return holderShape_; |
|
4718 } |
|
4719 HeapPtrFunction &getter() { |
|
4720 return getter_; |
|
4721 } |
|
4722 uint32_t pcOffset() const { |
|
4723 return pcOffset_; |
|
4724 } |
|
4725 |
|
4726 static size_t offsetOfShape() { |
|
4727 return offsetof(ICGetPropCallDOMProxyNativeStub, shape_); |
|
4728 } |
|
4729 static size_t offsetOfProxyHandler() { |
|
4730 return offsetof(ICGetPropCallDOMProxyNativeStub, proxyHandler_); |
|
4731 } |
|
4732 static size_t offsetOfExpandoShape() { |
|
4733 return offsetof(ICGetPropCallDOMProxyNativeStub, expandoShape_); |
|
4734 } |
|
4735 static size_t offsetOfHolder() { |
|
4736 return offsetof(ICGetPropCallDOMProxyNativeStub, holder_); |
|
4737 } |
|
4738 static size_t offsetOfHolderShape() { |
|
4739 return offsetof(ICGetPropCallDOMProxyNativeStub, holderShape_); |
|
4740 } |
|
4741 static size_t offsetOfGetter() { |
|
4742 return offsetof(ICGetPropCallDOMProxyNativeStub, getter_); |
|
4743 } |
|
4744 static size_t offsetOfPCOffset() { |
|
4745 return offsetof(ICGetPropCallDOMProxyNativeStub, pcOffset_); |
|
4746 } |
|
4747 }; |
|
4748 |
|
4749 class ICGetProp_CallDOMProxyNative : public ICGetPropCallDOMProxyNativeStub |
|
4750 { |
|
4751 friend class ICStubSpace; |
|
4752 ICGetProp_CallDOMProxyNative(JitCode *stubCode, ICStub *firstMonitorStub, HandleShape shape, |
|
4753 BaseProxyHandler *proxyHandler, HandleShape expandoShape, |
|
4754 HandleObject holder, HandleShape holderShape, |
|
4755 HandleFunction getter, uint32_t pcOffset) |
|
4756 : ICGetPropCallDOMProxyNativeStub(ICStub::GetProp_CallDOMProxyNative, stubCode, |
|
4757 firstMonitorStub, shape, proxyHandler, expandoShape, |
|
4758 holder, holderShape, getter, pcOffset) |
|
4759 {} |
|
4760 |
|
4761 public: |
|
4762 static inline ICGetProp_CallDOMProxyNative *New( |
|
4763 ICStubSpace *space, JitCode *code, ICStub *firstMonitorStub, |
|
4764 HandleShape shape, BaseProxyHandler *proxyHandler, |
|
4765 HandleShape expandoShape, HandleObject holder, HandleShape holderShape, |
|
4766 HandleFunction getter, uint32_t pcOffset) |
|
4767 { |
|
4768 if (!code) |
|
4769 return nullptr; |
|
4770 return space->allocate<ICGetProp_CallDOMProxyNative>(code, firstMonitorStub, shape, |
|
4771 proxyHandler, expandoShape, holder, |
|
4772 holderShape, getter, pcOffset); |
|
4773 } |
|
4774 }; |
|
4775 |
|
4776 class ICGetProp_CallDOMProxyWithGenerationNative : public ICGetPropCallDOMProxyNativeStub |
|
4777 { |
|
4778 protected: |
|
4779 ExpandoAndGeneration *expandoAndGeneration_; |
|
4780 uint32_t generation_; |
|
4781 |
|
4782 public: |
|
4783 ICGetProp_CallDOMProxyWithGenerationNative(JitCode *stubCode, ICStub *firstMonitorStub, |
|
4784 HandleShape shape, BaseProxyHandler *proxyHandler, |
|
4785 ExpandoAndGeneration *expandoAndGeneration, |
|
4786 uint32_t generation, HandleShape expandoShape, |
|
4787 HandleObject holder, HandleShape holderShape, |
|
4788 HandleFunction getter, uint32_t pcOffset) |
|
4789 : ICGetPropCallDOMProxyNativeStub(ICStub::GetProp_CallDOMProxyWithGenerationNative, |
|
4790 stubCode, firstMonitorStub, shape, proxyHandler, |
|
4791 expandoShape, holder, holderShape, getter, pcOffset), |
|
4792 expandoAndGeneration_(expandoAndGeneration), |
|
4793 generation_(generation) |
|
4794 { |
|
4795 } |
|
4796 |
|
4797 static inline ICGetProp_CallDOMProxyWithGenerationNative *New( |
|
4798 ICStubSpace *space, JitCode *code, ICStub *firstMonitorStub, |
|
4799 HandleShape shape, BaseProxyHandler *proxyHandler, |
|
4800 ExpandoAndGeneration *expandoAndGeneration, uint32_t generation, |
|
4801 HandleShape expandoShape, HandleObject holder, HandleShape holderShape, |
|
4802 HandleFunction getter, uint32_t pcOffset) |
|
4803 { |
|
4804 if (!code) |
|
4805 return nullptr; |
|
4806 return space->allocate<ICGetProp_CallDOMProxyWithGenerationNative>(code, firstMonitorStub, |
|
4807 shape, proxyHandler, expandoAndGeneration, |
|
4808 generation, expandoShape, holder, holderShape, |
|
4809 getter, pcOffset); |
|
4810 } |
|
4811 |
|
4812 void *expandoAndGeneration() const { |
|
4813 return expandoAndGeneration_; |
|
4814 } |
|
4815 uint32_t generation() const { |
|
4816 return generation_; |
|
4817 } |
|
4818 |
|
4819 void setGeneration(uint32_t value) { |
|
4820 generation_ = value; |
|
4821 } |
|
4822 |
|
4823 static size_t offsetOfInternalStruct() { |
|
4824 return offsetof(ICGetProp_CallDOMProxyWithGenerationNative, expandoAndGeneration_); |
|
4825 } |
|
4826 static size_t offsetOfGeneration() { |
|
4827 return offsetof(ICGetProp_CallDOMProxyWithGenerationNative, generation_); |
|
4828 } |
|
4829 }; |
|
4830 |
|
4831 class ICGetPropCallDOMProxyNativeCompiler : public ICStubCompiler { |
|
4832 ICStub *firstMonitorStub_; |
|
4833 Rooted<ProxyObject*> proxy_; |
|
4834 RootedObject holder_; |
|
4835 RootedFunction getter_; |
|
4836 uint32_t pcOffset_; |
|
4837 |
|
4838 bool generateStubCode(MacroAssembler &masm, Address* internalStructAddr, |
|
4839 Address* generationAddr); |
|
4840 bool generateStubCode(MacroAssembler &masm); |
|
4841 |
|
4842 public: |
|
4843 ICGetPropCallDOMProxyNativeCompiler(JSContext *cx, ICStub::Kind kind, |
|
4844 ICStub *firstMonitorStub, Handle<ProxyObject*> proxy, |
|
4845 HandleObject holder, HandleFunction getter, |
|
4846 uint32_t pcOffset); |
|
4847 |
|
4848 ICStub *getStub(ICStubSpace *space); |
|
4849 }; |
|
4850 |
|
4851 class ICGetProp_DOMProxyShadowed : public ICMonitoredStub |
|
4852 { |
|
4853 friend class ICStubSpace; |
|
4854 protected: |
|
4855 HeapPtrShape shape_; |
|
4856 BaseProxyHandler *proxyHandler_; |
|
4857 HeapPtrPropertyName name_; |
|
4858 uint32_t pcOffset_; |
|
4859 |
|
4860 ICGetProp_DOMProxyShadowed(JitCode *stubCode, ICStub *firstMonitorStub, HandleShape shape, |
|
4861 BaseProxyHandler *proxyHandler, HandlePropertyName name, |
|
4862 uint32_t pcOffset); |
|
4863 |
|
4864 public: |
|
4865 static inline ICGetProp_DOMProxyShadowed *New(ICStubSpace *space, JitCode *code, |
|
4866 ICStub *firstMonitorStub, HandleShape shape, |
|
4867 BaseProxyHandler *proxyHandler, |
|
4868 HandlePropertyName name, uint32_t pcOffset) |
|
4869 { |
|
4870 if (!code) |
|
4871 return nullptr; |
|
4872 return space->allocate<ICGetProp_DOMProxyShadowed>(code, firstMonitorStub, shape, |
|
4873 proxyHandler, name, pcOffset); |
|
4874 } |
|
4875 |
|
4876 HeapPtrShape &shape() { |
|
4877 return shape_; |
|
4878 } |
|
4879 HeapPtrPropertyName &name() { |
|
4880 return name_; |
|
4881 } |
|
4882 |
|
4883 static size_t offsetOfShape() { |
|
4884 return offsetof(ICGetProp_DOMProxyShadowed, shape_); |
|
4885 } |
|
4886 static size_t offsetOfProxyHandler() { |
|
4887 return offsetof(ICGetProp_DOMProxyShadowed, proxyHandler_); |
|
4888 } |
|
4889 static size_t offsetOfName() { |
|
4890 return offsetof(ICGetProp_DOMProxyShadowed, name_); |
|
4891 } |
|
4892 static size_t offsetOfPCOffset() { |
|
4893 return offsetof(ICGetProp_DOMProxyShadowed, pcOffset_); |
|
4894 } |
|
4895 |
|
4896 class Compiler : public ICStubCompiler { |
|
4897 ICStub *firstMonitorStub_; |
|
4898 Rooted<ProxyObject*> proxy_; |
|
4899 RootedPropertyName name_; |
|
4900 uint32_t pcOffset_; |
|
4901 |
|
4902 bool generateStubCode(MacroAssembler &masm); |
|
4903 |
|
4904 public: |
|
4905 Compiler(JSContext *cx, ICStub *firstMonitorStub, Handle<ProxyObject*> proxy, |
|
4906 HandlePropertyName name, uint32_t pcOffset) |
|
4907 : ICStubCompiler(cx, ICStub::GetProp_CallNative), |
|
4908 firstMonitorStub_(firstMonitorStub), |
|
4909 proxy_(cx, proxy), |
|
4910 name_(cx, name), |
|
4911 pcOffset_(pcOffset) |
|
4912 {} |
|
4913 |
|
4914 ICStub *getStub(ICStubSpace *space); |
|
4915 }; |
|
4916 }; |
|
4917 |
|
4918 class ICGetProp_ArgumentsLength : public ICStub |
|
4919 { |
|
4920 friend class ICStubSpace; |
|
4921 public: |
|
4922 enum Which { Normal, Strict, Magic }; |
|
4923 |
|
4924 protected: |
|
4925 ICGetProp_ArgumentsLength(JitCode *stubCode) |
|
4926 : ICStub(ICStub::GetProp_ArgumentsLength, stubCode) |
|
4927 { } |
|
4928 |
|
4929 public: |
|
4930 static inline ICGetProp_ArgumentsLength *New(ICStubSpace *space, JitCode *code) |
|
4931 { |
|
4932 if (!code) |
|
4933 return nullptr; |
|
4934 return space->allocate<ICGetProp_ArgumentsLength>(code); |
|
4935 } |
|
4936 |
|
4937 class Compiler : public ICStubCompiler { |
|
4938 protected: |
|
4939 Which which_; |
|
4940 |
|
4941 bool generateStubCode(MacroAssembler &masm); |
|
4942 |
|
4943 virtual int32_t getKey() const { |
|
4944 return static_cast<int32_t>(kind) | (static_cast<int32_t>(which_) << 16); |
|
4945 } |
|
4946 |
|
4947 public: |
|
4948 Compiler(JSContext *cx, Which which) |
|
4949 : ICStubCompiler(cx, ICStub::GetProp_ArgumentsLength), |
|
4950 which_(which) |
|
4951 {} |
|
4952 |
|
4953 ICStub *getStub(ICStubSpace *space) { |
|
4954 return ICGetProp_ArgumentsLength::New(space, getStubCode()); |
|
4955 } |
|
4956 }; |
|
4957 }; |
|
4958 |
|
4959 // SetProp |
|
4960 // JSOP_SETPROP |
|
4961 // JSOP_SETNAME |
|
4962 // JSOP_SETGNAME |
|
4963 // JSOP_INITPROP |
|
4964 |
|
4965 class ICSetProp_Fallback : public ICFallbackStub |
|
4966 { |
|
4967 friend class ICStubSpace; |
|
4968 |
|
4969 ICSetProp_Fallback(JitCode *stubCode) |
|
4970 : ICFallbackStub(ICStub::SetProp_Fallback, stubCode) |
|
4971 { } |
|
4972 |
|
4973 public: |
|
4974 static const uint32_t MAX_OPTIMIZED_STUBS = 8; |
|
4975 |
|
4976 static inline ICSetProp_Fallback *New(ICStubSpace *space, JitCode *code) { |
|
4977 if (!code) |
|
4978 return nullptr; |
|
4979 return space->allocate<ICSetProp_Fallback>(code); |
|
4980 } |
|
4981 |
|
4982 static const size_t UNOPTIMIZABLE_ACCESS_BIT = 0; |
|
4983 void noteUnoptimizableAccess() { |
|
4984 extra_ |= (1u << UNOPTIMIZABLE_ACCESS_BIT); |
|
4985 } |
|
4986 bool hadUnoptimizableAccess() const { |
|
4987 return extra_ & (1u << UNOPTIMIZABLE_ACCESS_BIT); |
|
4988 } |
|
4989 |
|
4990 class Compiler : public ICStubCompiler { |
|
4991 protected: |
|
4992 uint32_t returnFromIonOffset_; |
|
4993 uint32_t returnFromStubOffset_; |
|
4994 bool generateStubCode(MacroAssembler &masm); |
|
4995 bool postGenerateStubCode(MacroAssembler &masm, Handle<JitCode *> code); |
|
4996 |
|
4997 public: |
|
4998 Compiler(JSContext *cx) |
|
4999 : ICStubCompiler(cx, ICStub::SetProp_Fallback) |
|
5000 { } |
|
5001 |
|
5002 ICStub *getStub(ICStubSpace *space) { |
|
5003 return ICSetProp_Fallback::New(space, getStubCode()); |
|
5004 } |
|
5005 }; |
|
5006 }; |
|
5007 |
|
5008 // Optimized SETPROP/SETGNAME/SETNAME stub. |
|
5009 class ICSetProp_Native : public ICUpdatedStub |
|
5010 { |
|
5011 friend class ICStubSpace; |
|
5012 |
|
5013 protected: // Protected to silence Clang warning. |
|
5014 HeapPtrTypeObject type_; |
|
5015 HeapPtrShape shape_; |
|
5016 uint32_t offset_; |
|
5017 |
|
5018 ICSetProp_Native(JitCode *stubCode, HandleTypeObject type, HandleShape shape, uint32_t offset); |
|
5019 |
|
5020 public: |
|
5021 static inline ICSetProp_Native *New(ICStubSpace *space, JitCode *code, HandleTypeObject type, |
|
5022 HandleShape shape, uint32_t offset) |
|
5023 { |
|
5024 if (!code) |
|
5025 return nullptr; |
|
5026 return space->allocate<ICSetProp_Native>(code, type, shape, offset); |
|
5027 } |
|
5028 HeapPtrTypeObject &type() { |
|
5029 return type_; |
|
5030 } |
|
5031 HeapPtrShape &shape() { |
|
5032 return shape_; |
|
5033 } |
|
5034 static size_t offsetOfType() { |
|
5035 return offsetof(ICSetProp_Native, type_); |
|
5036 } |
|
5037 static size_t offsetOfShape() { |
|
5038 return offsetof(ICSetProp_Native, shape_); |
|
5039 } |
|
5040 static size_t offsetOfOffset() { |
|
5041 return offsetof(ICSetProp_Native, offset_); |
|
5042 } |
|
5043 |
|
5044 class Compiler : public ICStubCompiler { |
|
5045 RootedObject obj_; |
|
5046 bool isFixedSlot_; |
|
5047 uint32_t offset_; |
|
5048 |
|
5049 protected: |
|
5050 virtual int32_t getKey() const { |
|
5051 return static_cast<int32_t>(kind) | (static_cast<int32_t>(isFixedSlot_) << 16); |
|
5052 } |
|
5053 |
|
5054 bool generateStubCode(MacroAssembler &masm); |
|
5055 |
|
5056 public: |
|
5057 Compiler(JSContext *cx, HandleObject obj, bool isFixedSlot, uint32_t offset) |
|
5058 : ICStubCompiler(cx, ICStub::SetProp_Native), |
|
5059 obj_(cx, obj), |
|
5060 isFixedSlot_(isFixedSlot), |
|
5061 offset_(offset) |
|
5062 {} |
|
5063 |
|
5064 ICUpdatedStub *getStub(ICStubSpace *space); |
|
5065 }; |
|
5066 }; |
|
5067 |
|
5068 |
|
5069 template <size_t ProtoChainDepth> class ICSetProp_NativeAddImpl; |
|
5070 |
|
5071 class ICSetProp_NativeAdd : public ICUpdatedStub |
|
5072 { |
|
5073 public: |
|
5074 static const size_t MAX_PROTO_CHAIN_DEPTH = 4; |
|
5075 |
|
5076 protected: // Protected to silence Clang warning. |
|
5077 HeapPtrTypeObject type_; |
|
5078 HeapPtrShape newShape_; |
|
5079 uint32_t offset_; |
|
5080 |
|
5081 ICSetProp_NativeAdd(JitCode *stubCode, HandleTypeObject type, size_t protoChainDepth, |
|
5082 HandleShape newShape, uint32_t offset); |
|
5083 |
|
5084 public: |
|
5085 size_t protoChainDepth() const { |
|
5086 return extra_; |
|
5087 } |
|
5088 HeapPtrTypeObject &type() { |
|
5089 return type_; |
|
5090 } |
|
5091 HeapPtrShape &newShape() { |
|
5092 return newShape_; |
|
5093 } |
|
5094 |
|
5095 template <size_t ProtoChainDepth> |
|
5096 ICSetProp_NativeAddImpl<ProtoChainDepth> *toImpl() { |
|
5097 JS_ASSERT(ProtoChainDepth == protoChainDepth()); |
|
5098 return static_cast<ICSetProp_NativeAddImpl<ProtoChainDepth> *>(this); |
|
5099 } |
|
5100 |
|
5101 static size_t offsetOfType() { |
|
5102 return offsetof(ICSetProp_NativeAdd, type_); |
|
5103 } |
|
5104 static size_t offsetOfNewShape() { |
|
5105 return offsetof(ICSetProp_NativeAdd, newShape_); |
|
5106 } |
|
5107 static size_t offsetOfOffset() { |
|
5108 return offsetof(ICSetProp_NativeAdd, offset_); |
|
5109 } |
|
5110 }; |
|
5111 |
|
5112 template <size_t ProtoChainDepth> |
|
5113 class ICSetProp_NativeAddImpl : public ICSetProp_NativeAdd |
|
5114 { |
|
5115 friend class ICStubSpace; |
|
5116 |
|
5117 static const size_t NumShapes = ProtoChainDepth + 1; |
|
5118 mozilla::Array<HeapPtrShape, NumShapes> shapes_; |
|
5119 |
|
5120 ICSetProp_NativeAddImpl(JitCode *stubCode, HandleTypeObject type, |
|
5121 const AutoShapeVector *shapes, |
|
5122 HandleShape newShape, uint32_t offset); |
|
5123 |
|
5124 public: |
|
5125 static inline ICSetProp_NativeAddImpl *New( |
|
5126 ICStubSpace *space, JitCode *code, HandleTypeObject type, |
|
5127 const AutoShapeVector *shapes, HandleShape newShape, uint32_t offset) |
|
5128 { |
|
5129 if (!code) |
|
5130 return nullptr; |
|
5131 return space->allocate<ICSetProp_NativeAddImpl<ProtoChainDepth> >( |
|
5132 code, type, shapes, newShape, offset); |
|
5133 } |
|
5134 |
|
5135 void traceShapes(JSTracer *trc) { |
|
5136 for (size_t i = 0; i < NumShapes; i++) |
|
5137 MarkShape(trc, &shapes_[i], "baseline-setpropnativeadd-stub-shape"); |
|
5138 } |
|
5139 |
|
5140 static size_t offsetOfShape(size_t idx) { |
|
5141 return offsetof(ICSetProp_NativeAddImpl, shapes_) + (idx * sizeof(HeapPtrShape)); |
|
5142 } |
|
5143 }; |
|
5144 |
|
5145 class ICSetPropNativeAddCompiler : public ICStubCompiler { |
|
5146 RootedObject obj_; |
|
5147 RootedShape oldShape_; |
|
5148 size_t protoChainDepth_; |
|
5149 bool isFixedSlot_; |
|
5150 uint32_t offset_; |
|
5151 |
|
5152 protected: |
|
5153 virtual int32_t getKey() const { |
|
5154 return static_cast<int32_t>(kind) | (static_cast<int32_t>(isFixedSlot_) << 16) | |
|
5155 (static_cast<int32_t>(protoChainDepth_) << 20); |
|
5156 } |
|
5157 |
|
5158 bool generateStubCode(MacroAssembler &masm); |
|
5159 |
|
5160 public: |
|
5161 ICSetPropNativeAddCompiler(JSContext *cx, HandleObject obj, HandleShape oldShape, |
|
5162 size_t protoChainDepth, bool isFixedSlot, uint32_t offset); |
|
5163 |
|
5164 template <size_t ProtoChainDepth> |
|
5165 ICUpdatedStub *getStubSpecific(ICStubSpace *space, const AutoShapeVector *shapes) |
|
5166 { |
|
5167 RootedTypeObject type(cx, obj_->getType(cx)); |
|
5168 if (!type) |
|
5169 return nullptr; |
|
5170 |
|
5171 RootedShape newShape(cx, obj_->lastProperty()); |
|
5172 |
|
5173 return ICSetProp_NativeAddImpl<ProtoChainDepth>::New( |
|
5174 space, getStubCode(), type, shapes, newShape, offset_); |
|
5175 } |
|
5176 |
|
5177 ICUpdatedStub *getStub(ICStubSpace *space); |
|
5178 }; |
|
5179 |
|
5180 // Base stub for calling a setters on a native object. |
|
5181 class ICSetPropCallSetter : public ICStub |
|
5182 { |
|
5183 friend class ICStubSpace; |
|
5184 |
|
5185 protected: |
|
5186 // Object shape (lastProperty). |
|
5187 HeapPtrShape shape_; |
|
5188 |
|
5189 // Holder and shape. |
|
5190 HeapPtrObject holder_; |
|
5191 HeapPtrShape holderShape_; |
|
5192 |
|
5193 // Function to call. |
|
5194 HeapPtrFunction setter_; |
|
5195 |
|
5196 // PC of call, for profiler |
|
5197 uint32_t pcOffset_; |
|
5198 |
|
5199 ICSetPropCallSetter(Kind kind, JitCode *stubCode, HandleShape shape, HandleObject holder, |
|
5200 HandleShape holderShape, HandleFunction setter, uint32_t pcOffset); |
|
5201 |
|
5202 public: |
|
5203 HeapPtrShape &shape() { |
|
5204 return shape_; |
|
5205 } |
|
5206 HeapPtrObject &holder() { |
|
5207 return holder_; |
|
5208 } |
|
5209 HeapPtrShape &holderShape() { |
|
5210 return holderShape_; |
|
5211 } |
|
5212 HeapPtrFunction &setter() { |
|
5213 return setter_; |
|
5214 } |
|
5215 |
|
5216 static size_t offsetOfShape() { |
|
5217 return offsetof(ICSetPropCallSetter, shape_); |
|
5218 } |
|
5219 static size_t offsetOfHolder() { |
|
5220 return offsetof(ICSetPropCallSetter, holder_); |
|
5221 } |
|
5222 static size_t offsetOfHolderShape() { |
|
5223 return offsetof(ICSetPropCallSetter, holderShape_); |
|
5224 } |
|
5225 static size_t offsetOfSetter() { |
|
5226 return offsetof(ICSetPropCallSetter, setter_); |
|
5227 } |
|
5228 static size_t offsetOfPCOffset() { |
|
5229 return offsetof(ICSetPropCallSetter, pcOffset_); |
|
5230 } |
|
5231 |
|
5232 class Compiler : public ICStubCompiler { |
|
5233 protected: |
|
5234 RootedObject obj_; |
|
5235 RootedObject holder_; |
|
5236 RootedFunction setter_; |
|
5237 uint32_t pcOffset_; |
|
5238 |
|
5239 public: |
|
5240 Compiler(JSContext *cx, ICStub::Kind kind, HandleObject obj, HandleObject holder, |
|
5241 HandleFunction setter, uint32_t pcOffset) |
|
5242 : ICStubCompiler(cx, kind), |
|
5243 obj_(cx, obj), |
|
5244 holder_(cx, holder), |
|
5245 setter_(cx, setter), |
|
5246 pcOffset_(pcOffset) |
|
5247 { |
|
5248 JS_ASSERT(kind == ICStub::SetProp_CallScripted || kind == ICStub::SetProp_CallNative); |
|
5249 } |
|
5250 }; |
|
5251 }; |
|
5252 |
|
5253 // Stub for calling a scripted setter on a native object. |
|
5254 class ICSetProp_CallScripted : public ICSetPropCallSetter |
|
5255 { |
|
5256 friend class ICStubSpace; |
|
5257 |
|
5258 protected: |
|
5259 ICSetProp_CallScripted(JitCode *stubCode, HandleShape shape, HandleObject holder, |
|
5260 HandleShape holderShape, HandleFunction setter, uint32_t pcOffset) |
|
5261 : ICSetPropCallSetter(SetProp_CallScripted, stubCode, shape, holder, holderShape, |
|
5262 setter, pcOffset) |
|
5263 {} |
|
5264 |
|
5265 public: |
|
5266 static inline ICSetProp_CallScripted *New(ICStubSpace *space, JitCode *code, |
|
5267 HandleShape shape, HandleObject holder, |
|
5268 HandleShape holderShape, HandleFunction setter, |
|
5269 uint32_t pcOffset) |
|
5270 { |
|
5271 if (!code) |
|
5272 return nullptr; |
|
5273 return space->allocate<ICSetProp_CallScripted>(code, shape, holder, holderShape, setter, |
|
5274 pcOffset); |
|
5275 } |
|
5276 |
|
5277 class Compiler : public ICSetPropCallSetter::Compiler { |
|
5278 protected: |
|
5279 bool generateStubCode(MacroAssembler &masm); |
|
5280 |
|
5281 public: |
|
5282 Compiler(JSContext *cx, HandleObject obj, HandleObject holder, HandleFunction setter, |
|
5283 uint32_t pcOffset) |
|
5284 : ICSetPropCallSetter::Compiler(cx, ICStub::SetProp_CallScripted, |
|
5285 obj, holder, setter, pcOffset) |
|
5286 {} |
|
5287 |
|
5288 ICStub *getStub(ICStubSpace *space) { |
|
5289 RootedShape shape(cx, obj_->lastProperty()); |
|
5290 RootedShape holderShape(cx, holder_->lastProperty()); |
|
5291 return ICSetProp_CallScripted::New(space, getStubCode(), shape, holder_, holderShape, |
|
5292 setter_, pcOffset_); |
|
5293 } |
|
5294 }; |
|
5295 }; |
|
5296 |
|
5297 // Stub for calling a native setter on a native object. |
|
5298 class ICSetProp_CallNative : public ICSetPropCallSetter |
|
5299 { |
|
5300 friend class ICStubSpace; |
|
5301 |
|
5302 protected: |
|
5303 ICSetProp_CallNative(JitCode *stubCode, HandleShape shape, HandleObject holder, |
|
5304 HandleShape holderShape, HandleFunction setter, uint32_t pcOffset) |
|
5305 : ICSetPropCallSetter(SetProp_CallNative, stubCode, shape, holder, holderShape, |
|
5306 setter, pcOffset) |
|
5307 {} |
|
5308 |
|
5309 public: |
|
5310 static inline ICSetProp_CallNative *New(ICStubSpace *space, JitCode *code, |
|
5311 HandleShape shape, HandleObject holder, |
|
5312 HandleShape holderShape, HandleFunction setter, |
|
5313 uint32_t pcOffset) |
|
5314 { |
|
5315 if (!code) |
|
5316 return nullptr; |
|
5317 return space->allocate<ICSetProp_CallNative>(code, shape, holder, holderShape, setter, |
|
5318 pcOffset); |
|
5319 } |
|
5320 |
|
5321 class Compiler : public ICSetPropCallSetter::Compiler { |
|
5322 protected: |
|
5323 bool generateStubCode(MacroAssembler &masm); |
|
5324 |
|
5325 public: |
|
5326 Compiler(JSContext *cx, HandleObject obj, HandleObject holder, HandleFunction setter, |
|
5327 uint32_t pcOffset) |
|
5328 : ICSetPropCallSetter::Compiler(cx, ICStub::SetProp_CallNative, |
|
5329 obj, holder, setter, pcOffset) |
|
5330 {} |
|
5331 |
|
5332 ICStub *getStub(ICStubSpace *space) { |
|
5333 RootedShape shape(cx, obj_->lastProperty()); |
|
5334 RootedShape holderShape(cx, holder_->lastProperty()); |
|
5335 return ICSetProp_CallNative::New(space, getStubCode(), shape, holder_, holderShape, |
|
5336 setter_, pcOffset_); |
|
5337 } |
|
5338 }; |
|
5339 }; |
|
5340 |
|
5341 // Call |
|
5342 // JSOP_CALL |
|
5343 // JSOP_FUNAPPLY |
|
5344 // JSOP_FUNCALL |
|
5345 // JSOP_NEW |
|
5346 |
|
5347 class ICCallStubCompiler : public ICStubCompiler |
|
5348 { |
|
5349 protected: |
|
5350 ICCallStubCompiler(JSContext *cx, ICStub::Kind kind) |
|
5351 : ICStubCompiler(cx, kind) |
|
5352 { } |
|
5353 |
|
5354 enum FunApplyThing { |
|
5355 FunApply_MagicArgs, |
|
5356 FunApply_Array |
|
5357 }; |
|
5358 |
|
5359 void pushCallArguments(MacroAssembler &masm, GeneralRegisterSet regs, Register argcReg); |
|
5360 Register guardFunApply(MacroAssembler &masm, GeneralRegisterSet regs, Register argcReg, |
|
5361 bool checkNative, FunApplyThing applyThing, Label *failure); |
|
5362 void pushCallerArguments(MacroAssembler &masm, GeneralRegisterSet regs); |
|
5363 void pushArrayArguments(MacroAssembler &masm, Address arrayVal, GeneralRegisterSet regs); |
|
5364 }; |
|
5365 |
|
5366 class ICCall_Fallback : public ICMonitoredFallbackStub |
|
5367 { |
|
5368 friend class ICStubSpace; |
|
5369 public: |
|
5370 static const unsigned CONSTRUCTING_FLAG = 0x0001; |
|
5371 |
|
5372 static const uint32_t MAX_OPTIMIZED_STUBS = 16; |
|
5373 static const uint32_t MAX_SCRIPTED_STUBS = 7; |
|
5374 static const uint32_t MAX_NATIVE_STUBS = 7; |
|
5375 private: |
|
5376 |
|
5377 ICCall_Fallback(JitCode *stubCode, bool isConstructing) |
|
5378 : ICMonitoredFallbackStub(ICStub::Call_Fallback, stubCode) |
|
5379 { |
|
5380 extra_ = 0; |
|
5381 if (isConstructing) |
|
5382 extra_ |= CONSTRUCTING_FLAG; |
|
5383 } |
|
5384 |
|
5385 public: |
|
5386 |
|
5387 static inline ICCall_Fallback *New(ICStubSpace *space, JitCode *code, bool isConstructing) |
|
5388 { |
|
5389 if (!code) |
|
5390 return nullptr; |
|
5391 return space->allocate<ICCall_Fallback>(code, isConstructing); |
|
5392 } |
|
5393 |
|
5394 bool isConstructing() const { |
|
5395 return extra_ & CONSTRUCTING_FLAG; |
|
5396 } |
|
5397 |
|
5398 unsigned scriptedStubCount() const { |
|
5399 return numStubsWithKind(Call_Scripted); |
|
5400 } |
|
5401 bool scriptedStubsAreGeneralized() const { |
|
5402 return hasStub(Call_AnyScripted); |
|
5403 } |
|
5404 |
|
5405 unsigned nativeStubCount() const { |
|
5406 return numStubsWithKind(Call_Native); |
|
5407 } |
|
5408 bool nativeStubsAreGeneralized() const { |
|
5409 // Return hasStub(Call_AnyNative) after Call_AnyNative stub is added. |
|
5410 return false; |
|
5411 } |
|
5412 |
|
5413 // Compiler for this stub kind. |
|
5414 class Compiler : public ICCallStubCompiler { |
|
5415 protected: |
|
5416 bool isConstructing_; |
|
5417 uint32_t returnFromIonOffset_; |
|
5418 uint32_t returnFromStubOffset_; |
|
5419 bool generateStubCode(MacroAssembler &masm); |
|
5420 bool postGenerateStubCode(MacroAssembler &masm, Handle<JitCode *> code); |
|
5421 |
|
5422 public: |
|
5423 Compiler(JSContext *cx, bool isConstructing) |
|
5424 : ICCallStubCompiler(cx, ICStub::Call_Fallback), |
|
5425 isConstructing_(isConstructing) |
|
5426 { } |
|
5427 |
|
5428 ICStub *getStub(ICStubSpace *space) { |
|
5429 ICCall_Fallback *stub = ICCall_Fallback::New(space, getStubCode(), isConstructing_); |
|
5430 if (!stub || !stub->initMonitoringChain(cx, space)) |
|
5431 return nullptr; |
|
5432 return stub; |
|
5433 } |
|
5434 }; |
|
5435 }; |
|
5436 |
|
5437 class ICCall_Scripted : public ICMonitoredStub |
|
5438 { |
|
5439 friend class ICStubSpace; |
|
5440 |
|
5441 protected: |
|
5442 HeapPtrScript calleeScript_; |
|
5443 HeapPtrObject templateObject_; |
|
5444 uint32_t pcOffset_; |
|
5445 |
|
5446 ICCall_Scripted(JitCode *stubCode, ICStub *firstMonitorStub, |
|
5447 HandleScript calleeScript, HandleObject templateObject, |
|
5448 uint32_t pcOffset); |
|
5449 |
|
5450 public: |
|
5451 static inline ICCall_Scripted *New( |
|
5452 ICStubSpace *space, JitCode *code, ICStub *firstMonitorStub, |
|
5453 HandleScript calleeScript, HandleObject templateObject, |
|
5454 uint32_t pcOffset) |
|
5455 { |
|
5456 if (!code) |
|
5457 return nullptr; |
|
5458 return space->allocate<ICCall_Scripted>(code, firstMonitorStub, |
|
5459 calleeScript, templateObject, pcOffset); |
|
5460 } |
|
5461 |
|
5462 HeapPtrScript &calleeScript() { |
|
5463 return calleeScript_; |
|
5464 } |
|
5465 HeapPtrObject &templateObject() { |
|
5466 return templateObject_; |
|
5467 } |
|
5468 |
|
5469 static size_t offsetOfCalleeScript() { |
|
5470 return offsetof(ICCall_Scripted, calleeScript_); |
|
5471 } |
|
5472 static size_t offsetOfPCOffset() { |
|
5473 return offsetof(ICCall_Scripted, pcOffset_); |
|
5474 } |
|
5475 }; |
|
5476 |
|
5477 class ICCall_AnyScripted : public ICMonitoredStub |
|
5478 { |
|
5479 friend class ICStubSpace; |
|
5480 |
|
5481 protected: |
|
5482 uint32_t pcOffset_; |
|
5483 |
|
5484 ICCall_AnyScripted(JitCode *stubCode, ICStub *firstMonitorStub, uint32_t pcOffset) |
|
5485 : ICMonitoredStub(ICStub::Call_AnyScripted, stubCode, firstMonitorStub), |
|
5486 pcOffset_(pcOffset) |
|
5487 { } |
|
5488 |
|
5489 public: |
|
5490 static inline ICCall_AnyScripted *New(ICStubSpace *space, JitCode *code, |
|
5491 ICStub *firstMonitorStub, uint32_t pcOffset) |
|
5492 { |
|
5493 if (!code) |
|
5494 return nullptr; |
|
5495 return space->allocate<ICCall_AnyScripted>(code, firstMonitorStub, pcOffset); |
|
5496 } |
|
5497 |
|
5498 static size_t offsetOfPCOffset() { |
|
5499 return offsetof(ICCall_AnyScripted, pcOffset_); |
|
5500 } |
|
5501 }; |
|
5502 |
|
5503 // Compiler for Call_Scripted and Call_AnyScripted stubs. |
|
5504 class ICCallScriptedCompiler : public ICCallStubCompiler { |
|
5505 protected: |
|
5506 ICStub *firstMonitorStub_; |
|
5507 bool isConstructing_; |
|
5508 RootedScript calleeScript_; |
|
5509 RootedObject templateObject_; |
|
5510 uint32_t pcOffset_; |
|
5511 bool generateStubCode(MacroAssembler &masm); |
|
5512 |
|
5513 virtual int32_t getKey() const { |
|
5514 return static_cast<int32_t>(kind) | (static_cast<int32_t>(isConstructing_) << 16); |
|
5515 } |
|
5516 |
|
5517 public: |
|
5518 ICCallScriptedCompiler(JSContext *cx, ICStub *firstMonitorStub, |
|
5519 HandleScript calleeScript, HandleObject templateObject, |
|
5520 bool isConstructing, uint32_t pcOffset) |
|
5521 : ICCallStubCompiler(cx, ICStub::Call_Scripted), |
|
5522 firstMonitorStub_(firstMonitorStub), |
|
5523 isConstructing_(isConstructing), |
|
5524 calleeScript_(cx, calleeScript), |
|
5525 templateObject_(cx, templateObject), |
|
5526 pcOffset_(pcOffset) |
|
5527 { } |
|
5528 |
|
5529 ICCallScriptedCompiler(JSContext *cx, ICStub *firstMonitorStub, bool isConstructing, |
|
5530 uint32_t pcOffset) |
|
5531 : ICCallStubCompiler(cx, ICStub::Call_AnyScripted), |
|
5532 firstMonitorStub_(firstMonitorStub), |
|
5533 isConstructing_(isConstructing), |
|
5534 calleeScript_(cx, nullptr), |
|
5535 templateObject_(cx, nullptr), |
|
5536 pcOffset_(pcOffset) |
|
5537 { } |
|
5538 |
|
5539 ICStub *getStub(ICStubSpace *space) { |
|
5540 if (calleeScript_) { |
|
5541 return ICCall_Scripted::New(space, getStubCode(), firstMonitorStub_, |
|
5542 calleeScript_, templateObject_, |
|
5543 pcOffset_); |
|
5544 } |
|
5545 return ICCall_AnyScripted::New(space, getStubCode(), firstMonitorStub_, pcOffset_); |
|
5546 } |
|
5547 }; |
|
5548 |
|
5549 class ICCall_Native : public ICMonitoredStub |
|
5550 { |
|
5551 friend class ICStubSpace; |
|
5552 |
|
5553 protected: |
|
5554 HeapPtrFunction callee_; |
|
5555 HeapPtrObject templateObject_; |
|
5556 uint32_t pcOffset_; |
|
5557 |
|
5558 #ifdef JS_ARM_SIMULATOR |
|
5559 void *native_; |
|
5560 #endif |
|
5561 |
|
5562 ICCall_Native(JitCode *stubCode, ICStub *firstMonitorStub, |
|
5563 HandleFunction callee, HandleObject templateObject, |
|
5564 uint32_t pcOffset); |
|
5565 |
|
5566 public: |
|
5567 static inline ICCall_Native *New(ICStubSpace *space, JitCode *code, ICStub *firstMonitorStub, |
|
5568 HandleFunction callee, HandleObject templateObject, |
|
5569 uint32_t pcOffset) |
|
5570 { |
|
5571 if (!code) |
|
5572 return nullptr; |
|
5573 return space->allocate<ICCall_Native>(code, firstMonitorStub, |
|
5574 callee, templateObject, pcOffset); |
|
5575 } |
|
5576 |
|
5577 HeapPtrFunction &callee() { |
|
5578 return callee_; |
|
5579 } |
|
5580 HeapPtrObject &templateObject() { |
|
5581 return templateObject_; |
|
5582 } |
|
5583 |
|
5584 static size_t offsetOfCallee() { |
|
5585 return offsetof(ICCall_Native, callee_); |
|
5586 } |
|
5587 static size_t offsetOfPCOffset() { |
|
5588 return offsetof(ICCall_Native, pcOffset_); |
|
5589 } |
|
5590 |
|
5591 #ifdef JS_ARM_SIMULATOR |
|
5592 static size_t offsetOfNative() { |
|
5593 return offsetof(ICCall_Native, native_); |
|
5594 } |
|
5595 #endif |
|
5596 |
|
5597 // Compiler for this stub kind. |
|
5598 class Compiler : public ICCallStubCompiler { |
|
5599 protected: |
|
5600 ICStub *firstMonitorStub_; |
|
5601 bool isConstructing_; |
|
5602 RootedFunction callee_; |
|
5603 RootedObject templateObject_; |
|
5604 uint32_t pcOffset_; |
|
5605 bool generateStubCode(MacroAssembler &masm); |
|
5606 |
|
5607 virtual int32_t getKey() const { |
|
5608 return static_cast<int32_t>(kind) | (static_cast<int32_t>(isConstructing_) << 16); |
|
5609 } |
|
5610 |
|
5611 public: |
|
5612 Compiler(JSContext *cx, ICStub *firstMonitorStub, |
|
5613 HandleFunction callee, HandleObject templateObject, |
|
5614 bool isConstructing, uint32_t pcOffset) |
|
5615 : ICCallStubCompiler(cx, ICStub::Call_Native), |
|
5616 firstMonitorStub_(firstMonitorStub), |
|
5617 isConstructing_(isConstructing), |
|
5618 callee_(cx, callee), |
|
5619 templateObject_(cx, templateObject), |
|
5620 pcOffset_(pcOffset) |
|
5621 { } |
|
5622 |
|
5623 ICStub *getStub(ICStubSpace *space) { |
|
5624 return ICCall_Native::New(space, getStubCode(), firstMonitorStub_, |
|
5625 callee_, templateObject_, pcOffset_); |
|
5626 } |
|
5627 }; |
|
5628 }; |
|
5629 |
|
5630 class ICCall_ScriptedApplyArray : public ICMonitoredStub |
|
5631 { |
|
5632 friend class ICStubSpace; |
|
5633 public: |
|
5634 // The maximum length of an inlineable funcall array. |
|
5635 // Keep this small to avoid controllable stack overflows by attackers passing large |
|
5636 // arrays to fun.apply. |
|
5637 static const uint32_t MAX_ARGS_ARRAY_LENGTH = 16; |
|
5638 |
|
5639 protected: |
|
5640 uint32_t pcOffset_; |
|
5641 |
|
5642 ICCall_ScriptedApplyArray(JitCode *stubCode, ICStub *firstMonitorStub, uint32_t pcOffset) |
|
5643 : ICMonitoredStub(ICStub::Call_ScriptedApplyArray, stubCode, firstMonitorStub), |
|
5644 pcOffset_(pcOffset) |
|
5645 {} |
|
5646 |
|
5647 public: |
|
5648 static inline ICCall_ScriptedApplyArray *New(ICStubSpace *space, JitCode *code, |
|
5649 ICStub *firstMonitorStub, uint32_t pcOffset) |
|
5650 { |
|
5651 if (!code) |
|
5652 return nullptr; |
|
5653 return space->allocate<ICCall_ScriptedApplyArray>(code, firstMonitorStub, pcOffset); |
|
5654 } |
|
5655 |
|
5656 static size_t offsetOfPCOffset() { |
|
5657 return offsetof(ICCall_ScriptedApplyArray, pcOffset_); |
|
5658 } |
|
5659 |
|
5660 // Compiler for this stub kind. |
|
5661 class Compiler : public ICCallStubCompiler { |
|
5662 protected: |
|
5663 ICStub *firstMonitorStub_; |
|
5664 uint32_t pcOffset_; |
|
5665 bool generateStubCode(MacroAssembler &masm); |
|
5666 |
|
5667 virtual int32_t getKey() const { |
|
5668 return static_cast<int32_t>(kind); |
|
5669 } |
|
5670 |
|
5671 public: |
|
5672 Compiler(JSContext *cx, ICStub *firstMonitorStub, uint32_t pcOffset) |
|
5673 : ICCallStubCompiler(cx, ICStub::Call_ScriptedApplyArray), |
|
5674 firstMonitorStub_(firstMonitorStub), |
|
5675 pcOffset_(pcOffset) |
|
5676 { } |
|
5677 |
|
5678 ICStub *getStub(ICStubSpace *space) { |
|
5679 return ICCall_ScriptedApplyArray::New(space, getStubCode(), firstMonitorStub_, |
|
5680 pcOffset_); |
|
5681 } |
|
5682 }; |
|
5683 }; |
|
5684 |
|
5685 class ICCall_ScriptedApplyArguments : public ICMonitoredStub |
|
5686 { |
|
5687 friend class ICStubSpace; |
|
5688 |
|
5689 protected: |
|
5690 uint32_t pcOffset_; |
|
5691 |
|
5692 ICCall_ScriptedApplyArguments(JitCode *stubCode, ICStub *firstMonitorStub, uint32_t pcOffset) |
|
5693 : ICMonitoredStub(ICStub::Call_ScriptedApplyArguments, stubCode, firstMonitorStub), |
|
5694 pcOffset_(pcOffset) |
|
5695 {} |
|
5696 |
|
5697 public: |
|
5698 static inline ICCall_ScriptedApplyArguments *New(ICStubSpace *space, JitCode *code, |
|
5699 ICStub *firstMonitorStub, uint32_t pcOffset) |
|
5700 { |
|
5701 if (!code) |
|
5702 return nullptr; |
|
5703 return space->allocate<ICCall_ScriptedApplyArguments>(code, firstMonitorStub, pcOffset); |
|
5704 } |
|
5705 |
|
5706 static size_t offsetOfPCOffset() { |
|
5707 return offsetof(ICCall_ScriptedApplyArguments, pcOffset_); |
|
5708 } |
|
5709 |
|
5710 // Compiler for this stub kind. |
|
5711 class Compiler : public ICCallStubCompiler { |
|
5712 protected: |
|
5713 ICStub *firstMonitorStub_; |
|
5714 uint32_t pcOffset_; |
|
5715 bool generateStubCode(MacroAssembler &masm); |
|
5716 |
|
5717 virtual int32_t getKey() const { |
|
5718 return static_cast<int32_t>(kind); |
|
5719 } |
|
5720 |
|
5721 public: |
|
5722 Compiler(JSContext *cx, ICStub *firstMonitorStub, uint32_t pcOffset) |
|
5723 : ICCallStubCompiler(cx, ICStub::Call_ScriptedApplyArguments), |
|
5724 firstMonitorStub_(firstMonitorStub), |
|
5725 pcOffset_(pcOffset) |
|
5726 { } |
|
5727 |
|
5728 ICStub *getStub(ICStubSpace *space) { |
|
5729 return ICCall_ScriptedApplyArguments::New(space, getStubCode(), firstMonitorStub_, |
|
5730 pcOffset_); |
|
5731 } |
|
5732 }; |
|
5733 }; |
|
5734 |
|
5735 // Handles calls of the form |fun.call(...)| where fun is a scripted function. |
|
5736 class ICCall_ScriptedFunCall : public ICMonitoredStub |
|
5737 { |
|
5738 friend class ICStubSpace; |
|
5739 |
|
5740 protected: |
|
5741 uint32_t pcOffset_; |
|
5742 |
|
5743 ICCall_ScriptedFunCall(JitCode *stubCode, ICStub *firstMonitorStub, uint32_t pcOffset) |
|
5744 : ICMonitoredStub(ICStub::Call_ScriptedFunCall, stubCode, firstMonitorStub), |
|
5745 pcOffset_(pcOffset) |
|
5746 {} |
|
5747 |
|
5748 public: |
|
5749 static inline ICCall_ScriptedFunCall *New(ICStubSpace *space, JitCode *code, |
|
5750 ICStub *firstMonitorStub, uint32_t pcOffset) |
|
5751 { |
|
5752 if (!code) |
|
5753 return nullptr; |
|
5754 return space->allocate<ICCall_ScriptedFunCall>(code, firstMonitorStub, pcOffset); |
|
5755 } |
|
5756 |
|
5757 static size_t offsetOfPCOffset() { |
|
5758 return offsetof(ICCall_ScriptedFunCall, pcOffset_); |
|
5759 } |
|
5760 |
|
5761 // Compiler for this stub kind. |
|
5762 class Compiler : public ICCallStubCompiler { |
|
5763 protected: |
|
5764 ICStub *firstMonitorStub_; |
|
5765 uint32_t pcOffset_; |
|
5766 bool generateStubCode(MacroAssembler &masm); |
|
5767 |
|
5768 virtual int32_t getKey() const { |
|
5769 return static_cast<int32_t>(kind); |
|
5770 } |
|
5771 |
|
5772 public: |
|
5773 Compiler(JSContext *cx, ICStub *firstMonitorStub, uint32_t pcOffset) |
|
5774 : ICCallStubCompiler(cx, ICStub::Call_ScriptedFunCall), |
|
5775 firstMonitorStub_(firstMonitorStub), |
|
5776 pcOffset_(pcOffset) |
|
5777 { } |
|
5778 |
|
5779 ICStub *getStub(ICStubSpace *space) { |
|
5780 return ICCall_ScriptedFunCall::New(space, getStubCode(), firstMonitorStub_, |
|
5781 pcOffset_); |
|
5782 } |
|
5783 }; |
|
5784 }; |
|
5785 |
|
5786 // Stub for performing a TableSwitch, updating the IC's return address to jump |
|
5787 // to whatever point the switch is branching to. |
|
5788 class ICTableSwitch : public ICStub |
|
5789 { |
|
5790 friend class ICStubSpace; |
|
5791 |
|
5792 protected: // Protected to silence Clang warning. |
|
5793 void **table_; |
|
5794 int32_t min_; |
|
5795 int32_t length_; |
|
5796 void *defaultTarget_; |
|
5797 |
|
5798 ICTableSwitch(JitCode *stubCode, void **table, |
|
5799 int32_t min, int32_t length, void *defaultTarget) |
|
5800 : ICStub(TableSwitch, stubCode), table_(table), |
|
5801 min_(min), length_(length), defaultTarget_(defaultTarget) |
|
5802 {} |
|
5803 |
|
5804 public: |
|
5805 static inline ICTableSwitch *New(ICStubSpace *space, JitCode *code, void **table, |
|
5806 int32_t min, int32_t length, void *defaultTarget) { |
|
5807 if (!code) |
|
5808 return nullptr; |
|
5809 return space->allocate<ICTableSwitch>(code, table, min, length, defaultTarget); |
|
5810 } |
|
5811 |
|
5812 void fixupJumpTable(JSScript *script, BaselineScript *baseline); |
|
5813 |
|
5814 class Compiler : public ICStubCompiler { |
|
5815 bool generateStubCode(MacroAssembler &masm); |
|
5816 |
|
5817 jsbytecode *pc_; |
|
5818 |
|
5819 public: |
|
5820 Compiler(JSContext *cx, jsbytecode *pc) |
|
5821 : ICStubCompiler(cx, ICStub::TableSwitch), pc_(pc) |
|
5822 {} |
|
5823 |
|
5824 ICStub *getStub(ICStubSpace *space); |
|
5825 }; |
|
5826 }; |
|
5827 |
|
5828 // IC for constructing an iterator from an input value. |
|
5829 class ICIteratorNew_Fallback : public ICFallbackStub |
|
5830 { |
|
5831 friend class ICStubSpace; |
|
5832 |
|
5833 ICIteratorNew_Fallback(JitCode *stubCode) |
|
5834 : ICFallbackStub(ICStub::IteratorNew_Fallback, stubCode) |
|
5835 { } |
|
5836 |
|
5837 public: |
|
5838 static inline ICIteratorNew_Fallback *New(ICStubSpace *space, JitCode *code) { |
|
5839 if (!code) |
|
5840 return nullptr; |
|
5841 return space->allocate<ICIteratorNew_Fallback>(code); |
|
5842 } |
|
5843 |
|
5844 class Compiler : public ICStubCompiler { |
|
5845 protected: |
|
5846 bool generateStubCode(MacroAssembler &masm); |
|
5847 |
|
5848 public: |
|
5849 Compiler(JSContext *cx) |
|
5850 : ICStubCompiler(cx, ICStub::IteratorNew_Fallback) |
|
5851 { } |
|
5852 |
|
5853 ICStub *getStub(ICStubSpace *space) { |
|
5854 return ICIteratorNew_Fallback::New(space, getStubCode()); |
|
5855 } |
|
5856 }; |
|
5857 }; |
|
5858 |
|
5859 // IC for testing if there are more values in an iterator. |
|
5860 class ICIteratorMore_Fallback : public ICFallbackStub |
|
5861 { |
|
5862 friend class ICStubSpace; |
|
5863 |
|
5864 ICIteratorMore_Fallback(JitCode *stubCode) |
|
5865 : ICFallbackStub(ICStub::IteratorMore_Fallback, stubCode) |
|
5866 { } |
|
5867 |
|
5868 public: |
|
5869 static inline ICIteratorMore_Fallback *New(ICStubSpace *space, JitCode *code) { |
|
5870 if (!code) |
|
5871 return nullptr; |
|
5872 return space->allocate<ICIteratorMore_Fallback>(code); |
|
5873 } |
|
5874 |
|
5875 class Compiler : public ICStubCompiler { |
|
5876 protected: |
|
5877 bool generateStubCode(MacroAssembler &masm); |
|
5878 |
|
5879 public: |
|
5880 Compiler(JSContext *cx) |
|
5881 : ICStubCompiler(cx, ICStub::IteratorMore_Fallback) |
|
5882 { } |
|
5883 |
|
5884 ICStub *getStub(ICStubSpace *space) { |
|
5885 return ICIteratorMore_Fallback::New(space, getStubCode()); |
|
5886 } |
|
5887 }; |
|
5888 }; |
|
5889 |
|
5890 // IC for testing if there are more values in a native iterator. |
|
5891 class ICIteratorMore_Native : public ICStub |
|
5892 { |
|
5893 friend class ICStubSpace; |
|
5894 |
|
5895 ICIteratorMore_Native(JitCode *stubCode) |
|
5896 : ICStub(ICStub::IteratorMore_Native, stubCode) |
|
5897 { } |
|
5898 |
|
5899 public: |
|
5900 static inline ICIteratorMore_Native *New(ICStubSpace *space, JitCode *code) { |
|
5901 if (!code) |
|
5902 return nullptr; |
|
5903 return space->allocate<ICIteratorMore_Native>(code); |
|
5904 } |
|
5905 |
|
5906 class Compiler : public ICStubCompiler { |
|
5907 protected: |
|
5908 bool generateStubCode(MacroAssembler &masm); |
|
5909 |
|
5910 public: |
|
5911 Compiler(JSContext *cx) |
|
5912 : ICStubCompiler(cx, ICStub::IteratorMore_Native) |
|
5913 { } |
|
5914 |
|
5915 ICStub *getStub(ICStubSpace *space) { |
|
5916 return ICIteratorMore_Native::New(space, getStubCode()); |
|
5917 } |
|
5918 }; |
|
5919 }; |
|
5920 |
|
5921 // IC for getting the next value in an iterator. |
|
5922 class ICIteratorNext_Fallback : public ICFallbackStub |
|
5923 { |
|
5924 friend class ICStubSpace; |
|
5925 |
|
5926 ICIteratorNext_Fallback(JitCode *stubCode) |
|
5927 : ICFallbackStub(ICStub::IteratorNext_Fallback, stubCode) |
|
5928 { } |
|
5929 |
|
5930 public: |
|
5931 static inline ICIteratorNext_Fallback *New(ICStubSpace *space, JitCode *code) { |
|
5932 if (!code) |
|
5933 return nullptr; |
|
5934 return space->allocate<ICIteratorNext_Fallback>(code); |
|
5935 } |
|
5936 |
|
5937 void setHasNonStringResult() { |
|
5938 JS_ASSERT(extra_ == 0); |
|
5939 extra_ = 1; |
|
5940 } |
|
5941 bool hasNonStringResult() const { |
|
5942 return extra_; |
|
5943 } |
|
5944 |
|
5945 class Compiler : public ICStubCompiler { |
|
5946 protected: |
|
5947 bool generateStubCode(MacroAssembler &masm); |
|
5948 |
|
5949 public: |
|
5950 Compiler(JSContext *cx) |
|
5951 : ICStubCompiler(cx, ICStub::IteratorNext_Fallback) |
|
5952 { } |
|
5953 |
|
5954 ICStub *getStub(ICStubSpace *space) { |
|
5955 return ICIteratorNext_Fallback::New(space, getStubCode()); |
|
5956 } |
|
5957 }; |
|
5958 }; |
|
5959 |
|
5960 // IC for getting the next value in a native iterator. |
|
5961 class ICIteratorNext_Native : public ICStub |
|
5962 { |
|
5963 friend class ICStubSpace; |
|
5964 |
|
5965 ICIteratorNext_Native(JitCode *stubCode) |
|
5966 : ICStub(ICStub::IteratorNext_Native, stubCode) |
|
5967 { } |
|
5968 |
|
5969 public: |
|
5970 static inline ICIteratorNext_Native *New(ICStubSpace *space, JitCode *code) { |
|
5971 if (!code) |
|
5972 return nullptr; |
|
5973 return space->allocate<ICIteratorNext_Native>(code); |
|
5974 } |
|
5975 |
|
5976 class Compiler : public ICStubCompiler { |
|
5977 protected: |
|
5978 bool generateStubCode(MacroAssembler &masm); |
|
5979 |
|
5980 public: |
|
5981 Compiler(JSContext *cx) |
|
5982 : ICStubCompiler(cx, ICStub::IteratorNext_Native) |
|
5983 { } |
|
5984 |
|
5985 ICStub *getStub(ICStubSpace *space) { |
|
5986 return ICIteratorNext_Native::New(space, getStubCode()); |
|
5987 } |
|
5988 }; |
|
5989 }; |
|
5990 |
|
5991 // IC for closing an iterator. |
|
5992 class ICIteratorClose_Fallback : public ICFallbackStub |
|
5993 { |
|
5994 friend class ICStubSpace; |
|
5995 |
|
5996 ICIteratorClose_Fallback(JitCode *stubCode) |
|
5997 : ICFallbackStub(ICStub::IteratorClose_Fallback, stubCode) |
|
5998 { } |
|
5999 |
|
6000 public: |
|
6001 static inline ICIteratorClose_Fallback *New(ICStubSpace *space, JitCode *code) { |
|
6002 if (!code) |
|
6003 return nullptr; |
|
6004 return space->allocate<ICIteratorClose_Fallback>(code); |
|
6005 } |
|
6006 |
|
6007 class Compiler : public ICStubCompiler { |
|
6008 protected: |
|
6009 bool generateStubCode(MacroAssembler &masm); |
|
6010 |
|
6011 public: |
|
6012 Compiler(JSContext *cx) |
|
6013 : ICStubCompiler(cx, ICStub::IteratorClose_Fallback) |
|
6014 { } |
|
6015 |
|
6016 ICStub *getStub(ICStubSpace *space) { |
|
6017 return ICIteratorClose_Fallback::New(space, getStubCode()); |
|
6018 } |
|
6019 }; |
|
6020 }; |
|
6021 |
|
6022 // InstanceOf |
|
6023 // JSOP_INSTANCEOF |
|
6024 class ICInstanceOf_Fallback : public ICFallbackStub |
|
6025 { |
|
6026 friend class ICStubSpace; |
|
6027 |
|
6028 ICInstanceOf_Fallback(JitCode *stubCode) |
|
6029 : ICFallbackStub(ICStub::InstanceOf_Fallback, stubCode) |
|
6030 { } |
|
6031 |
|
6032 public: |
|
6033 static inline ICInstanceOf_Fallback *New(ICStubSpace *space, JitCode *code) { |
|
6034 if (!code) |
|
6035 return nullptr; |
|
6036 return space->allocate<ICInstanceOf_Fallback>(code); |
|
6037 } |
|
6038 |
|
6039 class Compiler : public ICStubCompiler { |
|
6040 protected: |
|
6041 bool generateStubCode(MacroAssembler &masm); |
|
6042 |
|
6043 public: |
|
6044 Compiler(JSContext *cx) |
|
6045 : ICStubCompiler(cx, ICStub::InstanceOf_Fallback) |
|
6046 { } |
|
6047 |
|
6048 ICStub *getStub(ICStubSpace *space) { |
|
6049 return ICInstanceOf_Fallback::New(space, getStubCode()); |
|
6050 } |
|
6051 }; |
|
6052 }; |
|
6053 |
|
6054 // TypeOf |
|
6055 // JSOP_TYPEOF |
|
6056 // JSOP_TYPEOFEXPR |
|
6057 class ICTypeOf_Fallback : public ICFallbackStub |
|
6058 { |
|
6059 friend class ICStubSpace; |
|
6060 |
|
6061 ICTypeOf_Fallback(JitCode *stubCode) |
|
6062 : ICFallbackStub(ICStub::TypeOf_Fallback, stubCode) |
|
6063 { } |
|
6064 |
|
6065 public: |
|
6066 static inline ICTypeOf_Fallback *New(ICStubSpace *space, JitCode *code) { |
|
6067 if (!code) |
|
6068 return nullptr; |
|
6069 return space->allocate<ICTypeOf_Fallback>(code); |
|
6070 } |
|
6071 |
|
6072 class Compiler : public ICStubCompiler { |
|
6073 protected: |
|
6074 bool generateStubCode(MacroAssembler &masm); |
|
6075 |
|
6076 public: |
|
6077 Compiler(JSContext *cx) |
|
6078 : ICStubCompiler(cx, ICStub::TypeOf_Fallback) |
|
6079 { } |
|
6080 |
|
6081 ICStub *getStub(ICStubSpace *space) { |
|
6082 return ICTypeOf_Fallback::New(space, getStubCode()); |
|
6083 } |
|
6084 }; |
|
6085 }; |
|
6086 |
|
6087 class ICTypeOf_Typed : public ICFallbackStub |
|
6088 { |
|
6089 friend class ICStubSpace; |
|
6090 |
|
6091 ICTypeOf_Typed(JitCode *stubCode, JSType type) |
|
6092 : ICFallbackStub(ICStub::TypeOf_Typed, stubCode) |
|
6093 { |
|
6094 extra_ = uint16_t(type); |
|
6095 JS_ASSERT(JSType(extra_) == type); |
|
6096 } |
|
6097 |
|
6098 public: |
|
6099 static inline ICTypeOf_Typed *New(ICStubSpace *space, JitCode *code, JSType type) { |
|
6100 if (!code) |
|
6101 return nullptr; |
|
6102 return space->allocate<ICTypeOf_Typed>(code, type); |
|
6103 } |
|
6104 |
|
6105 JSType type() const { |
|
6106 return JSType(extra_); |
|
6107 } |
|
6108 |
|
6109 class Compiler : public ICStubCompiler { |
|
6110 protected: |
|
6111 JSType type_; |
|
6112 RootedString typeString_; |
|
6113 bool generateStubCode(MacroAssembler &masm); |
|
6114 |
|
6115 virtual int32_t getKey() const { |
|
6116 return static_cast<int32_t>(kind) | (static_cast<int32_t>(type_) << 16); |
|
6117 } |
|
6118 |
|
6119 public: |
|
6120 Compiler(JSContext *cx, JSType type, HandleString string) |
|
6121 : ICStubCompiler(cx, ICStub::TypeOf_Typed), |
|
6122 type_(type), |
|
6123 typeString_(cx, string) |
|
6124 { } |
|
6125 |
|
6126 ICStub *getStub(ICStubSpace *space) { |
|
6127 return ICTypeOf_Typed::New(space, getStubCode(), type_); |
|
6128 } |
|
6129 }; |
|
6130 }; |
|
6131 |
|
6132 class ICRest_Fallback : public ICFallbackStub |
|
6133 { |
|
6134 friend class ICStubSpace; |
|
6135 |
|
6136 HeapPtrObject templateObject_; |
|
6137 |
|
6138 ICRest_Fallback(JitCode *stubCode, JSObject *templateObject) |
|
6139 : ICFallbackStub(ICStub::Rest_Fallback, stubCode), templateObject_(templateObject) |
|
6140 { } |
|
6141 |
|
6142 public: |
|
6143 static const uint32_t MAX_OPTIMIZED_STUBS = 8; |
|
6144 |
|
6145 static inline ICRest_Fallback *New(ICStubSpace *space, JitCode *code, |
|
6146 JSObject *templateObject) { |
|
6147 if (!code) |
|
6148 return nullptr; |
|
6149 return space->allocate<ICRest_Fallback>(code, templateObject); |
|
6150 } |
|
6151 |
|
6152 HeapPtrObject &templateObject() { |
|
6153 return templateObject_; |
|
6154 } |
|
6155 |
|
6156 class Compiler : public ICStubCompiler { |
|
6157 protected: |
|
6158 RootedObject templateObject; |
|
6159 bool generateStubCode(MacroAssembler &masm); |
|
6160 |
|
6161 public: |
|
6162 Compiler(JSContext *cx, JSObject *templateObject) |
|
6163 : ICStubCompiler(cx, ICStub::Rest_Fallback), |
|
6164 templateObject(cx, templateObject) |
|
6165 { } |
|
6166 |
|
6167 ICStub *getStub(ICStubSpace *space) { |
|
6168 return ICRest_Fallback::New(space, getStubCode(), templateObject); |
|
6169 } |
|
6170 }; |
|
6171 }; |
|
6172 |
|
6173 // Stub for JSOP_RETSUB ("returning" from a |finally| block). |
|
6174 class ICRetSub_Fallback : public ICFallbackStub |
|
6175 { |
|
6176 friend class ICStubSpace; |
|
6177 |
|
6178 ICRetSub_Fallback(JitCode *stubCode) |
|
6179 : ICFallbackStub(ICStub::RetSub_Fallback, stubCode) |
|
6180 { } |
|
6181 |
|
6182 public: |
|
6183 static const uint32_t MAX_OPTIMIZED_STUBS = 8; |
|
6184 |
|
6185 static inline ICRetSub_Fallback *New(ICStubSpace *space, JitCode *code) { |
|
6186 if (!code) |
|
6187 return nullptr; |
|
6188 return space->allocate<ICRetSub_Fallback>(code); |
|
6189 } |
|
6190 |
|
6191 class Compiler : public ICStubCompiler { |
|
6192 protected: |
|
6193 bool generateStubCode(MacroAssembler &masm); |
|
6194 |
|
6195 public: |
|
6196 Compiler(JSContext *cx) |
|
6197 : ICStubCompiler(cx, ICStub::RetSub_Fallback) |
|
6198 { } |
|
6199 |
|
6200 ICStub *getStub(ICStubSpace *space) { |
|
6201 return ICRetSub_Fallback::New(space, getStubCode()); |
|
6202 } |
|
6203 }; |
|
6204 }; |
|
6205 |
|
6206 // Optimized JSOP_RETSUB stub. Every stub maps a single pc offset to its |
|
6207 // native code address. |
|
6208 class ICRetSub_Resume : public ICStub |
|
6209 { |
|
6210 friend class ICStubSpace; |
|
6211 |
|
6212 protected: |
|
6213 uint32_t pcOffset_; |
|
6214 uint8_t *addr_; |
|
6215 |
|
6216 ICRetSub_Resume(JitCode *stubCode, uint32_t pcOffset, uint8_t *addr) |
|
6217 : ICStub(ICStub::RetSub_Resume, stubCode), |
|
6218 pcOffset_(pcOffset), |
|
6219 addr_(addr) |
|
6220 { } |
|
6221 |
|
6222 public: |
|
6223 static ICRetSub_Resume *New(ICStubSpace *space, JitCode *code, uint32_t pcOffset, |
|
6224 uint8_t *addr) { |
|
6225 if (!code) |
|
6226 return nullptr; |
|
6227 return space->allocate<ICRetSub_Resume>(code, pcOffset, addr); |
|
6228 } |
|
6229 |
|
6230 static size_t offsetOfPCOffset() { |
|
6231 return offsetof(ICRetSub_Resume, pcOffset_); |
|
6232 } |
|
6233 static size_t offsetOfAddr() { |
|
6234 return offsetof(ICRetSub_Resume, addr_); |
|
6235 } |
|
6236 |
|
6237 class Compiler : public ICStubCompiler { |
|
6238 uint32_t pcOffset_; |
|
6239 uint8_t *addr_; |
|
6240 |
|
6241 bool generateStubCode(MacroAssembler &masm); |
|
6242 |
|
6243 public: |
|
6244 Compiler(JSContext *cx, uint32_t pcOffset, uint8_t *addr) |
|
6245 : ICStubCompiler(cx, ICStub::RetSub_Resume), |
|
6246 pcOffset_(pcOffset), |
|
6247 addr_(addr) |
|
6248 { } |
|
6249 |
|
6250 ICStub *getStub(ICStubSpace *space) { |
|
6251 return ICRetSub_Resume::New(space, getStubCode(), pcOffset_, addr_); |
|
6252 } |
|
6253 }; |
|
6254 }; |
|
6255 |
|
6256 } // namespace jit |
|
6257 } // namespace js |
|
6258 |
|
6259 #endif // JS_ION |
|
6260 |
|
6261 #endif /* jit_BaselineIC_h */ |