~oif-team/ubuntu/natty/qt4-x11/xi2.1

« back to all changes in this revision

Viewing changes to src/3rdparty/webkit/JavaScriptCore/jit/JITInlineMethods.h

  • Committer: Bazaar Package Importer
  • Author(s): Alessandro Ghersi
  • Date: 2009-11-02 18:30:08 UTC
  • mfrom: (1.2.2 upstream)
  • mto: (15.2.5 experimental)
  • mto: This revision was merged to the branch mainline in revision 88.
  • Revision ID: james.westby@ubuntu.com-20091102183008-b6a4gcs128mvfb3m
Tags: upstream-4.6.0~beta1
ImportĀ upstreamĀ versionĀ 4.6.0~beta1

Show diffs side-by-side

added added

removed removed

Lines of Context:
30
30
 
31
31
#if ENABLE(JIT)
32
32
 
33
 
#if PLATFORM(WIN)
34
 
#undef FIELD_OFFSET // Fix conflict with winnt.h.
35
 
#endif
36
 
 
37
 
// FIELD_OFFSET: Like the C++ offsetof macro, but you can use it with classes.
38
 
// The magic number 0x4000 is insignificant. We use it to avoid using NULL, since
39
 
// NULL can cause compiler problems, especially in cases of multiple inheritance.
40
 
#define FIELD_OFFSET(class, field) (reinterpret_cast<ptrdiff_t>(&(reinterpret_cast<class*>(0x4000)->field)) - 0x4000)
41
 
 
42
33
namespace JSC {
43
34
 
 
35
/* Deprecated: Please use JITStubCall instead. */
 
36
 
 
37
// puts an arg onto the stack, as an arg to a context threaded function.
 
38
ALWAYS_INLINE void JIT::emitPutJITStubArg(RegisterID src, unsigned argumentNumber)
 
39
{
 
40
    unsigned argumentStackOffset = (argumentNumber * (sizeof(JSValue) / sizeof(void*))) + 1;
 
41
    poke(src, argumentStackOffset);
 
42
}
 
43
 
 
44
/* Deprecated: Please use JITStubCall instead. */
 
45
 
 
46
ALWAYS_INLINE void JIT::emitPutJITStubArgConstant(unsigned value, unsigned argumentNumber)
 
47
{
 
48
    unsigned argumentStackOffset = (argumentNumber * (sizeof(JSValue) / sizeof(void*))) + 1;
 
49
    poke(Imm32(value), argumentStackOffset);
 
50
}
 
51
 
 
52
/* Deprecated: Please use JITStubCall instead. */
 
53
 
 
54
ALWAYS_INLINE void JIT::emitPutJITStubArgConstant(void* value, unsigned argumentNumber)
 
55
{
 
56
    unsigned argumentStackOffset = (argumentNumber * (sizeof(JSValue) / sizeof(void*))) + 1;
 
57
    poke(ImmPtr(value), argumentStackOffset);
 
58
}
 
59
 
 
60
/* Deprecated: Please use JITStubCall instead. */
 
61
 
 
62
ALWAYS_INLINE void JIT::emitGetJITStubArg(unsigned argumentNumber, RegisterID dst)
 
63
{
 
64
    unsigned argumentStackOffset = (argumentNumber * (sizeof(JSValue) / sizeof(void*))) + 1;
 
65
    peek(dst, argumentStackOffset);
 
66
}
 
67
 
 
68
ALWAYS_INLINE bool JIT::isOperandConstantImmediateDouble(unsigned src)
 
69
{
 
70
    return m_codeBlock->isConstantRegisterIndex(src) && getConstantOperand(src).isDouble();
 
71
}
 
72
 
 
73
ALWAYS_INLINE JSValue JIT::getConstantOperand(unsigned src)
 
74
{
 
75
    ASSERT(m_codeBlock->isConstantRegisterIndex(src));
 
76
    return m_codeBlock->getConstant(src);
 
77
}
 
78
 
 
79
ALWAYS_INLINE void JIT::emitPutToCallFrameHeader(RegisterID from, RegisterFile::CallFrameHeaderEntry entry)
 
80
{
 
81
    storePtr(from, Address(callFrameRegister, entry * sizeof(Register)));
 
82
}
 
83
 
 
84
ALWAYS_INLINE void JIT::emitPutImmediateToCallFrameHeader(void* value, RegisterFile::CallFrameHeaderEntry entry)
 
85
{
 
86
    storePtr(ImmPtr(value), Address(callFrameRegister, entry * sizeof(Register)));
 
87
}
 
88
 
 
89
ALWAYS_INLINE void JIT::emitGetFromCallFrameHeaderPtr(RegisterFile::CallFrameHeaderEntry entry, RegisterID to, RegisterID from)
 
90
{
 
91
    loadPtr(Address(from, entry * sizeof(Register)), to);
 
92
#if !USE(JSVALUE32_64)
 
93
    killLastResultRegister();
 
94
#endif
 
95
}
 
96
 
 
97
ALWAYS_INLINE void JIT::emitGetFromCallFrameHeader32(RegisterFile::CallFrameHeaderEntry entry, RegisterID to, RegisterID from)
 
98
{
 
99
    load32(Address(from, entry * sizeof(Register)), to);
 
100
#if !USE(JSVALUE32_64)
 
101
    killLastResultRegister();
 
102
#endif
 
103
}
 
104
 
 
105
ALWAYS_INLINE JIT::Call JIT::emitNakedCall(CodePtr function)
 
106
{
 
107
    ASSERT(m_bytecodeIndex != (unsigned)-1); // This method should only be called during hot/cold path generation, so that m_bytecodeIndex is set.
 
108
 
 
109
    Call nakedCall = nearCall();
 
110
    m_calls.append(CallRecord(nakedCall, m_bytecodeIndex, function.executableAddress()));
 
111
    return nakedCall;
 
112
}
 
113
 
 
114
#if defined(ASSEMBLER_HAS_CONSTANT_POOL) && ASSEMBLER_HAS_CONSTANT_POOL
 
115
 
 
116
ALWAYS_INLINE void JIT::beginUninterruptedSequence(int insnSpace, int constSpace)
 
117
{
 
118
#if PLATFORM(ARM_TRADITIONAL)
 
119
#ifndef NDEBUG
 
120
    // Ensure the label after the sequence can also fit
 
121
    insnSpace += sizeof(ARMWord);
 
122
    constSpace += sizeof(uint64_t);
 
123
#endif
 
124
 
 
125
    ensureSpace(insnSpace, constSpace);
 
126
 
 
127
#endif
 
128
 
 
129
#if defined(ASSEMBLER_HAS_CONSTANT_POOL) && ASSEMBLER_HAS_CONSTANT_POOL
 
130
#ifndef NDEBUG
 
131
    m_uninterruptedInstructionSequenceBegin = label();
 
132
    m_uninterruptedConstantSequenceBegin = sizeOfConstantPool();
 
133
#endif
 
134
#endif
 
135
}
 
136
 
 
137
ALWAYS_INLINE void JIT::endUninterruptedSequence(int insnSpace, int constSpace)
 
138
{
 
139
#if defined(ASSEMBLER_HAS_CONSTANT_POOL) && ASSEMBLER_HAS_CONSTANT_POOL
 
140
    ASSERT(differenceBetween(m_uninterruptedInstructionSequenceBegin, label()) == insnSpace);
 
141
    ASSERT(sizeOfConstantPool() - m_uninterruptedConstantSequenceBegin == constSpace);
 
142
#endif
 
143
}
 
144
 
 
145
#endif
 
146
 
 
147
#if PLATFORM(ARM_THUMB2)
 
148
 
 
149
ALWAYS_INLINE void JIT::preserveReturnAddressAfterCall(RegisterID reg)
 
150
{
 
151
    move(linkRegister, reg);
 
152
}
 
153
 
 
154
ALWAYS_INLINE void JIT::restoreReturnAddressBeforeReturn(RegisterID reg)
 
155
{
 
156
    move(reg, linkRegister);
 
157
}
 
158
 
 
159
ALWAYS_INLINE void JIT::restoreReturnAddressBeforeReturn(Address address)
 
160
{
 
161
    loadPtr(address, linkRegister);
 
162
}
 
163
 
 
164
#else // PLATFORM(X86) || PLATFORM(X86_64) || PLATFORM(ARM_TRADITIONAL)
 
165
 
 
166
ALWAYS_INLINE void JIT::preserveReturnAddressAfterCall(RegisterID reg)
 
167
{
 
168
    pop(reg);
 
169
}
 
170
 
 
171
ALWAYS_INLINE void JIT::restoreReturnAddressBeforeReturn(RegisterID reg)
 
172
{
 
173
    push(reg);
 
174
}
 
175
 
 
176
ALWAYS_INLINE void JIT::restoreReturnAddressBeforeReturn(Address address)
 
177
{
 
178
    push(address);
 
179
}
 
180
 
 
181
#endif
 
182
 
 
183
#if USE(JIT_STUB_ARGUMENT_VA_LIST)
 
184
ALWAYS_INLINE void JIT::restoreArgumentReference()
 
185
{
 
186
    poke(callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof (void*));
 
187
}
 
188
ALWAYS_INLINE void JIT::restoreArgumentReferenceForTrampoline() {}
 
189
#else
 
190
ALWAYS_INLINE void JIT::restoreArgumentReference()
 
191
{
 
192
    move(stackPointerRegister, firstArgumentRegister);
 
193
    poke(callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof (void*));
 
194
#if PLATFORM(ARM_TRADITIONAL)
 
195
    move(ctiReturnRegister, ARMRegisters::lr);
 
196
#endif
 
197
}
 
198
ALWAYS_INLINE void JIT::restoreArgumentReferenceForTrampoline()
 
199
{
 
200
#if PLATFORM(X86)
 
201
    // Within a trampoline the return address will be on the stack at this point.
 
202
    addPtr(Imm32(sizeof(void*)), stackPointerRegister, firstArgumentRegister);
 
203
#elif PLATFORM(ARM_THUMB2)
 
204
    move(stackPointerRegister, firstArgumentRegister);
 
205
#endif
 
206
    // In the trampoline on x86-64, the first argument register is not overwritten.
 
207
}
 
208
#endif
 
209
 
 
210
ALWAYS_INLINE JIT::Jump JIT::checkStructure(RegisterID reg, Structure* structure)
 
211
{
 
212
    return branchPtr(NotEqual, Address(reg, OBJECT_OFFSETOF(JSCell, m_structure)), ImmPtr(structure));
 
213
}
 
214
 
 
215
ALWAYS_INLINE void JIT::linkSlowCaseIfNotJSCell(Vector<SlowCaseEntry>::iterator& iter, int vReg)
 
216
{
 
217
    if (!m_codeBlock->isKnownNotImmediate(vReg))
 
218
        linkSlowCase(iter);
 
219
}
 
220
 
 
221
ALWAYS_INLINE void JIT::addSlowCase(Jump jump)
 
222
{
 
223
    ASSERT(m_bytecodeIndex != (unsigned)-1); // This method should only be called during hot/cold path generation, so that m_bytecodeIndex is set.
 
224
 
 
225
    m_slowCases.append(SlowCaseEntry(jump, m_bytecodeIndex));
 
226
}
 
227
 
 
228
ALWAYS_INLINE void JIT::addSlowCase(JumpList jumpList)
 
229
{
 
230
    ASSERT(m_bytecodeIndex != (unsigned)-1); // This method should only be called during hot/cold path generation, so that m_bytecodeIndex is set.
 
231
 
 
232
    const JumpList::JumpVector& jumpVector = jumpList.jumps();
 
233
    size_t size = jumpVector.size();
 
234
    for (size_t i = 0; i < size; ++i)
 
235
        m_slowCases.append(SlowCaseEntry(jumpVector[i], m_bytecodeIndex));
 
236
}
 
237
 
 
238
ALWAYS_INLINE void JIT::addJump(Jump jump, int relativeOffset)
 
239
{
 
240
    ASSERT(m_bytecodeIndex != (unsigned)-1); // This method should only be called during hot/cold path generation, so that m_bytecodeIndex is set.
 
241
 
 
242
    m_jmpTable.append(JumpTable(jump, m_bytecodeIndex + relativeOffset));
 
243
}
 
244
 
 
245
ALWAYS_INLINE void JIT::emitJumpSlowToHot(Jump jump, int relativeOffset)
 
246
{
 
247
    ASSERT(m_bytecodeIndex != (unsigned)-1); // This method should only be called during hot/cold path generation, so that m_bytecodeIndex is set.
 
248
 
 
249
    jump.linkTo(m_labels[m_bytecodeIndex + relativeOffset], this);
 
250
}
 
251
 
 
252
#if ENABLE(SAMPLING_FLAGS)
 
253
ALWAYS_INLINE void JIT::setSamplingFlag(int32_t flag)
 
254
{
 
255
    ASSERT(flag >= 1);
 
256
    ASSERT(flag <= 32);
 
257
    or32(Imm32(1u << (flag - 1)), AbsoluteAddress(&SamplingFlags::s_flags));
 
258
}
 
259
 
 
260
ALWAYS_INLINE void JIT::clearSamplingFlag(int32_t flag)
 
261
{
 
262
    ASSERT(flag >= 1);
 
263
    ASSERT(flag <= 32);
 
264
    and32(Imm32(~(1u << (flag - 1))), AbsoluteAddress(&SamplingFlags::s_flags));
 
265
}
 
266
#endif
 
267
 
 
268
#if ENABLE(SAMPLING_COUNTERS)
 
269
ALWAYS_INLINE void JIT::emitCount(AbstractSamplingCounter& counter, uint32_t count)
 
270
{
 
271
#if PLATFORM(X86_64) // Or any other 64-bit plattform.
 
272
    addPtr(Imm32(count), AbsoluteAddress(&counter.m_counter));
 
273
#elif PLATFORM(X86) // Or any other little-endian 32-bit plattform.
 
274
    intptr_t hiWord = reinterpret_cast<intptr_t>(&counter.m_counter) + sizeof(int32_t);
 
275
    add32(Imm32(count), AbsoluteAddress(&counter.m_counter));
 
276
    addWithCarry32(Imm32(0), AbsoluteAddress(reinterpret_cast<void*>(hiWord)));
 
277
#else
 
278
#error "SAMPLING_FLAGS not implemented on this platform."
 
279
#endif
 
280
}
 
281
#endif
 
282
 
 
283
#if ENABLE(OPCODE_SAMPLING)
 
284
#if PLATFORM(X86_64)
 
285
ALWAYS_INLINE void JIT::sampleInstruction(Instruction* instruction, bool inHostFunction)
 
286
{
 
287
    move(ImmPtr(m_interpreter->sampler()->sampleSlot()), X86Registers::ecx);
 
288
    storePtr(ImmPtr(m_interpreter->sampler()->encodeSample(instruction, inHostFunction)), X86Registers::ecx);
 
289
}
 
290
#else
 
291
ALWAYS_INLINE void JIT::sampleInstruction(Instruction* instruction, bool inHostFunction)
 
292
{
 
293
    storePtr(ImmPtr(m_interpreter->sampler()->encodeSample(instruction, inHostFunction)), m_interpreter->sampler()->sampleSlot());
 
294
}
 
295
#endif
 
296
#endif
 
297
 
 
298
#if ENABLE(CODEBLOCK_SAMPLING)
 
299
#if PLATFORM(X86_64)
 
300
ALWAYS_INLINE void JIT::sampleCodeBlock(CodeBlock* codeBlock)
 
301
{
 
302
    move(ImmPtr(m_interpreter->sampler()->codeBlockSlot()), X86Registers::ecx);
 
303
    storePtr(ImmPtr(codeBlock), X86Registers::ecx);
 
304
}
 
305
#else
 
306
ALWAYS_INLINE void JIT::sampleCodeBlock(CodeBlock* codeBlock)
 
307
{
 
308
    storePtr(ImmPtr(codeBlock), m_interpreter->sampler()->codeBlockSlot());
 
309
}
 
310
#endif
 
311
#endif
 
312
 
 
313
inline JIT::Address JIT::addressFor(unsigned index, RegisterID base)
 
314
{
 
315
    return Address(base, (index * sizeof(Register)));
 
316
}
 
317
 
 
318
#if USE(JSVALUE32_64)
 
319
 
 
320
inline JIT::Address JIT::tagFor(unsigned index, RegisterID base)
 
321
{
 
322
    return Address(base, (index * sizeof(Register)) + OBJECT_OFFSETOF(JSValue, u.asBits.tag));
 
323
}
 
324
 
 
325
inline JIT::Address JIT::payloadFor(unsigned index, RegisterID base)
 
326
{
 
327
    return Address(base, (index * sizeof(Register)) + OBJECT_OFFSETOF(JSValue, u.asBits.payload));
 
328
}
 
329
 
 
330
inline void JIT::emitLoadTag(unsigned index, RegisterID tag)
 
331
{
 
332
    RegisterID mappedTag;
 
333
    if (getMappedTag(index, mappedTag)) {
 
334
        move(mappedTag, tag);
 
335
        unmap(tag);
 
336
        return;
 
337
    }
 
338
 
 
339
    if (m_codeBlock->isConstantRegisterIndex(index)) {
 
340
        move(Imm32(getConstantOperand(index).tag()), tag);
 
341
        unmap(tag);
 
342
        return;
 
343
    }
 
344
 
 
345
    load32(tagFor(index), tag);
 
346
    unmap(tag);
 
347
}
 
348
 
 
349
inline void JIT::emitLoadPayload(unsigned index, RegisterID payload)
 
350
{
 
351
    RegisterID mappedPayload;
 
352
    if (getMappedPayload(index, mappedPayload)) {
 
353
        move(mappedPayload, payload);
 
354
        unmap(payload);
 
355
        return;
 
356
    }
 
357
 
 
358
    if (m_codeBlock->isConstantRegisterIndex(index)) {
 
359
        move(Imm32(getConstantOperand(index).payload()), payload);
 
360
        unmap(payload);
 
361
        return;
 
362
    }
 
363
 
 
364
    load32(payloadFor(index), payload);
 
365
    unmap(payload);
 
366
}
 
367
 
 
368
inline void JIT::emitLoad(const JSValue& v, RegisterID tag, RegisterID payload)
 
369
{
 
370
    move(Imm32(v.payload()), payload);
 
371
    move(Imm32(v.tag()), tag);
 
372
}
 
373
 
 
374
inline void JIT::emitLoad(unsigned index, RegisterID tag, RegisterID payload, RegisterID base)
 
375
{
 
376
    ASSERT(tag != payload);
 
377
 
 
378
    if (base == callFrameRegister) {
 
379
        ASSERT(payload != base);
 
380
        emitLoadPayload(index, payload);
 
381
        emitLoadTag(index, tag);
 
382
        return;
 
383
    }
 
384
 
 
385
    if (payload == base) { // avoid stomping base
 
386
        load32(tagFor(index, base), tag);
 
387
        load32(payloadFor(index, base), payload);
 
388
        return;
 
389
    }
 
390
 
 
391
    load32(payloadFor(index, base), payload);
 
392
    load32(tagFor(index, base), tag);
 
393
}
 
394
 
 
395
inline void JIT::emitLoad2(unsigned index1, RegisterID tag1, RegisterID payload1, unsigned index2, RegisterID tag2, RegisterID payload2)
 
396
{
 
397
    if (isMapped(index1)) {
 
398
        emitLoad(index1, tag1, payload1);
 
399
        emitLoad(index2, tag2, payload2);
 
400
        return;
 
401
    }
 
402
    emitLoad(index2, tag2, payload2);
 
403
    emitLoad(index1, tag1, payload1);
 
404
}
 
405
 
 
406
inline void JIT::emitLoadDouble(unsigned index, FPRegisterID value)
 
407
{
 
408
    if (m_codeBlock->isConstantRegisterIndex(index)) {
 
409
        Register& inConstantPool = m_codeBlock->constantRegister(index);
 
410
        loadDouble(&inConstantPool, value);
 
411
    } else
 
412
        loadDouble(addressFor(index), value);
 
413
}
 
414
 
 
415
inline void JIT::emitLoadInt32ToDouble(unsigned index, FPRegisterID value)
 
416
{
 
417
    if (m_codeBlock->isConstantRegisterIndex(index)) {
 
418
        Register& inConstantPool = m_codeBlock->constantRegister(index);
 
419
        char* bytePointer = reinterpret_cast<char*>(&inConstantPool);
 
420
        convertInt32ToDouble(AbsoluteAddress(bytePointer + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), value);
 
421
    } else
 
422
        convertInt32ToDouble(payloadFor(index), value);
 
423
}
 
424
 
 
425
inline void JIT::emitStore(unsigned index, RegisterID tag, RegisterID payload, RegisterID base)
 
426
{
 
427
    store32(payload, payloadFor(index, base));
 
428
    store32(tag, tagFor(index, base));
 
429
}
 
430
 
 
431
inline void JIT::emitStoreInt32(unsigned index, RegisterID payload, bool indexIsInt32)
 
432
{
 
433
    store32(payload, payloadFor(index, callFrameRegister));
 
434
    if (!indexIsInt32)
 
435
        store32(Imm32(JSValue::Int32Tag), tagFor(index, callFrameRegister));
 
436
}
 
437
 
 
438
inline void JIT::emitStoreInt32(unsigned index, Imm32 payload, bool indexIsInt32)
 
439
{
 
440
    store32(payload, payloadFor(index, callFrameRegister));
 
441
    if (!indexIsInt32)
 
442
        store32(Imm32(JSValue::Int32Tag), tagFor(index, callFrameRegister));
 
443
}
 
444
 
 
445
inline void JIT::emitStoreCell(unsigned index, RegisterID payload, bool indexIsCell)
 
446
{
 
447
    store32(payload, payloadFor(index, callFrameRegister));
 
448
    if (!indexIsCell)
 
449
        store32(Imm32(JSValue::CellTag), tagFor(index, callFrameRegister));
 
450
}
 
451
 
 
452
inline void JIT::emitStoreBool(unsigned index, RegisterID tag, bool indexIsBool)
 
453
{
 
454
    if (!indexIsBool)
 
455
        store32(Imm32(0), payloadFor(index, callFrameRegister));
 
456
    store32(tag, tagFor(index, callFrameRegister));
 
457
}
 
458
 
 
459
inline void JIT::emitStoreDouble(unsigned index, FPRegisterID value)
 
460
{
 
461
    storeDouble(value, addressFor(index));
 
462
}
 
463
 
 
464
inline void JIT::emitStore(unsigned index, const JSValue constant, RegisterID base)
 
465
{
 
466
    store32(Imm32(constant.payload()), payloadFor(index, base));
 
467
    store32(Imm32(constant.tag()), tagFor(index, base));
 
468
}
 
469
 
 
470
ALWAYS_INLINE void JIT::emitInitRegister(unsigned dst)
 
471
{
 
472
    emitStore(dst, jsUndefined());
 
473
}
 
474
 
 
475
inline bool JIT::isLabeled(unsigned bytecodeIndex)
 
476
{
 
477
    for (size_t numberOfJumpTargets = m_codeBlock->numberOfJumpTargets(); m_jumpTargetIndex != numberOfJumpTargets; ++m_jumpTargetIndex) {
 
478
        unsigned jumpTarget = m_codeBlock->jumpTarget(m_jumpTargetIndex);
 
479
        if (jumpTarget == bytecodeIndex)
 
480
            return true;
 
481
        if (jumpTarget > bytecodeIndex)
 
482
            return false;
 
483
    }
 
484
    return false;
 
485
}
 
486
 
 
487
inline void JIT::map(unsigned bytecodeIndex, unsigned virtualRegisterIndex, RegisterID tag, RegisterID payload)
 
488
{
 
489
    if (isLabeled(bytecodeIndex))
 
490
        return;
 
491
 
 
492
    m_mappedBytecodeIndex = bytecodeIndex;
 
493
    m_mappedVirtualRegisterIndex = virtualRegisterIndex;
 
494
    m_mappedTag = tag;
 
495
    m_mappedPayload = payload;
 
496
}
 
497
 
 
498
inline void JIT::unmap(RegisterID registerID)
 
499
{
 
500
    if (m_mappedTag == registerID)
 
501
        m_mappedTag = (RegisterID)-1;
 
502
    else if (m_mappedPayload == registerID)
 
503
        m_mappedPayload = (RegisterID)-1;
 
504
}
 
505
 
 
506
inline void JIT::unmap()
 
507
{
 
508
    m_mappedBytecodeIndex = (unsigned)-1;
 
509
    m_mappedVirtualRegisterIndex = (unsigned)-1;
 
510
    m_mappedTag = (RegisterID)-1;
 
511
    m_mappedPayload = (RegisterID)-1;
 
512
}
 
513
 
 
514
inline bool JIT::isMapped(unsigned virtualRegisterIndex)
 
515
{
 
516
    if (m_mappedBytecodeIndex != m_bytecodeIndex)
 
517
        return false;
 
518
    if (m_mappedVirtualRegisterIndex != virtualRegisterIndex)
 
519
        return false;
 
520
    return true;
 
521
}
 
522
 
 
523
inline bool JIT::getMappedPayload(unsigned virtualRegisterIndex, RegisterID& payload)
 
524
{
 
525
    if (m_mappedBytecodeIndex != m_bytecodeIndex)
 
526
        return false;
 
527
    if (m_mappedVirtualRegisterIndex != virtualRegisterIndex)
 
528
        return false;
 
529
    if (m_mappedPayload == (RegisterID)-1)
 
530
        return false;
 
531
    payload = m_mappedPayload;
 
532
    return true;
 
533
}
 
534
 
 
535
inline bool JIT::getMappedTag(unsigned virtualRegisterIndex, RegisterID& tag)
 
536
{
 
537
    if (m_mappedBytecodeIndex != m_bytecodeIndex)
 
538
        return false;
 
539
    if (m_mappedVirtualRegisterIndex != virtualRegisterIndex)
 
540
        return false;
 
541
    if (m_mappedTag == (RegisterID)-1)
 
542
        return false;
 
543
    tag = m_mappedTag;
 
544
    return true;
 
545
}
 
546
 
 
547
inline void JIT::emitJumpSlowCaseIfNotJSCell(unsigned virtualRegisterIndex)
 
548
{
 
549
    if (!m_codeBlock->isKnownNotImmediate(virtualRegisterIndex))
 
550
        addSlowCase(branch32(NotEqual, tagFor(virtualRegisterIndex), Imm32(JSValue::CellTag)));
 
551
}
 
552
 
 
553
inline void JIT::emitJumpSlowCaseIfNotJSCell(unsigned virtualRegisterIndex, RegisterID tag)
 
554
{
 
555
    if (!m_codeBlock->isKnownNotImmediate(virtualRegisterIndex))
 
556
        addSlowCase(branch32(NotEqual, tag, Imm32(JSValue::CellTag)));
 
557
}
 
558
 
 
559
inline void JIT::linkSlowCaseIfNotJSCell(Vector<SlowCaseEntry>::iterator& iter, unsigned virtualRegisterIndex)
 
560
{
 
561
    if (!m_codeBlock->isKnownNotImmediate(virtualRegisterIndex))
 
562
        linkSlowCase(iter);
 
563
}
 
564
 
 
565
ALWAYS_INLINE bool JIT::isOperandConstantImmediateInt(unsigned src)
 
566
{
 
567
    return m_codeBlock->isConstantRegisterIndex(src) && getConstantOperand(src).isInt32();
 
568
}
 
569
 
 
570
ALWAYS_INLINE bool JIT::getOperandConstantImmediateInt(unsigned op1, unsigned op2, unsigned& op, int32_t& constant)
 
571
{
 
572
    if (isOperandConstantImmediateInt(op1)) {
 
573
        constant = getConstantOperand(op1).asInt32();
 
574
        op = op2;
 
575
        return true;
 
576
    }
 
577
 
 
578
    if (isOperandConstantImmediateInt(op2)) {
 
579
        constant = getConstantOperand(op2).asInt32();
 
580
        op = op1;
 
581
        return true;
 
582
    }
 
583
    
 
584
    return false;
 
585
}
 
586
 
 
587
/* Deprecated: Please use JITStubCall instead. */
 
588
 
 
589
ALWAYS_INLINE void JIT::emitPutJITStubArg(RegisterID tag, RegisterID payload, unsigned argumentNumber)
 
590
{
 
591
    unsigned argumentStackOffset = (argumentNumber * (sizeof(JSValue) / sizeof(void*))) + 1;
 
592
    poke(payload, argumentStackOffset);
 
593
    poke(tag, argumentStackOffset + 1);
 
594
}
 
595
 
 
596
/* Deprecated: Please use JITStubCall instead. */
 
597
 
 
598
ALWAYS_INLINE void JIT::emitPutJITStubArgFromVirtualRegister(unsigned src, unsigned argumentNumber, RegisterID scratch1, RegisterID scratch2)
 
599
{
 
600
    unsigned argumentStackOffset = (argumentNumber * (sizeof(JSValue) / sizeof(void*))) + 1;
 
601
    if (m_codeBlock->isConstantRegisterIndex(src)) {
 
602
        JSValue constant = m_codeBlock->getConstant(src);
 
603
        poke(Imm32(constant.payload()), argumentStackOffset);
 
604
        poke(Imm32(constant.tag()), argumentStackOffset + 1);
 
605
    } else {
 
606
        emitLoad(src, scratch1, scratch2);
 
607
        poke(scratch2, argumentStackOffset);
 
608
        poke(scratch1, argumentStackOffset + 1);
 
609
    }
 
610
}
 
611
 
 
612
#else // USE(JSVALUE32_64)
 
613
 
44
614
ALWAYS_INLINE void JIT::killLastResultRegister()
45
615
{
46
616
    m_lastResultBytecodeRegister = std::numeric_limits<int>::max();
53
623
 
54
624
    // TODO: we want to reuse values that are already in registers if we can - add a register allocator!
55
625
    if (m_codeBlock->isConstantRegisterIndex(src)) {
56
 
        JSValuePtr value = m_codeBlock->getConstant(src);
57
 
        move(ImmPtr(JSValuePtr::encode(value)), dst);
 
626
        JSValue value = m_codeBlock->getConstant(src);
 
627
        move(ImmPtr(JSValue::encode(value)), dst);
58
628
        killLastResultRegister();
59
629
        return;
60
630
    }
69
639
 
70
640
        if (!atJumpTarget) {
71
641
            // The argument we want is already stored in eax
72
 
            if (dst != X86::eax)
73
 
                move(X86::eax, dst);
 
642
            if (dst != cachedResultRegister)
 
643
                move(cachedResultRegister, dst);
74
644
            killLastResultRegister();
75
645
            return;
76
646
        }
91
661
    }
92
662
}
93
663
 
94
 
// puts an arg onto the stack, as an arg to a context threaded function.
95
 
ALWAYS_INLINE void JIT::emitPutJITStubArg(RegisterID src, unsigned argumentNumber)
96
 
{
97
 
    poke(src, argumentNumber);
98
 
}
99
 
 
100
 
ALWAYS_INLINE void JIT::emitPutJITStubArgConstant(unsigned value, unsigned argumentNumber)
101
 
{
102
 
    poke(Imm32(value), argumentNumber);
103
 
}
104
 
 
105
 
ALWAYS_INLINE void JIT::emitPutJITStubArgConstant(void* value, unsigned argumentNumber)
106
 
{
107
 
    poke(ImmPtr(value), argumentNumber);
108
 
}
109
 
 
110
 
ALWAYS_INLINE void JIT::emitGetJITStubArg(unsigned argumentNumber, RegisterID dst)
111
 
{
112
 
    peek(dst, argumentNumber);
113
 
}
114
 
 
115
 
ALWAYS_INLINE JSValuePtr JIT::getConstantOperand(unsigned src)
116
 
{
117
 
    ASSERT(m_codeBlock->isConstantRegisterIndex(src));
118
 
    return m_codeBlock->getConstant(src);
119
 
}
120
 
 
121
664
ALWAYS_INLINE int32_t JIT::getConstantOperandImmediateInt(unsigned src)
122
665
{
123
 
    return static_cast<int32_t>(JSImmediate::intValue(getConstantOperand(src)));
 
666
    return getConstantOperand(src).asInt32();
124
667
}
125
668
 
