js/src/jit/BaselineIC.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial