js/src/jit/x64/BaselineHelpers-x64.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_x64_BaselineHelpers_x64_h
michael@0 8 #define jit_x64_BaselineHelpers_x64_h
michael@0 9
michael@0 10 #ifdef JS_ION
michael@0 11 #include "jit/BaselineFrame.h"
michael@0 12 #include "jit/BaselineIC.h"
michael@0 13 #include "jit/BaselineRegisters.h"
michael@0 14 #include "jit/IonMacroAssembler.h"
michael@0 15
michael@0 16 namespace js {
michael@0 17 namespace jit {
michael@0 18
michael@0 19 // Distance from Stack top to the top Value inside an IC stub (this is the return address).
michael@0 20 static const size_t ICStackValueOffset = sizeof(void *);
michael@0 21
michael@0 22 inline void
michael@0 23 EmitRestoreTailCallReg(MacroAssembler &masm)
michael@0 24 {
michael@0 25 masm.pop(BaselineTailCallReg);
michael@0 26 }
michael@0 27
michael@0 28 inline void
michael@0 29 EmitRepushTailCallReg(MacroAssembler &masm)
michael@0 30 {
michael@0 31 masm.push(BaselineTailCallReg);
michael@0 32 }
michael@0 33
michael@0 34 inline void
michael@0 35 EmitCallIC(CodeOffsetLabel *patchOffset, MacroAssembler &masm)
michael@0 36 {
michael@0 37 // Move ICEntry offset into BaselineStubReg
michael@0 38 CodeOffsetLabel offset = masm.movWithPatch(ImmWord(-1), BaselineStubReg);
michael@0 39 *patchOffset = offset;
michael@0 40
michael@0 41 // Load stub pointer into BaselineStubReg
michael@0 42 masm.loadPtr(Address(BaselineStubReg, (int32_t) ICEntry::offsetOfFirstStub()),
michael@0 43 BaselineStubReg);
michael@0 44
michael@0 45 // Call the stubcode.
michael@0 46 masm.call(Operand(BaselineStubReg, ICStub::offsetOfStubCode()));
michael@0 47 }
michael@0 48
michael@0 49 inline void
michael@0 50 EmitEnterTypeMonitorIC(MacroAssembler &masm,
michael@0 51 size_t monitorStubOffset = ICMonitoredStub::offsetOfFirstMonitorStub())
michael@0 52 {
michael@0 53 // This is expected to be called from within an IC, when BaselineStubReg
michael@0 54 // is properly initialized to point to the stub.
michael@0 55 masm.loadPtr(Address(BaselineStubReg, (int32_t) monitorStubOffset), BaselineStubReg);
michael@0 56
michael@0 57 // Jump to the stubcode.
michael@0 58 masm.jmp(Operand(BaselineStubReg, (int32_t) ICStub::offsetOfStubCode()));
michael@0 59 }
michael@0 60
michael@0 61 inline void
michael@0 62 EmitReturnFromIC(MacroAssembler &masm)
michael@0 63 {
michael@0 64 masm.ret();
michael@0 65 }
michael@0 66
michael@0 67 inline void
michael@0 68 EmitChangeICReturnAddress(MacroAssembler &masm, Register reg)
michael@0 69 {
michael@0 70 masm.storePtr(reg, Address(StackPointer, 0));
michael@0 71 }
michael@0 72
michael@0 73 inline void
michael@0 74 EmitTailCallVM(JitCode *target, MacroAssembler &masm, uint32_t argSize)
michael@0 75 {
michael@0 76 // We an assume during this that R0 and R1 have been pushed.
michael@0 77 masm.movq(BaselineFrameReg, ScratchReg);
michael@0 78 masm.addq(Imm32(BaselineFrame::FramePointerOffset), ScratchReg);
michael@0 79 masm.subq(BaselineStackReg, ScratchReg);
michael@0 80
michael@0 81 // Store frame size without VMFunction arguments for GC marking.
michael@0 82 masm.movq(ScratchReg, rdx);
michael@0 83 masm.subq(Imm32(argSize), rdx);
michael@0 84 masm.store32(rdx, Address(BaselineFrameReg, BaselineFrame::reverseOffsetOfFrameSize()));
michael@0 85
michael@0 86 // Push frame descriptor and perform the tail call.
michael@0 87 masm.makeFrameDescriptor(ScratchReg, JitFrame_BaselineJS);
michael@0 88 masm.push(ScratchReg);
michael@0 89 masm.push(BaselineTailCallReg);
michael@0 90 masm.jmp(target);
michael@0 91 }
michael@0 92
michael@0 93 inline void
michael@0 94 EmitCreateStubFrameDescriptor(MacroAssembler &masm, Register reg)
michael@0 95 {
michael@0 96 // Compute stub frame size. We have to add two pointers: the stub reg and previous
michael@0 97 // frame pointer pushed by EmitEnterStubFrame.
michael@0 98 masm.movq(BaselineFrameReg, reg);
michael@0 99 masm.addq(Imm32(sizeof(void *) * 2), reg);
michael@0 100 masm.subq(BaselineStackReg, reg);
michael@0 101
michael@0 102 masm.makeFrameDescriptor(reg, JitFrame_BaselineStub);
michael@0 103 }
michael@0 104
michael@0 105 inline void
michael@0 106 EmitCallVM(JitCode *target, MacroAssembler &masm)
michael@0 107 {
michael@0 108 EmitCreateStubFrameDescriptor(masm, ScratchReg);
michael@0 109 masm.push(ScratchReg);
michael@0 110 masm.call(target);
michael@0 111 }
michael@0 112
michael@0 113 // Size of vales pushed by EmitEnterStubFrame.
michael@0 114 static const uint32_t STUB_FRAME_SIZE = 4 * sizeof(void *);
michael@0 115 static const uint32_t STUB_FRAME_SAVED_STUB_OFFSET = sizeof(void *);
michael@0 116
michael@0 117 inline void
michael@0 118 EmitEnterStubFrame(MacroAssembler &masm, Register)
michael@0 119 {
michael@0 120 EmitRestoreTailCallReg(masm);
michael@0 121
michael@0 122 // Compute frame size.
michael@0 123 masm.movq(BaselineFrameReg, ScratchReg);
michael@0 124 masm.addq(Imm32(BaselineFrame::FramePointerOffset), ScratchReg);
michael@0 125 masm.subq(BaselineStackReg, ScratchReg);
michael@0 126
michael@0 127 masm.store32(ScratchReg, Address(BaselineFrameReg, BaselineFrame::reverseOffsetOfFrameSize()));
michael@0 128
michael@0 129 // Note: when making changes here, don't forget to update STUB_FRAME_SIZE
michael@0 130 // if needed.
michael@0 131
michael@0 132 // Push frame descriptor and return address.
michael@0 133 masm.makeFrameDescriptor(ScratchReg, JitFrame_BaselineJS);
michael@0 134 masm.push(ScratchReg);
michael@0 135 masm.push(BaselineTailCallReg);
michael@0 136
michael@0 137 // Save old frame pointer, stack pointer and stub reg.
michael@0 138 masm.push(BaselineStubReg);
michael@0 139 masm.push(BaselineFrameReg);
michael@0 140 masm.mov(BaselineStackReg, BaselineFrameReg);
michael@0 141 }
michael@0 142
michael@0 143 inline void
michael@0 144 EmitLeaveStubFrameHead(MacroAssembler &masm, bool calledIntoIon = false)
michael@0 145 {
michael@0 146 // Ion frames do not save and restore the frame pointer. If we called
michael@0 147 // into Ion, we have to restore the stack pointer from the frame descriptor.
michael@0 148 // If we performed a VM call, the descriptor has been popped already so
michael@0 149 // in that case we use the frame pointer.
michael@0 150 if (calledIntoIon) {
michael@0 151 masm.pop(ScratchReg);
michael@0 152 masm.shrq(Imm32(FRAMESIZE_SHIFT), ScratchReg);
michael@0 153 masm.addq(ScratchReg, BaselineStackReg);
michael@0 154 } else {
michael@0 155 masm.mov(BaselineFrameReg, BaselineStackReg);
michael@0 156 }
michael@0 157 }
michael@0 158
michael@0 159 inline void
michael@0 160 EmitLeaveStubFrameCommonTail(MacroAssembler &masm)
michael@0 161 {
michael@0 162 masm.pop(BaselineFrameReg);
michael@0 163 masm.pop(BaselineStubReg);
michael@0 164
michael@0 165 // Pop return address.
michael@0 166 masm.pop(BaselineTailCallReg);
michael@0 167
michael@0 168 // Overwrite frame descriptor with return address, so that the stack matches
michael@0 169 // the state before entering the stub frame.
michael@0 170 masm.storePtr(BaselineTailCallReg, Address(BaselineStackReg, 0));
michael@0 171 }
michael@0 172
michael@0 173 inline void
michael@0 174 EmitLeaveStubFrame(MacroAssembler &masm, bool calledIntoIon = false)
michael@0 175 {
michael@0 176 EmitLeaveStubFrameHead(masm, calledIntoIon);
michael@0 177 EmitLeaveStubFrameCommonTail(masm);
michael@0 178 }
michael@0 179
michael@0 180 inline void
michael@0 181 EmitStowICValues(MacroAssembler &masm, int values)
michael@0 182 {
michael@0 183 JS_ASSERT(values >= 0 && values <= 2);
michael@0 184 switch(values) {
michael@0 185 case 1:
michael@0 186 // Stow R0
michael@0 187 masm.pop(BaselineTailCallReg);
michael@0 188 masm.pushValue(R0);
michael@0 189 masm.push(BaselineTailCallReg);
michael@0 190 break;
michael@0 191 case 2:
michael@0 192 // Stow R0 and R1
michael@0 193 masm.pop(BaselineTailCallReg);
michael@0 194 masm.pushValue(R0);
michael@0 195 masm.pushValue(R1);
michael@0 196 masm.push(BaselineTailCallReg);
michael@0 197 break;
michael@0 198 }
michael@0 199 }
michael@0 200
michael@0 201 inline void
michael@0 202 EmitUnstowICValues(MacroAssembler &masm, int values, bool discard = false)
michael@0 203 {
michael@0 204 JS_ASSERT(values >= 0 && values <= 2);
michael@0 205 switch(values) {
michael@0 206 case 1:
michael@0 207 // Unstow R0
michael@0 208 masm.pop(BaselineTailCallReg);
michael@0 209 if (discard)
michael@0 210 masm.addPtr(Imm32(sizeof(Value)), BaselineStackReg);
michael@0 211 else
michael@0 212 masm.popValue(R0);
michael@0 213 masm.push(BaselineTailCallReg);
michael@0 214 break;
michael@0 215 case 2:
michael@0 216 // Unstow R0 and R1
michael@0 217 masm.pop(BaselineTailCallReg);
michael@0 218 if (discard) {
michael@0 219 masm.addPtr(Imm32(sizeof(Value) * 2), BaselineStackReg);
michael@0 220 } else {
michael@0 221 masm.popValue(R1);
michael@0 222 masm.popValue(R0);
michael@0 223 }
michael@0 224 masm.push(BaselineTailCallReg);
michael@0 225 break;
michael@0 226 }
michael@0 227 }
michael@0 228
michael@0 229 inline void
michael@0 230 EmitCallTypeUpdateIC(MacroAssembler &masm, JitCode *code, uint32_t objectOffset)
michael@0 231 {
michael@0 232 // R0 contains the value that needs to be typechecked.
michael@0 233 // The object we're updating is a boxed Value on the stack, at offset
michael@0 234 // objectOffset from stack top, excluding the return address.
michael@0 235
michael@0 236 // Save the current BaselineStubReg to stack
michael@0 237 masm.push(BaselineStubReg);
michael@0 238
michael@0 239 // This is expected to be called from within an IC, when BaselineStubReg
michael@0 240 // is properly initialized to point to the stub.
michael@0 241 masm.loadPtr(Address(BaselineStubReg, (int32_t) ICUpdatedStub::offsetOfFirstUpdateStub()),
michael@0 242 BaselineStubReg);
michael@0 243
michael@0 244 // Call the stubcode.
michael@0 245 masm.call(Operand(BaselineStubReg, ICStub::offsetOfStubCode()));
michael@0 246
michael@0 247 // Restore the old stub reg.
michael@0 248 masm.pop(BaselineStubReg);
michael@0 249
michael@0 250 // The update IC will store 0 or 1 in R1.scratchReg() reflecting if the
michael@0 251 // value in R0 type-checked properly or not.
michael@0 252 Label success;
michael@0 253 masm.cmp32(R1.scratchReg(), Imm32(1));
michael@0 254 masm.j(Assembler::Equal, &success);
michael@0 255
michael@0 256 // If the IC failed, then call the update fallback function.
michael@0 257 EmitEnterStubFrame(masm, R1.scratchReg());
michael@0 258
michael@0 259 masm.loadValue(Address(BaselineStackReg, STUB_FRAME_SIZE + objectOffset), R1);
michael@0 260
michael@0 261 masm.pushValue(R0);
michael@0 262 masm.pushValue(R1);
michael@0 263 masm.push(BaselineStubReg);
michael@0 264
michael@0 265 // Load previous frame pointer, push BaselineFrame *.
michael@0 266 masm.loadPtr(Address(BaselineFrameReg, 0), R0.scratchReg());
michael@0 267 masm.pushBaselineFramePtr(R0.scratchReg(), R0.scratchReg());
michael@0 268
michael@0 269 EmitCallVM(code, masm);
michael@0 270 EmitLeaveStubFrame(masm);
michael@0 271
michael@0 272 // Success at end.
michael@0 273 masm.bind(&success);
michael@0 274 }
michael@0 275
michael@0 276 template <typename AddrType>
michael@0 277 inline void
michael@0 278 EmitPreBarrier(MacroAssembler &masm, const AddrType &addr, MIRType type)
michael@0 279 {
michael@0 280 masm.patchableCallPreBarrier(addr, type);
michael@0 281 }
michael@0 282
michael@0 283 inline void
michael@0 284 EmitStubGuardFailure(MacroAssembler &masm)
michael@0 285 {
michael@0 286 // NOTE: This routine assumes that the stub guard code left the stack in the
michael@0 287 // same state it was in when it was entered.
michael@0 288
michael@0 289 // BaselineStubEntry points to the current stub.
michael@0 290
michael@0 291 // Load next stub into BaselineStubReg
michael@0 292 masm.loadPtr(Address(BaselineStubReg, ICStub::offsetOfNext()), BaselineStubReg);
michael@0 293
michael@0 294 // Return address is already loaded, just jump to the next stubcode.
michael@0 295 masm.jmp(Operand(BaselineStubReg, ICStub::offsetOfStubCode()));
michael@0 296 }
michael@0 297
michael@0 298
michael@0 299 } // namespace jit
michael@0 300 } // namespace js
michael@0 301
michael@0 302 #endif // JS_ION
michael@0 303
michael@0 304 #endif /* jit_x64_BaselineHelpers_x64_h */

mercurial