126
669
ALWAYS_INLINE bool JIT::isOperandConstantImmediateInt(unsigned src)
127
670
{
128
 
    return m_codeBlock->isConstantRegisterIndex(src) && JSImmediate::isNumber(getConstantOperand(src));
129
 
}
130
 
 
131
 
// get arg puts an arg from the SF register array onto the stack, as an arg to a context threaded function.
132
 
ALWAYS_INLINE void JIT::emitPutJITStubArgFromVirtualRegister(unsigned src, unsigned argumentNumber, RegisterID scratch)
133
 
{
134
 
    if (m_codeBlock->isConstantRegisterIndex(src)) {
135
 
        JSValuePtr value = m_codeBlock->getConstant(src);
136
 
        emitPutJITStubArgConstant(JSValuePtr::encode(value), argumentNumber);
137
 
    } else {
138
 
        loadPtr(Address(callFrameRegister, src * sizeof(Register)), scratch);
139
 
        emitPutJITStubArg(scratch, argumentNumber);
140
 
    }
141
 
 
142
 
    killLastResultRegister();
143
 
}
144
 
 
145
 
ALWAYS_INLINE void JIT::emitPutCTIParam(void* value, unsigned name)
146
 
{
147
 
    poke(ImmPtr(value), name);
148
 
}
149
 
 
150
 
ALWAYS_INLINE void JIT::emitPutCTIParam(RegisterID from, unsigned name)
151
 
{
152
 
    poke(from, name);
153
 
}
154
 
 
155
 
ALWAYS_INLINE void JIT::emitGetCTIParam(unsigned name, RegisterID to)
156
 
{
157
 
    peek(to, name);
158
 
    killLastResultRegister();
159
 
}
160
 
 
161
 
ALWAYS_INLINE void JIT::emitPutToCallFrameHeader(RegisterID from, RegisterFile::CallFrameHeaderEntry entry)
162
 
{
163
 
    storePtr(from, Address(callFrameRegister, entry * sizeof(Register)));
164
 
}
165
 
 
166
 
ALWAYS_INLINE void JIT::emitPutImmediateToCallFrameHeader(void* value, RegisterFile::CallFrameHeaderEntry entry)
167
 
{
168
 
    storePtr(ImmPtr(value), Address(callFrameRegister, entry * sizeof(Register)));
169
 
}
170
 
 
171
 
ALWAYS_INLINE void JIT::emitGetFromCallFrameHeader(RegisterFile::CallFrameHeaderEntry entry, RegisterID to)
172
 
{
173
 
    loadPtr(Address(callFrameRegister, entry * sizeof(Register)), to);
174
 
    killLastResultRegister();
 
671
    return m_codeBlock->isConstantRegisterIndex(src) && getConstantOperand(src).isInt32();
175
672
}
176
673
 
177
674
ALWAYS_INLINE void JIT::emitPutVirtualRegister(unsigned dst, RegisterID from)
178
675
{
179
676
    storePtr(from, Address(callFrameRegister, dst * sizeof(Register)));
180
 
    m_lastResultBytecodeRegister = (from == X86::eax) ? dst : std::numeric_limits<int>::max();
181
 
    // FIXME: #ifndef NDEBUG, Write the correct m_type to the register.
 
677
    m_lastResultBytecodeRegister = (from == cachedResultRegister) ? dst : std::numeric_limits<int>::max();
182
678
}
183
679
 
184
680
ALWAYS_INLINE void JIT::emitInitRegister(unsigned dst)
185
681
{
186
 
    storePtr(ImmPtr(JSValuePtr::encode(jsUndefined())), Address(callFrameRegister, dst * sizeof(Register)));
187
 
    // FIXME: #ifndef NDEBUG, Write the correct m_type to the register.
188
 
}
189
 
 
190
 
ALWAYS_INLINE JIT::Jump JIT::emitNakedCall(X86::RegisterID r)
191
 
{
192
 
    ASSERT(m_bytecodeIndex != (unsigned)-1); // This method should only be called during hot/cold path generation, so that m_bytecodeIndex is set.
193
 
 
194
 
    Jump nakedCall = call(r);
195
 
    m_calls.append(CallRecord(nakedCall, m_bytecodeIndex));
196
 
    return nakedCall;
197
 
}
198
 
 
199
 
ALWAYS_INLINE JIT::Jump JIT::emitNakedCall(void* function)
200
 
{
201
 
    ASSERT(m_bytecodeIndex != (unsigned)-1); // This method should only be called during hot/cold path generation, so that m_bytecodeIndex is set.
202
 
 
203
 
    Jump nakedCall = call();
204
 
    m_calls.append(CallRecord(nakedCall, m_bytecodeIndex, function));
205
 
    return nakedCall;
206
 
}
207
 
 
208
 
#if USE(JIT_STUB_ARGUMENT_REGISTER)
209
 
ALWAYS_INLINE void JIT::restoreArgumentReference()
210
 
{
211
 
#if PLATFORM(X86_64)
212
 
    move(X86::esp, X86::edi);
213
 
#else
214
 
    move(X86::esp, X86::ecx);
215
 
#endif
216
 
    emitPutCTIParam(callFrameRegister, STUB_ARGS_callFrame);
217
 
}
218
 
ALWAYS_INLINE void JIT::restoreArgumentReferenceForTrampoline()
219
 
{
220
 
    // In the trampoline on x86-64, the first argument register is not overwritten.
221
 
#if !PLATFORM(X86_64)
222
 
    move(X86::esp, X86::ecx);
223
 
    addPtr(Imm32(sizeof(void*)), X86::ecx);
224
 
#endif
225
 
}
226
 
#elif USE(JIT_STUB_ARGUMENT_STACK)
227
 
ALWAYS_INLINE void JIT::restoreArgumentReference()
228
 
{
229
 
    storePtr(X86::esp, X86::esp);
230
 
    emitPutCTIParam(callFrameRegister, STUB_ARGS_callFrame);
231
 
}
232
 
ALWAYS_INLINE void JIT::restoreArgumentReferenceForTrampoline() {}
233
 
#else // JIT_STUB_ARGUMENT_VA_LIST
234
 
ALWAYS_INLINE void JIT::restoreArgumentReference()
235
 
{
236
 
    emitPutCTIParam(callFrameRegister, STUB_ARGS_callFrame);
237
 
}
238
 
ALWAYS_INLINE void JIT::restoreArgumentReferenceForTrampoline() {}
239
 
#endif
240
 
 
241
 
ALWAYS_INLINE JIT::Jump JIT::emitCTICall_internal(void* helper)
242
 
{
243
 
    ASSERT(m_bytecodeIndex != (unsigned)-1); // This method should only be called during hot/cold path generation, so that m_bytecodeIndex is set.
244
 
 
245
 
#if ENABLE(OPCODE_SAMPLING)
246
 
    store32(Imm32(m_interpreter->sampler()->encodeSample(m_codeBlock->instructions().begin() + m_bytecodeIndex, true)), m_interpreter->sampler()->sampleSlot());
247
 
#endif
248
 
    restoreArgumentReference();
249
 
    Jump ctiCall = call();
250
 
    m_calls.append(CallRecord(ctiCall, m_bytecodeIndex, helper));
251
 
#if ENABLE(OPCODE_SAMPLING)
252
 
    store32(Imm32(m_interpreter->sampler()->encodeSample(m_codeBlock->instructions().begin() + m_bytecodeIndex, false)), m_interpreter->sampler()->sampleSlot());
253
 
#endif
254
 
    killLastResultRegister();
255
 
 
256
 
    return ctiCall;
257
 
}
258
 
 
259
 
ALWAYS_INLINE JIT::Jump JIT::checkStructure(RegisterID reg, Structure* structure)
260
 
{
261
 
    return jnePtr(Address(reg, FIELD_OFFSET(JSCell, m_structure)), ImmPtr(structure));
 
682
    storePtr(ImmPtr(JSValue::encode(jsUndefined())), Address(callFrameRegister, dst * sizeof(Register)));
262
683
}
263
684
 
264
685
ALWAYS_INLINE JIT::Jump JIT::emitJumpIfJSCell(RegisterID reg)
265
686
{
266
 
#if USE(ALTERNATE_JSIMMEDIATE)
267
 
    return jzPtr(reg, ImmPtr(reinterpret_cast<void*>(JSImmediate::TagMask)));
 
687
#if USE(JSVALUE64)
 
688
    return branchTestPtr(Zero, reg, tagMaskRegister);
268
689
#else
269
 
    return jz32(reg, Imm32(JSImmediate::TagMask));
 
690
    return branchTest32(Zero, reg, Imm32(JSImmediate::TagMask));
270
691
#endif
271
692
}
272
693
 
 
694
ALWAYS_INLINE JIT::Jump JIT::emitJumpIfBothJSCells(RegisterID reg1, RegisterID reg2, RegisterID scratch)
 
695
{
 
696
    move(reg1, scratch);
 
697
    orPtr(reg2, scratch);
 
698
    return emitJumpIfJSCell(scratch);
 
699
}
 
700
 
273
701
ALWAYS_INLINE void JIT::emitJumpSlowCaseIfJSCell(RegisterID reg)
274
702
{
275
703
    addSlowCase(emitJumpIfJSCell(reg));
277
705
 
278
706
ALWAYS_INLINE JIT::Jump JIT::emitJumpIfNotJSCell(RegisterID reg)
279
707
{
280
 
#if USE(ALTERNATE_JSIMMEDIATE)
281
 
    return jnzPtr(reg, ImmPtr(reinterpret_cast<void*>(JSImmediate::TagMask)));
 
708
#if USE(JSVALUE64)
 
709
    return branchTestPtr(NonZero, reg, tagMaskRegister);
282
710
#else
283
 
    return jnz32(reg, Imm32(JSImmediate::TagMask));
 
711
    return branchTest32(NonZero, reg, Imm32(JSImmediate::TagMask));
284
712
#endif
285
713
}
286
714
 
295
723
        emitJumpSlowCaseIfNotJSCell(reg);
296
724
}
297
725
 
298
 
ALWAYS_INLINE void JIT::linkSlowCaseIfNotJSCell(Vector<SlowCaseEntry>::iterator& iter, int vReg)
299
 
{
300
 
    if (!m_codeBlock->isKnownNotImmediate(vReg))
301
 
        linkSlowCase(iter);
302
 
}
303
 
 
304
 
ALWAYS_INLINE JIT::Jump JIT::emitJumpIfImmNum(RegisterID reg)
305
 
{
306
 
#if USE(ALTERNATE_JSIMMEDIATE)
307
 
    return jaePtr(reg, ImmPtr(reinterpret_cast<void*>(JSImmediate::TagTypeInteger)));
308
 
#else
309
 
    return jnz32(reg, Imm32(JSImmediate::TagTypeInteger));
310
 
#endif
311
 
}
312
 
 
313
 
ALWAYS_INLINE void JIT::emitJumpSlowCaseIfNotImmNum(RegisterID reg)
314
 
{
315
 
#if USE(ALTERNATE_JSIMMEDIATE)
316
 
    addSlowCase(jbPtr(reg, ImmPtr(reinterpret_cast<void*>(JSImmediate::TagTypeInteger))));
317
 
#else
318
 
    addSlowCase(jz32(reg, Imm32(JSImmediate::TagTypeInteger)));
319
 
#endif
320
 
}
321
 
 
322
 
ALWAYS_INLINE void JIT::emitJumpSlowCaseIfNotImmNums(RegisterID reg1, RegisterID reg2, RegisterID scratch)
 
726
#if USE(JSVALUE64)
 
727
ALWAYS_INLINE JIT::Jump JIT::emitJumpIfImmediateNumber(RegisterID reg)
 
728
{
 
729
    return branchTestPtr(NonZero, reg, tagTypeNumberRegister);
 
730
}
 
731
ALWAYS_INLINE JIT::Jump JIT::emitJumpIfNotImmediateNumber(RegisterID reg)
 
732
{
 
733
    return branchTestPtr(Zero, reg, tagTypeNumberRegister);
 
734
}
 
735
 
 
736
inline void JIT::emitLoadDouble(unsigned index, FPRegisterID value)
 
737
{
 
738
    if (m_codeBlock->isConstantRegisterIndex(index)) {
 
739
        Register& inConstantPool = m_codeBlock->constantRegister(index);
 
740
        loadDouble(&inConstantPool, value);
 
741
    } else
 
742
        loadDouble(addressFor(index), value);
 
743
}
 
744
 
 
745
inline void JIT::emitLoadInt32ToDouble(unsigned index, FPRegisterID value)
 
746
{
 
747
    if (m_codeBlock->isConstantRegisterIndex(index)) {
 
748
        Register& inConstantPool = m_codeBlock->constantRegister(index);
 
749
        convertInt32ToDouble(AbsoluteAddress(&inConstantPool), value);
 
750
    } else
 
751
        convertInt32ToDouble(addressFor(index), value);
 
752
}
 
753
#endif
 
754
 
 
755
ALWAYS_INLINE JIT::Jump JIT::emitJumpIfImmediateInteger(RegisterID reg)
 
756
{
 
757
#if USE(JSVALUE64)
 
758
    return branchPtr(AboveOrEqual, reg, tagTypeNumberRegister);
 
759
#else
 
760
    return branchTest32(NonZero, reg, Imm32(JSImmediate::TagTypeNumber));
 
761
#endif
 
762
}
 
763
 
 
764
ALWAYS_INLINE JIT::Jump JIT::emitJumpIfNotImmediateInteger(RegisterID reg)
 
765
{
 
766
#if USE(JSVALUE64)
 
767
    return branchPtr(Below, reg, tagTypeNumberRegister);
 
768
#else
 
769
    return branchTest32(Zero, reg, Imm32(JSImmediate::TagTypeNumber));
 
770
#endif
 
771
}
 
772
 
 
773
ALWAYS_INLINE JIT::Jump JIT::emitJumpIfNotImmediateIntegers(RegisterID reg1, RegisterID reg2, RegisterID scratch)
323
774
{
324
775
    move(reg1, scratch);
325
776
    andPtr(reg2, scratch);
326
 
    emitJumpSlowCaseIfNotImmNum(scratch);
327
 
}
328
 
 
329
 
#if !USE(ALTERNATE_JSIMMEDIATE)
 
777
    return emitJumpIfNotImmediateInteger(scratch);
 
778
}
 
779
 
 
780
ALWAYS_INLINE void JIT::emitJumpSlowCaseIfNotImmediateInteger(RegisterID reg)
 
781
{
 
782
    addSlowCase(emitJumpIfNotImmediateInteger(reg));
 
783
}
 
784
 
 
785
ALWAYS_INLINE void JIT::emitJumpSlowCaseIfNotImmediateIntegers(RegisterID reg1, RegisterID reg2, RegisterID scratch)
 
786
{
 
787
    addSlowCase(emitJumpIfNotImmediateIntegers(reg1, reg2, scratch));
 
788
}
 
789
 
 
790
ALWAYS_INLINE void JIT::emitJumpSlowCaseIfNotImmediateNumber(RegisterID reg)
 
791
{
 
792
    addSlowCase(emitJumpIfNotImmediateNumber(reg));
 
793
}
 
794
 
 
795
#if !USE(JSVALUE64)
330
796
ALWAYS_INLINE void JIT::emitFastArithDeTagImmediate(RegisterID reg)
331
797
{
332
 
    subPtr(Imm32(JSImmediate::TagTypeInteger), reg);
 
798
    subPtr(Imm32(JSImmediate::TagTypeNumber), reg);
333
799
}
334
800
 
335
801
ALWAYS_INLINE JIT::Jump JIT::emitFastArithDeTagImmediateJumpIfZero(RegisterID reg)
336
802
{
337
 
    return jzSubPtr(Imm32(JSImmediate::TagTypeInteger), reg);
 
803
    return branchSubPtr(Zero, Imm32(JSImmediate::TagTypeNumber), reg);
338
804
}
339
805
#endif
340
806
 
341
807
ALWAYS_INLINE void JIT::emitFastArithReTagImmediate(RegisterID src, RegisterID dest)
342
808
{
343
 
#if USE(ALTERNATE_JSIMMEDIATE)
 
809
#if USE(JSVALUE64)
344
810
    emitFastArithIntToImmNoCheck(src, dest);
345
811
#else
346
812
    if (src != dest)
347
813
        move(src, dest);
348
 
    addPtr(Imm32(JSImmediate::TagTypeInteger), dest);
 
814
    addPtr(Imm32(JSImmediate::TagTypeNumber), dest);
349
815
#endif
350
816
}
351
817
 
352
818
ALWAYS_INLINE void JIT::emitFastArithImmToInt(RegisterID reg)
353
819
{
354
 
#if USE(ALTERNATE_JSIMMEDIATE)
 
820
#if USE(JSVALUE64)
355
821
    UNUSED_PARAM(reg);
356
822
#else
357
823
    rshiftPtr(Imm32(JSImmediate::IntegerPayloadShift), reg);
361
827
// operand is int32_t, must have been zero-extended if register is 64-bit.
362
828
ALWAYS_INLINE void JIT::emitFastArithIntToImmNoCheck(RegisterID src, RegisterID dest)
363
829
{
364
 
#if USE(ALTERNATE_JSIMMEDIATE)
 
830
#if USE(JSVALUE64)
365
831
    if (src != dest)
366
832
        move(src, dest);
367
 
    orPtr(ImmPtr(reinterpret_cast<void*>(JSImmediate::TagTypeInteger)), dest);
 
833
    orPtr(tagTypeNumberRegister, dest);
368
834
#else
369
835
    signExtend32ToPtr(src, dest);
370
836
    addPtr(dest, dest);
378
844
    or32(Imm32(static_cast<int32_t>(JSImmediate::FullTagTypeBool)), reg);
379
845
}
380
846
 
381
 
ALWAYS_INLINE void JIT::addSlowCase(Jump jump)
382
 
{
383
 
    ASSERT(m_bytecodeIndex != (unsigned)-1); // This method should only be called during hot/cold path generation, so that m_bytecodeIndex is set.
384
 
 
385
 
    m_slowCases.append(SlowCaseEntry(jump, m_bytecodeIndex));
386
 
}
387
 
 
388
 
ALWAYS_INLINE void JIT::addJump(Jump jump, int relativeOffset)
389
 
{
390
 
    ASSERT(m_bytecodeIndex != (unsigned)-1); // This method should only be called during hot/cold path generation, so that m_bytecodeIndex is set.
391
 
 
392
 
    m_jmpTable.append(JumpTable(jump, m_bytecodeIndex + relativeOffset));
393
 
}
394
 
 
395
 
ALWAYS_INLINE void JIT::emitJumpSlowToHot(Jump jump, int relativeOffset)
396
 
{
397
 
    ASSERT(m_bytecodeIndex != (unsigned)-1); // This method should only be called during hot/cold path generation, so that m_bytecodeIndex is set.
398
 
 
399
 
    jump.linkTo(m_labels[m_bytecodeIndex + relativeOffset], this);
400
 
}
401
 
 
402
 
}
 
847
/* Deprecated: Please use JITStubCall instead. */
 
848
 
 
849
// get arg puts an arg from the SF register array onto the stack, as an arg to a context threaded function.
 
850
ALWAYS_INLINE void JIT::emitPutJITStubArgFromVirtualRegister(unsigned src, unsigned argumentNumber, RegisterID scratch)
 
851
{
 
852
    unsigned argumentStackOffset = (argumentNumber * (sizeof(JSValue) / sizeof(void*))) + 1;
 
853
    if (m_codeBlock->isConstantRegisterIndex(src)) {
 
854
        JSValue value = m_codeBlock->getConstant(src);
 
855
        poke(ImmPtr(JSValue::encode(value)), argumentStackOffset);
 
856
    } else {
 
857
        loadPtr(Address(callFrameRegister, src * sizeof(Register)), scratch);
 
858
        poke(scratch, argumentStackOffset);
 
859
    }
 
860
 
 
861
    killLastResultRegister();
 
862
}
 
863
 
 
864
#endif // USE(JSVALUE32_64)
 
865
 
 
866
} // namespace JSC
403
867
 
404
868
#endif // ENABLE(JIT)
405
869