]> git.saurik.com Git - apple/javascriptcore.git/blame - jit/JITInlines.h
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / jit / JITInlines.h
CommitLineData
9dae56ea 1/*
ed1e77d3 2 * Copyright (C) 2008, 2012, 2013, 2015 Apple Inc. All rights reserved.
9dae56ea
A
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
93a37866
A
26#ifndef JITInlines_h
27#define JITInlines_h
9dae56ea 28
9dae56ea
A
29#if ENABLE(JIT)
30
81345200
A
31#include "JSCInlines.h"
32
ba379fdc
A
33namespace JSC {
34
ed1e77d3
A
35#if USE(JSVALUE64)
36inline MacroAssembler::JumpList JIT::emitDoubleGetByVal(Instruction* instruction, PatchableJump& badType)
37{
38 JumpList slowCases = emitDoubleLoad(instruction, badType);
39 moveDoubleTo64(fpRegT0, regT0);
40 sub64(tagTypeNumberRegister, regT0);
41 return slowCases;
42}
43#else
44inline MacroAssembler::JumpList JIT::emitDoubleGetByVal(Instruction* instruction, PatchableJump& badType)
45{
46 JumpList slowCases = emitDoubleLoad(instruction, badType);
47 moveDoubleToInts(fpRegT0, regT0, regT1);
48 return slowCases;
49}
50#endif // USE(JSVALUE64)
51
52ALWAYS_INLINE MacroAssembler::JumpList JIT::emitLoadForArrayMode(Instruction* currentInstruction, JITArrayMode arrayMode, PatchableJump& badType)
53{
54 switch (arrayMode) {
55 case JITInt32:
56 return emitInt32Load(currentInstruction, badType);
57 case JITDouble:
58 return emitDoubleLoad(currentInstruction, badType);
59 case JITContiguous:
60 return emitContiguousLoad(currentInstruction, badType);
61 case JITArrayStorage:
62 return emitArrayStorageLoad(currentInstruction, badType);
63 default:
64 break;
65 }
66 RELEASE_ASSERT_NOT_REACHED();
67 return MacroAssembler::JumpList();
68}
69
70inline MacroAssembler::JumpList JIT::emitContiguousGetByVal(Instruction* instruction, PatchableJump& badType, IndexingType expectedShape)
71{
72 return emitContiguousLoad(instruction, badType, expectedShape);
73}
74
75inline MacroAssembler::JumpList JIT::emitArrayStorageGetByVal(Instruction* instruction, PatchableJump& badType)
76{
77 return emitArrayStorageLoad(instruction, badType);
78}
79
81345200 80ALWAYS_INLINE bool JIT::isOperandConstantImmediateDouble(int src)
f9bf01c6
A
81{
82 return m_codeBlock->isConstantRegisterIndex(src) && getConstantOperand(src).isDouble();
ba379fdc
A
83}
84
81345200 85ALWAYS_INLINE JSValue JIT::getConstantOperand(int src)
ba379fdc
A
86{
87 ASSERT(m_codeBlock->isConstantRegisterIndex(src));
88 return m_codeBlock->getConstant(src);
89}
90
93a37866 91ALWAYS_INLINE void JIT::emitPutIntToCallFrameHeader(RegisterID from, JSStack::CallFrameHeaderEntry entry)
14957cd0
A
92{
93#if USE(JSVALUE32_64)
14957cd0
A
94 store32(TrustedImm32(Int32Tag), intTagFor(entry, callFrameRegister));
95 store32(from, intPayloadFor(entry, callFrameRegister));
93a37866
A
96#else
97 store64(from, addressFor(entry, callFrameRegister));
98#endif
ba379fdc
A
99}
100
4e4e5a6f
A
101ALWAYS_INLINE void JIT::emitLoadCharacterString(RegisterID src, RegisterID dst, JumpList& failures)
102{
81345200 103 failures.append(branchStructure(NotEqual, Address(src, JSCell::structureIDOffset()), m_vm->stringStructure.get()));
14957cd0 104 failures.append(branch32(NotEqual, MacroAssembler::Address(src, ThunkHelpers::jsStringLengthOffset()), TrustedImm32(1)));
4e4e5a6f 105 loadPtr(MacroAssembler::Address(src, ThunkHelpers::jsStringValueOffset()), dst);
6fe7ccc8 106 failures.append(branchTest32(Zero, dst));
93a37866
A
107 loadPtr(MacroAssembler::Address(dst, StringImpl::flagsOffset()), regT1);
108 loadPtr(MacroAssembler::Address(dst, StringImpl::dataOffset()), dst);
6fe7ccc8
A
109
110 JumpList is16Bit;
111 JumpList cont8Bit;
93a37866 112 is16Bit.append(branchTest32(Zero, regT1, TrustedImm32(StringImpl::flagIs8Bit())));
6fe7ccc8
A
113 load8(MacroAssembler::Address(dst, 0), dst);
114 cont8Bit.append(jump());
115 is16Bit.link(this);
4e4e5a6f 116 load16(MacroAssembler::Address(dst, 0), dst);
6fe7ccc8 117 cont8Bit.link(this);
4e4e5a6f
A
118}
119
ba379fdc
A
120ALWAYS_INLINE JIT::Call JIT::emitNakedCall(CodePtr function)
121{
ed1e77d3 122 ASSERT(m_bytecodeOffset != std::numeric_limits<unsigned>::max()); // This method should only be called during hot/cold path generation, so that m_bytecodeOffset is set.
ba379fdc 123 Call nakedCall = nearCall();
14957cd0 124 m_calls.append(CallRecord(nakedCall, m_bytecodeOffset, function.executableAddress()));
ba379fdc
A
125 return nakedCall;
126}
127
81345200 128ALWAYS_INLINE void JIT::updateTopCallFrame()
14957cd0 129{
81345200
A
130 ASSERT(static_cast<int>(m_bytecodeOffset) >= 0);
131#if USE(JSVALUE32_64)
132 Instruction* instruction = m_codeBlock->instructions().begin() + m_bytecodeOffset + 1;
133 uint32_t locationBits = CallFrame::Location::encodeAsBytecodeInstruction(instruction);
134#else
135 uint32_t locationBits = CallFrame::Location::encodeAsBytecodeOffset(m_bytecodeOffset + 1);
136#endif
137 store32(TrustedImm32(locationBits), intTagFor(JSStack::ArgumentCount));
138 storePtr(callFrameRegister, &m_vm->topCallFrame);
14957cd0
A
139}
140
81345200
A
141ALWAYS_INLINE MacroAssembler::Call JIT::appendCallWithExceptionCheck(const FunctionPtr& function)
142{
143 updateTopCallFrame();
144 MacroAssembler::Call call = appendCall(function);
145 exceptionCheck();
146 return call;
147}
f9bf01c6 148
81345200
A
149#if OS(WINDOWS) && CPU(X86_64)
150ALWAYS_INLINE MacroAssembler::Call JIT::appendCallWithExceptionCheckAndSlowPathReturnType(const FunctionPtr& function)
f9bf01c6 151{
81345200
A
152 updateTopCallFrame();
153 MacroAssembler::Call call = appendCallWithSlowPathReturnType(function);
154 exceptionCheck();
155 return call;
156}
f9bf01c6
A
157#endif
158
81345200
A
159ALWAYS_INLINE MacroAssembler::Call JIT::appendCallWithCallFrameRollbackOnException(const FunctionPtr& function)
160{
161 updateTopCallFrame(); // The callee is responsible for setting topCallFrame to their caller
162 MacroAssembler::Call call = appendCall(function);
163 exceptionCheckWithCallFrameRollback();
164 return call;
165}
f9bf01c6 166
81345200
A
167ALWAYS_INLINE MacroAssembler::Call JIT::appendCallWithExceptionCheckSetJSValueResult(const FunctionPtr& function, int dst)
168{
169 MacroAssembler::Call call = appendCallWithExceptionCheck(function);
170#if USE(JSVALUE64)
171 emitPutVirtualRegister(dst, returnValueGPR);
172#else
173 emitStore(dst, returnValueGPR2, returnValueGPR);
14957cd0 174#endif
81345200
A
175 return call;
176}
14957cd0 177
81345200
A
178ALWAYS_INLINE MacroAssembler::Call JIT::appendCallWithExceptionCheckSetJSValueResultWithProfile(const FunctionPtr& function, int dst)
179{
180 MacroAssembler::Call call = appendCallWithExceptionCheck(function);
181 emitValueProfilingSite();
182#if USE(JSVALUE64)
183 emitPutVirtualRegister(dst, returnValueGPR);
184#else
185 emitStore(dst, returnValueGPR2, returnValueGPR);
f9bf01c6 186#endif
81345200
A
187 return call;
188}
189
190ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(C_JITOperation_E operation)
191{
192 setupArgumentsExecState();
193 return appendCallWithExceptionCheck(operation);
194}
195
ed1e77d3
A
196ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(C_JITOperation_EJsc operation, GPRReg arg1)
197{
198 setupArgumentsWithExecState(arg1);
199 return appendCallWithExceptionCheck(operation);
200}
201
202ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(C_JITOperation_EJscZ operation, GPRReg arg1, int32_t arg2)
203{
204 setupArgumentsWithExecState(arg1, TrustedImm32(arg2));
205 return appendCallWithExceptionCheck(operation);
206}
207
208ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(C_JITOperation_EL operation, GPRReg arg1)
209{
210 setupArgumentsWithExecState(arg1);
211 return appendCallWithExceptionCheck(operation);
212}
213
214ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(C_JITOperation_EL operation, TrustedImmPtr arg1)
215{
216 setupArgumentsWithExecState(arg1);
217 return appendCallWithExceptionCheck(operation);
218}
219
81345200
A
220ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(C_JITOperation_EO operation, GPRReg arg)
221{
222 setupArgumentsWithExecState(arg);
223 return appendCallWithExceptionCheck(operation);
224}
225
226ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(C_JITOperation_ESt operation, Structure* structure)
227{
228 setupArgumentsWithExecState(TrustedImmPtr(structure));
229 return appendCallWithExceptionCheck(operation);
230}
231
232ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(C_JITOperation_EZ operation, int32_t arg)
233{
234 setupArgumentsWithExecState(TrustedImm32(arg));
235 return appendCallWithExceptionCheck(operation);
236}
f9bf01c6 237
81345200
A
238ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(J_JITOperation_E operation, int dst)
239{
240 setupArgumentsExecState();
241 return appendCallWithExceptionCheckSetJSValueResult(operation, dst);
242}
243
244ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(J_JITOperation_EAapJcpZ operation, int dst, ArrayAllocationProfile* arg1, GPRReg arg2, int32_t arg3)
245{
246 setupArgumentsWithExecState(TrustedImmPtr(arg1), arg2, TrustedImm32(arg3));
247 return appendCallWithExceptionCheckSetJSValueResult(operation, dst);
248}
249
250ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(J_JITOperation_EAapJcpZ operation, int dst, ArrayAllocationProfile* arg1, const JSValue* arg2, int32_t arg3)
251{
252 setupArgumentsWithExecState(TrustedImmPtr(arg1), TrustedImmPtr(arg2), TrustedImm32(arg3));
253 return appendCallWithExceptionCheckSetJSValueResult(operation, dst);
254}
255
256ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(J_JITOperation_EC operation, int dst, JSCell* cell)
257{
258 setupArgumentsWithExecState(TrustedImmPtr(cell));
259 return appendCallWithExceptionCheckSetJSValueResult(operation, dst);
260}
261
262ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_EC operation, JSCell* cell)
263{
264 setupArgumentsWithExecState(TrustedImmPtr(cell));
265 return appendCallWithExceptionCheck(operation);
266}
267
ed1e77d3
A
268ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(J_JITOperation_EJscC operation, int dst, GPRReg arg1, JSCell* cell)
269{
270 setupArgumentsWithExecState(arg1, TrustedImmPtr(cell));
271 return appendCallWithExceptionCheckSetJSValueResult(operation, dst);
272}
273
81345200
A
274ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(J_JITOperation_EP operation, int dst, void* pointer)
275{
276 setupArgumentsWithExecState(TrustedImmPtr(pointer));
277 return appendCallWithExceptionCheckSetJSValueResult(operation, dst);
278}
279
280ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(WithProfileTag, J_JITOperation_EPc operation, int dst, Instruction* bytecodePC)
281{
282 setupArgumentsWithExecState(TrustedImmPtr(bytecodePC));
283 return appendCallWithExceptionCheckSetJSValueResultWithProfile(operation, dst);
284}
285
286ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(J_JITOperation_EZ operation, int dst, int32_t arg)
287{
288 setupArgumentsWithExecState(TrustedImm32(arg));
289 return appendCallWithExceptionCheckSetJSValueResult(operation, dst);
290}
291
ed1e77d3
A
292ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(J_JITOperation_EZZ operation, int dst, int32_t arg1, int32_t arg2)
293{
294 setupArgumentsWithExecState(TrustedImm32(arg1), TrustedImm32(arg2));
295 return appendCallWithExceptionCheckSetJSValueResult(operation, dst);
296}
297
81345200
A
298ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(S_JITOperation_ECC operation, RegisterID regOp1, RegisterID regOp2)
299{
300 setupArgumentsWithExecState(regOp1, regOp2);
301 return appendCallWithExceptionCheck(operation);
302}
303
304ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(S_JITOperation_EOJss operation, RegisterID regOp1, RegisterID regOp2)
305{
306 setupArgumentsWithExecState(regOp1, regOp2);
307 return appendCallWithExceptionCheck(operation);
308}
309
310ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(Sprt_JITOperation_EZ operation, int32_t op)
311{
312#if OS(WINDOWS) && CPU(X86_64)
313 setupArgumentsWithExecStateForCallWithSlowPathReturnType(TrustedImm32(op));
314 return appendCallWithExceptionCheckAndSlowPathReturnType(operation);
315#else
316 setupArgumentsWithExecState(TrustedImm32(op));
317 return appendCallWithExceptionCheck(operation);
f9bf01c6 318#endif
f9bf01c6
A
319}
320
81345200 321ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_E operation)
f9bf01c6 322{
81345200
A
323 setupArgumentsExecState();
324 return appendCallWithExceptionCheck(operation);
325}
93a37866 326
81345200
A
327ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_EC operation, RegisterID regOp)
328{
329 setupArgumentsWithExecState(regOp);
330 return appendCallWithExceptionCheck(operation);
331}
332
333ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_ECC operation, RegisterID regOp1, RegisterID regOp2)
334{
335 setupArgumentsWithExecState(regOp1, regOp2);
336 return appendCallWithExceptionCheck(operation);
337}
338
ed1e77d3
A
339ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(J_JITOperation_EE operation, RegisterID regOp)
340{
341 setupArgumentsWithExecState(regOp);
342 updateTopCallFrame();
343 return appendCallWithExceptionCheck(operation);
344}
345
81345200
A
346ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_EPc operation, Instruction* bytecodePC)
347{
348 setupArgumentsWithExecState(TrustedImmPtr(bytecodePC));
349 return appendCallWithExceptionCheck(operation);
350}
351
352ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_EZ operation, int32_t op)
353{
354 setupArgumentsWithExecState(TrustedImm32(op));
355 return appendCallWithExceptionCheck(operation);
356}
357
358ALWAYS_INLINE MacroAssembler::Call JIT::callOperationWithCallFrameRollbackOnException(J_JITOperation_E operation)
359{
360 setupArgumentsExecState();
361 return appendCallWithCallFrameRollbackOnException(operation);
362}
363
81345200
A
364ALWAYS_INLINE MacroAssembler::Call JIT::callOperationWithCallFrameRollbackOnException(V_JITOperation_ECb operation, CodeBlock* pointer)
365{
366 setupArgumentsWithExecState(TrustedImmPtr(pointer));
367 return appendCallWithCallFrameRollbackOnException(operation);
368}
369
370ALWAYS_INLINE MacroAssembler::Call JIT::callOperationWithCallFrameRollbackOnException(Z_JITOperation_E operation)
371{
372 setupArgumentsExecState();
373 return appendCallWithCallFrameRollbackOnException(operation);
374}
375
376
377#if USE(JSVALUE64)
ed1e77d3 378ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(Z_JITOperation_EJZZ operation, GPRReg arg1, int32_t arg2, int32_t arg3)
81345200
A
379{
380 setupArgumentsWithExecState(arg1, TrustedImm32(arg2), TrustedImm32(arg3));
381 return appendCallWithExceptionCheck(operation);
382}
383
ed1e77d3 384ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(F_JITOperation_EFJZZ operation, GPRReg arg1, GPRReg arg2, int32_t arg3, GPRReg arg4)
81345200 385{
ed1e77d3 386 setupArgumentsWithExecState(arg1, arg2, TrustedImm32(arg3), arg4);
81345200
A
387 return appendCallWithExceptionCheck(operation);
388}
389
ed1e77d3 390ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_ESsiJJI operation, StructureStubInfo* stubInfo, RegisterID regOp1, RegisterID regOp2, UniquedStringImpl* uid)
81345200
A
391{
392 setupArgumentsWithExecState(TrustedImmPtr(stubInfo), regOp1, regOp2, TrustedImmPtr(uid));
393 return appendCallWithExceptionCheck(operation);
394}
395
396ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_EJJJ operation, RegisterID regOp1, RegisterID regOp2, RegisterID regOp3)
397{
398 setupArgumentsWithExecState(regOp1, regOp2, regOp3);
399 return appendCallWithExceptionCheck(operation);
400}
401
ed1e77d3
A
402ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_EJJJAp operation, RegisterID regOp1, RegisterID regOp2, RegisterID regOp3, ArrayProfile* arrayProfile)
403{
404 setupArgumentsWithExecState(regOp1, regOp2, regOp3, TrustedImmPtr(arrayProfile));
405 return appendCallWithExceptionCheck(operation);
406}
407
408ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_EZJ operation, int dst, GPRReg arg)
409{
410 setupArgumentsWithExecState(TrustedImm32(dst), arg);
411 return appendCallWithExceptionCheck(operation);
412}
413
414ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(JIT::WithProfileTag, J_JITOperation_ESsiJI operation, int dst, StructureStubInfo* stubInfo, GPRReg arg1, UniquedStringImpl* uid)
81345200
A
415{
416 setupArgumentsWithExecState(TrustedImmPtr(stubInfo), arg1, TrustedImmPtr(uid));
417 return appendCallWithExceptionCheckSetJSValueResultWithProfile(operation, dst);
418}
419
420ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(JIT::WithProfileTag, J_JITOperation_EJJ operation, int dst, GPRReg arg1, GPRReg arg2)
421{
422 setupArgumentsWithExecState(arg1, arg2);
423 return appendCallWithExceptionCheckSetJSValueResultWithProfile(operation, dst);
424}
425
426ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(J_JITOperation_EAapJ operation, int dst, ArrayAllocationProfile* arg1, GPRReg arg2)
427{
428 setupArgumentsWithExecState(TrustedImmPtr(arg1), arg2);
429 return appendCallWithExceptionCheckSetJSValueResult(operation, dst);
430}
431
432ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(J_JITOperation_EJ operation, int dst, GPRReg arg1)
433{
434 setupArgumentsWithExecState(arg1);
435 return appendCallWithExceptionCheckSetJSValueResult(operation, dst);
436}
437
438ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(J_JITOperation_EJIdc operation, int dst, GPRReg arg1, const Identifier* arg2)
439{
440 setupArgumentsWithExecState(arg1, TrustedImmPtr(arg2));
441 return appendCallWithExceptionCheckSetJSValueResult(operation, dst);
442}
443
444ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(J_JITOperation_EJJ operation, int dst, GPRReg arg1, GPRReg arg2)
445{
446 setupArgumentsWithExecState(arg1, arg2);
447 return appendCallWithExceptionCheckSetJSValueResult(operation, dst);
448}
449
ed1e77d3
A
450ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(J_JITOperation_EJJAp operation, int dst, GPRReg arg1, GPRReg arg2, ArrayProfile* arrayProfile)
451{
452 setupArgumentsWithExecState(arg1, arg2, TrustedImmPtr(arrayProfile));
453 return appendCallWithExceptionCheckSetJSValueResult(operation, dst);
454}
455
81345200
A
456ALWAYS_INLINE MacroAssembler::Call JIT::callOperationNoExceptionCheck(V_JITOperation_EJ operation, GPRReg arg1)
457{
458 setupArgumentsWithExecState(arg1);
459 updateTopCallFrame();
460 return appendCall(operation);
461}
462
463ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(P_JITOperation_EJS operation, GPRReg arg1, size_t arg2)
464{
465 setupArgumentsWithExecState(arg1, TrustedImmPtr(arg2));
466 return appendCallWithExceptionCheck(operation);
467}
468
469ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(S_JITOperation_EJ operation, RegisterID regOp)
470{
471 setupArgumentsWithExecState(regOp);
472 return appendCallWithExceptionCheck(operation);
473}
474
475ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(S_JITOperation_EJJ operation, RegisterID regOp1, RegisterID regOp2)
476{
477 setupArgumentsWithExecState(regOp1, regOp2);
478 return appendCallWithExceptionCheck(operation);
479}
480
ed1e77d3 481ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_EZSymtabJ operation, int op1, SymbolTable* symbolTable, RegisterID regOp3)
81345200 482{
ed1e77d3 483 setupArgumentsWithExecState(TrustedImm32(op1), TrustedImmPtr(symbolTable), regOp3);
81345200
A
484 return appendCallWithExceptionCheck(operation);
485}
486
487ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_EJ operation, RegisterID regOp)
488{
489 setupArgumentsWithExecState(regOp);
490 return appendCallWithExceptionCheck(operation);
491}
492
ed1e77d3
A
493ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_EJIdJ operation, RegisterID regOp1, const Identifier* identOp2, RegisterID regOp3)
494{
495 setupArgumentsWithExecState(regOp1, TrustedImmPtr(identOp2), regOp3);
496 return appendCallWithExceptionCheck(operation);
497}
498
81345200
A
499ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_EJIdJJ operation, RegisterID regOp1, const Identifier* identOp2, RegisterID regOp3, RegisterID regOp4)
500{
501 setupArgumentsWithExecState(regOp1, TrustedImmPtr(identOp2), regOp3, regOp4);
502 return appendCallWithExceptionCheck(operation);
503}
504
505ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_EJZ operation, RegisterID regOp1, int32_t op2)
506{
507 setupArgumentsWithExecState(regOp1, TrustedImm32(op2));
508 return appendCallWithExceptionCheck(operation);
509}
510
511ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_EJZJ operation, RegisterID regOp1, int32_t op2, RegisterID regOp3)
512{
513 setupArgumentsWithExecState(regOp1, TrustedImm32(op2), regOp3);
514 return appendCallWithExceptionCheck(operation);
515}
14957cd0 516
81345200
A
517#else // USE(JSVALUE32_64)
518
519// EncodedJSValue in JSVALUE32_64 is a 64-bit integer. When being compiled in ARM EABI, it must be aligned even-numbered register (r0, r2 or [sp]).
520// To avoid assemblies from using wrong registers, let's occupy r1 or r3 with a dummy argument when necessary.
521#if (COMPILER_SUPPORTS(EABI) && CPU(ARM)) || CPU(MIPS)
522#define EABI_32BIT_DUMMY_ARG TrustedImm32(0),
93a37866 523#else
81345200 524#define EABI_32BIT_DUMMY_ARG
14957cd0 525#endif
93a37866 526
81345200
A
527// JSVALUE32_64 is a 64-bit integer that cannot be put half in an argument register and half on stack when using SH4 architecture.
528// To avoid this, let's occupy the 4th argument register (r7) with a dummy argument when necessary. This must only be done when there
529// is no other 32-bit value argument behind this 64-bit JSValue.
530#if CPU(SH4)
531#define SH4_32BIT_DUMMY_ARG TrustedImm32(0),
93a37866 532#else
81345200 533#define SH4_32BIT_DUMMY_ARG
f9bf01c6 534#endif
81345200
A
535
536ALWAYS_INLINE MacroAssembler::Call JIT::callOperationNoExceptionCheck(V_JITOperation_EJ operation, GPRReg arg1Tag, GPRReg arg1Payload)
537{
538 setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1Payload, arg1Tag);
539 updateTopCallFrame();
540 return appendCall(operation);
f9bf01c6
A
541}
542
ed1e77d3 543ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(Z_JITOperation_EJZZ operation, GPRReg arg1Tag, GPRReg arg1Payload, int32_t arg2, int32_t arg3)
81345200
A
544{
545 setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1Payload, arg1Tag, TrustedImm32(arg2), TrustedImm32(arg3));
546 return appendCallWithExceptionCheck(operation);
547}
14957cd0 548
ed1e77d3 549ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(F_JITOperation_EFJZZ operation, GPRReg arg1, GPRReg arg2Tag, GPRReg arg2Payload, int32_t arg3, GPRReg arg4)
6fe7ccc8 550{
ed1e77d3 551 setupArgumentsWithExecState(arg1, arg2Payload, arg2Tag, TrustedImm32(arg3), arg4);
81345200
A
552 return appendCallWithExceptionCheck(operation);
553}
554
555ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(J_JITOperation_EAapJ operation, int dst, ArrayAllocationProfile* arg1, GPRReg arg2Tag, GPRReg arg2Payload)
556{
557 setupArgumentsWithExecState(TrustedImmPtr(arg1), arg2Payload, arg2Tag);
558 return appendCallWithExceptionCheckSetJSValueResult(operation, dst);
6fe7ccc8
A
559}
560
81345200 561ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(J_JITOperation_EJ operation, int dst, GPRReg arg1Tag, GPRReg arg1Payload)
ba379fdc 562{
81345200
A
563 setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1Payload, arg1Tag);
564 return appendCallWithExceptionCheckSetJSValueResult(operation, dst);
565}
566
ed1e77d3 567ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(JIT::WithProfileTag, J_JITOperation_ESsiJI operation, int dst, StructureStubInfo* stubInfo, GPRReg arg1Tag, GPRReg arg1Payload, UniquedStringImpl* uid)
81345200
A
568{
569 setupArgumentsWithExecState(TrustedImmPtr(stubInfo), arg1Payload, arg1Tag, TrustedImmPtr(uid));
570 return appendCallWithExceptionCheckSetJSValueResultWithProfile(operation, dst);
571}
572
573ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(J_JITOperation_EJIdc operation, int dst, GPRReg arg1Tag, GPRReg arg1Payload, const Identifier* arg2)
574{
575 setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1Payload, arg1Tag, TrustedImmPtr(arg2));
576 return appendCallWithExceptionCheckSetJSValueResult(operation, dst);
577}
578
579ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(J_JITOperation_EJJ operation, int dst, GPRReg arg1Tag, GPRReg arg1Payload, GPRReg arg2Tag, GPRReg arg2Payload)
580{
581 setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1Payload, arg1Tag, SH4_32BIT_DUMMY_ARG arg2Payload, arg2Tag);
582 return appendCallWithExceptionCheckSetJSValueResult(operation, dst);
583}
584
ed1e77d3
A
585ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(J_JITOperation_EJJAp operation, int dst, GPRReg arg1Tag, GPRReg arg1Payload, GPRReg arg2Tag, GPRReg arg2Payload, ArrayProfile* arrayProfile)
586{
587 setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1Payload, arg1Tag, SH4_32BIT_DUMMY_ARG arg2Payload, arg2Tag, TrustedImmPtr(arrayProfile));
588 return appendCallWithExceptionCheckSetJSValueResult(operation, dst);
589}
590
81345200
A
591ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(JIT::WithProfileTag, J_JITOperation_EJJ operation, int dst, GPRReg arg1Tag, GPRReg arg1Payload, GPRReg arg2Tag, GPRReg arg2Payload)
592{
593 setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1Payload, arg1Tag, SH4_32BIT_DUMMY_ARG arg2Payload, arg2Tag);
594 return appendCallWithExceptionCheckSetJSValueResultWithProfile(operation, dst);
595}
596
597ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(P_JITOperation_EJS operation, GPRReg arg1Tag, GPRReg arg1Payload, size_t arg2)
598{
599 setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1Payload, arg1Tag, TrustedImmPtr(arg2));
600 return appendCallWithExceptionCheck(operation);
601}
602
603ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(S_JITOperation_EJ operation, RegisterID argTag, RegisterID argPayload)
604{
605 setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG argPayload, argTag);
606 return appendCallWithExceptionCheck(operation);
607}
608
609ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(S_JITOperation_EJJ operation, RegisterID arg1Tag, RegisterID arg1Payload, RegisterID arg2Tag, RegisterID arg2Payload)
610{
611 setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1Payload, arg1Tag, SH4_32BIT_DUMMY_ARG arg2Payload, arg2Tag);
612 return appendCallWithExceptionCheck(operation);
ba379fdc 613}
ba379fdc 614
ed1e77d3
A
615ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_ECIC operation, RegisterID regOp1, const Identifier* identOp2, RegisterID regOp3)
616{
617 setupArgumentsWithExecState(regOp1, TrustedImmPtr(identOp2), regOp3);
618 return appendCallWithExceptionCheck(operation);
619}
620
81345200
A
621ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_ECICC operation, RegisterID regOp1, const Identifier* identOp2, RegisterID regOp3, RegisterID regOp4)
622{
623 setupArgumentsWithExecState(regOp1, TrustedImmPtr(identOp2), regOp3, regOp4);
624 return appendCallWithExceptionCheck(operation);
625}
626
627ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_EJ operation, RegisterID regOp1Tag, RegisterID regOp1Payload)
628{
629 setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG regOp1Payload, regOp1Tag);
630 return appendCallWithExceptionCheck(operation);
631}
632
ed1e77d3 633ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_EZSymtabJ operation, int32_t op1, SymbolTable* symbolTable, RegisterID regOp3Tag, RegisterID regOp3Payload)
81345200 634{
ed1e77d3 635 setupArgumentsWithExecState(TrustedImm32(op1), TrustedImmPtr(symbolTable), EABI_32BIT_DUMMY_ARG regOp3Payload, regOp3Tag);
81345200
A
636 return appendCallWithExceptionCheck(operation);
637}
638
ed1e77d3 639ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_ESsiJJI operation, StructureStubInfo* stubInfo, RegisterID regOp1Tag, RegisterID regOp1Payload, RegisterID regOp2Tag, RegisterID regOp2Payload, UniquedStringImpl* uid)
81345200
A
640{
641 setupArgumentsWithExecState(TrustedImmPtr(stubInfo), regOp1Payload, regOp1Tag, regOp2Payload, regOp2Tag, TrustedImmPtr(uid));
642 return appendCallWithExceptionCheck(operation);
643}
644
645ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_EJJJ operation, RegisterID regOp1Tag, RegisterID regOp1Payload, RegisterID regOp2Tag, RegisterID regOp2Payload, RegisterID regOp3Tag, RegisterID regOp3Payload)
646{
647 setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG regOp1Payload, regOp1Tag, SH4_32BIT_DUMMY_ARG regOp2Payload, regOp2Tag, regOp3Payload, regOp3Tag);
648 return appendCallWithExceptionCheck(operation);
649}
650
ed1e77d3
A
651ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_EJJJAp operation, RegisterID regOp1Tag, RegisterID regOp1Payload, RegisterID regOp2Tag, RegisterID regOp2Payload, RegisterID regOp3Tag, RegisterID regOp3Payload, ArrayProfile* arrayProfile)
652{
653 setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG regOp1Payload, regOp1Tag, SH4_32BIT_DUMMY_ARG regOp2Payload, regOp2Tag, regOp3Payload, regOp3Tag, TrustedImmPtr(arrayProfile));
654 return appendCallWithExceptionCheck(operation);
655}
656
657ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_EZJ operation, int dst, RegisterID regOp1Tag, RegisterID regOp1Payload)
658{
659 setupArgumentsWithExecState(TrustedImm32(dst), regOp1Payload, regOp1Tag);
660 return appendCallWithExceptionCheck(operation);
661}
662
81345200
A
663ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_EJZ operation, RegisterID regOp1Tag, RegisterID regOp1Payload, int32_t op2)
664{
665 setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG regOp1Payload, regOp1Tag, TrustedImm32(op2));
666 return appendCallWithExceptionCheck(operation);
667}
668
669ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_EJZJ operation, RegisterID regOp1Tag, RegisterID regOp1Payload, int32_t op2, RegisterID regOp3Tag, RegisterID regOp3Payload)
670{
671 setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG regOp1Payload, regOp1Tag, TrustedImm32(op2), EABI_32BIT_DUMMY_ARG regOp3Payload, regOp3Tag);
672 return appendCallWithExceptionCheck(operation);
673}
674
675#undef EABI_32BIT_DUMMY_ARG
676#undef SH4_32BIT_DUMMY_ARG
677
678#endif // USE(JSVALUE32_64)
679
ba379fdc
A
680ALWAYS_INLINE JIT::Jump JIT::checkStructure(RegisterID reg, Structure* structure)
681{
81345200 682 return branchStructure(NotEqual, Address(reg, JSCell::structureIDOffset()), structure);
ba379fdc
A
683}
684
685ALWAYS_INLINE void JIT::linkSlowCaseIfNotJSCell(Vector<SlowCaseEntry>::iterator& iter, int vReg)
686{
687 if (!m_codeBlock->isKnownNotImmediate(vReg))
688 linkSlowCase(iter);
689}
690
691ALWAYS_INLINE void JIT::addSlowCase(Jump jump)
9dae56ea 692{
ed1e77d3 693 ASSERT(m_bytecodeOffset != std::numeric_limits<unsigned>::max()); // This method should only be called during hot/cold path generation, so that m_bytecodeOffset is set.
9dae56ea 694
14957cd0 695 m_slowCases.append(SlowCaseEntry(jump, m_bytecodeOffset));
ba379fdc
A
696}
697
698ALWAYS_INLINE void JIT::addSlowCase(JumpList jumpList)
699{
ed1e77d3 700 ASSERT(m_bytecodeOffset != std::numeric_limits<unsigned>::max()); // This method should only be called during hot/cold path generation, so that m_bytecodeOffset is set.
ba379fdc
A
701
702 const JumpList::JumpVector& jumpVector = jumpList.jumps();
703 size_t size = jumpVector.size();
704 for (size_t i = 0; i < size; ++i)
14957cd0 705 m_slowCases.append(SlowCaseEntry(jumpVector[i], m_bytecodeOffset));
ba379fdc
A
706}
707
6fe7ccc8
A
708ALWAYS_INLINE void JIT::addSlowCase()
709{
ed1e77d3 710 ASSERT(m_bytecodeOffset != std::numeric_limits<unsigned>::max()); // This method should only be called during hot/cold path generation, so that m_bytecodeOffset is set.
6fe7ccc8
A
711
712 Jump emptyJump; // Doing it this way to make Windows happy.
713 m_slowCases.append(SlowCaseEntry(emptyJump, m_bytecodeOffset));
714}
715
ba379fdc
A
716ALWAYS_INLINE void JIT::addJump(Jump jump, int relativeOffset)
717{
ed1e77d3 718 ASSERT(m_bytecodeOffset != std::numeric_limits<unsigned>::max()); // This method should only be called during hot/cold path generation, so that m_bytecodeOffset is set.
ba379fdc 719
14957cd0 720 m_jmpTable.append(JumpTable(jump, m_bytecodeOffset + relativeOffset));
ba379fdc
A
721}
722
723ALWAYS_INLINE void JIT::emitJumpSlowToHot(Jump jump, int relativeOffset)
724{
ed1e77d3 725 ASSERT(m_bytecodeOffset != std::numeric_limits<unsigned>::max()); // This method should only be called during hot/cold path generation, so that m_bytecodeOffset is set.
ba379fdc 726
14957cd0 727 jump.linkTo(m_labels[m_bytecodeOffset + relativeOffset], this);
ba379fdc
A
728}
729
ed1e77d3
A
730ALWAYS_INLINE JIT::Jump JIT::emitJumpIfCellObject(RegisterID cellReg)
731{
732 return branch8(AboveOrEqual, Address(cellReg, JSCell::typeInfoTypeOffset()), TrustedImm32(ObjectType));
733}
734
81345200 735ALWAYS_INLINE JIT::Jump JIT::emitJumpIfCellNotObject(RegisterID cellReg)
6fe7ccc8 736{
81345200 737 return branch8(Below, Address(cellReg, JSCell::typeInfoTypeOffset()), TrustedImm32(ObjectType));
6fe7ccc8
A
738}
739
ba379fdc
A
740#if ENABLE(SAMPLING_FLAGS)
741ALWAYS_INLINE void JIT::setSamplingFlag(int32_t flag)
742{
743 ASSERT(flag >= 1);
744 ASSERT(flag <= 32);
14957cd0 745 or32(TrustedImm32(1u << (flag - 1)), AbsoluteAddress(SamplingFlags::addressOfFlags()));
ba379fdc
A
746}
747
748ALWAYS_INLINE void JIT::clearSamplingFlag(int32_t flag)
749{
750 ASSERT(flag >= 1);
751 ASSERT(flag <= 32);
14957cd0 752 and32(TrustedImm32(~(1u << (flag - 1))), AbsoluteAddress(SamplingFlags::addressOfFlags()));
ba379fdc
A
753}
754#endif
755
756#if ENABLE(SAMPLING_COUNTERS)
6fe7ccc8
A
757ALWAYS_INLINE void JIT::emitCount(AbstractSamplingCounter& counter, int32_t count)
758{
759 add64(TrustedImm32(count), AbsoluteAddress(counter.addressOfCounter()));
ba379fdc
A
760}
761#endif
762
763#if ENABLE(OPCODE_SAMPLING)
f9bf01c6 764#if CPU(X86_64)
ba379fdc
A
765ALWAYS_INLINE void JIT::sampleInstruction(Instruction* instruction, bool inHostFunction)
766{
14957cd0
A
767 move(TrustedImmPtr(m_interpreter->sampler()->sampleSlot()), X86Registers::ecx);
768 storePtr(TrustedImmPtr(m_interpreter->sampler()->encodeSample(instruction, inHostFunction)), X86Registers::ecx);
ba379fdc
A
769}
770#else
771ALWAYS_INLINE void JIT::sampleInstruction(Instruction* instruction, bool inHostFunction)
772{
14957cd0 773 storePtr(TrustedImmPtr(m_interpreter->sampler()->encodeSample(instruction, inHostFunction)), m_interpreter->sampler()->sampleSlot());
ba379fdc
A
774}
775#endif
776#endif
777
778#if ENABLE(CODEBLOCK_SAMPLING)
f9bf01c6 779#if CPU(X86_64)
ba379fdc
A
780ALWAYS_INLINE void JIT::sampleCodeBlock(CodeBlock* codeBlock)
781{
14957cd0
A
782 move(TrustedImmPtr(m_interpreter->sampler()->codeBlockSlot()), X86Registers::ecx);
783 storePtr(TrustedImmPtr(codeBlock), X86Registers::ecx);
ba379fdc
A
784}
785#else
786ALWAYS_INLINE void JIT::sampleCodeBlock(CodeBlock* codeBlock)
787{
14957cd0 788 storePtr(TrustedImmPtr(codeBlock), m_interpreter->sampler()->codeBlockSlot());
ba379fdc
A
789}
790#endif
791#endif
792
81345200 793ALWAYS_INLINE bool JIT::isOperandConstantImmediateChar(int src)
f9bf01c6 794{
4e4e5a6f 795 return m_codeBlock->isConstantRegisterIndex(src) && getConstantOperand(src).isString() && asString(getConstantOperand(src).asCell())->length() == 1;
f9bf01c6
A
796}
797
93a37866
A
798template<typename StructureType>
799inline void JIT::emitAllocateJSObject(RegisterID allocator, StructureType structure, RegisterID result, RegisterID scratch)
6fe7ccc8 800{
93a37866 801 loadPtr(Address(allocator, MarkedAllocator::offsetOfFreeListHead()), result);
6fe7ccc8
A
802 addSlowCase(branchTestPtr(Zero, result));
803
804 // remove the object from the free list
93a37866
A
805 loadPtr(Address(result), scratch);
806 storePtr(scratch, Address(allocator, MarkedAllocator::offsetOfFreeListHead()));
6fe7ccc8 807
6fe7ccc8 808 // initialize the object's property storage pointer
93a37866 809 storePtr(TrustedImmPtr(0), Address(result, JSObject::butterflyOffset()));
81345200
A
810
811 // initialize the object's structure
812 emitStoreStructureWithTypeInfo(structure, result, scratch);
6fe7ccc8
A
813}
814
6fe7ccc8
A
815inline void JIT::emitValueProfilingSite(ValueProfile* valueProfile)
816{
817 ASSERT(shouldEmitProfiling());
818 ASSERT(valueProfile);
819
820 const RegisterID value = regT0;
821#if USE(JSVALUE32_64)
822 const RegisterID valueTag = regT1;
823#endif
6fe7ccc8 824
81345200
A
825 // We're in a simple configuration: only one bucket, so we can just do a direct
826 // store.
6fe7ccc8 827#if USE(JSVALUE64)
81345200 828 store64(value, valueProfile->m_buckets);
6fe7ccc8 829#else
81345200
A
830 EncodedValueDescriptor* descriptor = bitwise_cast<EncodedValueDescriptor*>(valueProfile->m_buckets);
831 store32(value, &descriptor->asBits.payload);
832 store32(valueTag, &descriptor->asBits.tag);
6fe7ccc8
A
833#endif
834}
835
836inline void JIT::emitValueProfilingSite(unsigned bytecodeOffset)
837{
838 if (!shouldEmitProfiling())
839 return;
840 emitValueProfilingSite(m_codeBlock->valueProfileForBytecodeOffset(bytecodeOffset));
841}
842
843inline void JIT::emitValueProfilingSite()
844{
845 emitValueProfilingSite(m_bytecodeOffset);
846}
93a37866 847
81345200 848inline void JIT::emitArrayProfilingSiteWithCell(RegisterID cell, RegisterID indexingType, ArrayProfile* arrayProfile)
93a37866 849{
81345200
A
850 if (shouldEmitProfiling()) {
851 load32(MacroAssembler::Address(cell, JSCell::structureIDOffset()), indexingType);
852 store32(indexingType, arrayProfile->addressOfLastSeenStructureID());
853 }
93a37866 854
81345200 855 load8(Address(cell, JSCell::indexingTypeOffset()), indexingType);
93a37866
A
856}
857
81345200 858inline void JIT::emitArrayProfilingSiteForBytecodeIndexWithCell(RegisterID cell, RegisterID indexingType, unsigned bytecodeIndex)
93a37866 859{
81345200 860 emitArrayProfilingSiteWithCell(cell, indexingType, m_codeBlock->getOrAddArrayProfile(bytecodeIndex));
93a37866
A
861}
862
863inline void JIT::emitArrayProfileStoreToHoleSpecialCase(ArrayProfile* arrayProfile)
864{
93a37866 865 store8(TrustedImm32(1), arrayProfile->addressOfMayStoreToHole());
93a37866
A
866}
867
868inline void JIT::emitArrayProfileOutOfBoundsSpecialCase(ArrayProfile* arrayProfile)
869{
93a37866 870 store8(TrustedImm32(1), arrayProfile->addressOfOutOfBounds());
93a37866
A
871}
872
873static inline bool arrayProfileSaw(ArrayModes arrayModes, IndexingType capability)
874{
93a37866 875 return arrayModesInclude(arrayModes, capability);
93a37866
A
876}
877
878inline JITArrayMode JIT::chooseArrayMode(ArrayProfile* profile)
879{
81345200
A
880 ConcurrentJITLocker locker(m_codeBlock->m_lock);
881 profile->computeUpdatedPrediction(locker, m_codeBlock);
882 ArrayModes arrayModes = profile->observedArrayModes(locker);
93a37866
A
883 if (arrayProfileSaw(arrayModes, DoubleShape))
884 return JITDouble;
885 if (arrayProfileSaw(arrayModes, Int32Shape))
886 return JITInt32;
887 if (arrayProfileSaw(arrayModes, ArrayStorageShape))
888 return JITArrayStorage;
889 return JITContiguous;
93a37866 890}
6fe7ccc8 891
ba379fdc
A
892#if USE(JSVALUE32_64)
893
6fe7ccc8 894inline void JIT::emitLoadTag(int index, RegisterID tag)
ba379fdc 895{
ba379fdc
A
896 if (m_codeBlock->isConstantRegisterIndex(index)) {
897 move(Imm32(getConstantOperand(index).tag()), tag);
ba379fdc
A
898 return;
899 }
9dae56ea 900
ba379fdc 901 load32(tagFor(index), tag);
ba379fdc
A
902}
903
6fe7ccc8 904inline void JIT::emitLoadPayload(int index, RegisterID payload)
ba379fdc 905{
ba379fdc
A
906 if (m_codeBlock->isConstantRegisterIndex(index)) {
907 move(Imm32(getConstantOperand(index).payload()), payload);
ba379fdc
A
908 return;
909 }
910
911 load32(payloadFor(index), payload);
9dae56ea
A
912}
913
ba379fdc 914inline void JIT::emitLoad(const JSValue& v, RegisterID tag, RegisterID payload)
9dae56ea 915{
ba379fdc
A
916 move(Imm32(v.payload()), payload);
917 move(Imm32(v.tag()), tag);
918}
919
6fe7ccc8 920inline void JIT::emitLoad(int index, RegisterID tag, RegisterID payload, RegisterID base)
ba379fdc 921{
93a37866 922 RELEASE_ASSERT(tag != payload);
ba379fdc
A
923
924 if (base == callFrameRegister) {
93a37866 925 RELEASE_ASSERT(payload != base);
ba379fdc
A
926 emitLoadPayload(index, payload);
927 emitLoadTag(index, tag);
928 return;
9dae56ea 929 }
ba379fdc
A
930
931 if (payload == base) { // avoid stomping base
932 load32(tagFor(index, base), tag);
933 load32(payloadFor(index, base), payload);
934 return;
935 }
936
937 load32(payloadFor(index, base), payload);
938 load32(tagFor(index, base), tag);
9dae56ea
A
939}
940
6fe7ccc8 941inline void JIT::emitLoad2(int index1, RegisterID tag1, RegisterID payload1, int index2, RegisterID tag2, RegisterID payload2)
9dae56ea 942{
ba379fdc
A
943 emitLoad(index2, tag2, payload2);
944 emitLoad(index1, tag1, payload1);
9dae56ea
A
945}
946
6fe7ccc8 947inline void JIT::emitLoadDouble(int index, FPRegisterID value)
9dae56ea 948{
ba379fdc 949 if (m_codeBlock->isConstantRegisterIndex(index)) {
14957cd0 950 WriteBarrier<Unknown>& inConstantPool = m_codeBlock->constantRegister(index);
81345200 951 loadDouble(TrustedImmPtr(&inConstantPool), value);
ba379fdc
A
952 } else
953 loadDouble(addressFor(index), value);
9dae56ea
A
954}
955
6fe7ccc8 956inline void JIT::emitLoadInt32ToDouble(int index, FPRegisterID value)
9dae56ea 957{
ba379fdc 958 if (m_codeBlock->isConstantRegisterIndex(index)) {
14957cd0 959 WriteBarrier<Unknown>& inConstantPool = m_codeBlock->constantRegister(index);
ba379fdc
A
960 char* bytePointer = reinterpret_cast<char*>(&inConstantPool);
961 convertInt32ToDouble(AbsoluteAddress(bytePointer + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), value);
962 } else
963 convertInt32ToDouble(payloadFor(index), value);
9dae56ea
A
964}
965
6fe7ccc8 966inline void JIT::emitStore(int index, RegisterID tag, RegisterID payload, RegisterID base)
9dae56ea 967{
ba379fdc
A
968 store32(payload, payloadFor(index, base));
969 store32(tag, tagFor(index, base));
9dae56ea
A
970}
971
6fe7ccc8 972inline void JIT::emitStoreInt32(int index, RegisterID payload, bool indexIsInt32)
9dae56ea 973{
ba379fdc
A
974 store32(payload, payloadFor(index, callFrameRegister));
975 if (!indexIsInt32)
14957cd0 976 store32(TrustedImm32(JSValue::Int32Tag), tagFor(index, callFrameRegister));
9dae56ea
A
977}
978
6fe7ccc8 979inline void JIT::emitStoreInt32(int index, TrustedImm32 payload, bool indexIsInt32)
9dae56ea 980{
ba379fdc
A
981 store32(payload, payloadFor(index, callFrameRegister));
982 if (!indexIsInt32)
14957cd0 983 store32(TrustedImm32(JSValue::Int32Tag), tagFor(index, callFrameRegister));
9dae56ea
A
984}
985
6fe7ccc8 986inline void JIT::emitStoreCell(int index, RegisterID payload, bool indexIsCell)
9dae56ea 987{
ba379fdc
A
988 store32(payload, payloadFor(index, callFrameRegister));
989 if (!indexIsCell)
14957cd0 990 store32(TrustedImm32(JSValue::CellTag), tagFor(index, callFrameRegister));
9dae56ea
A
991}
992
6fe7ccc8 993inline void JIT::emitStoreBool(int index, RegisterID payload, bool indexIsBool)
9dae56ea 994{
14957cd0 995 store32(payload, payloadFor(index, callFrameRegister));
ba379fdc 996 if (!indexIsBool)
14957cd0 997 store32(TrustedImm32(JSValue::BooleanTag), tagFor(index, callFrameRegister));
ba379fdc 998}
9dae56ea 999
6fe7ccc8 1000inline void JIT::emitStoreDouble(int index, FPRegisterID value)
ba379fdc
A
1001{
1002 storeDouble(value, addressFor(index));
9dae56ea
A
1003}
1004
6fe7ccc8 1005inline void JIT::emitStore(int index, const JSValue constant, RegisterID base)
9dae56ea 1006{
ba379fdc
A
1007 store32(Imm32(constant.payload()), payloadFor(index, base));
1008 store32(Imm32(constant.tag()), tagFor(index, base));
9dae56ea
A
1009}
1010
81345200 1011ALWAYS_INLINE void JIT::emitInitRegister(int dst)
9dae56ea 1012{
ba379fdc 1013 emitStore(dst, jsUndefined());
9dae56ea
A
1014}
1015
6fe7ccc8 1016inline void JIT::emitJumpSlowCaseIfNotJSCell(int virtualRegisterIndex)
ba379fdc 1017{
4e4e5a6f
A
1018 if (!m_codeBlock->isKnownNotImmediate(virtualRegisterIndex)) {
1019 if (m_codeBlock->isConstantRegisterIndex(virtualRegisterIndex))
1020 addSlowCase(jump());
1021 else
1022 addSlowCase(emitJumpIfNotJSCell(virtualRegisterIndex));
1023 }
9dae56ea
A
1024}
1025
6fe7ccc8 1026inline void JIT::emitJumpSlowCaseIfNotJSCell(int virtualRegisterIndex, RegisterID tag)
9dae56ea 1027{
4e4e5a6f
A
1028 if (!m_codeBlock->isKnownNotImmediate(virtualRegisterIndex)) {
1029 if (m_codeBlock->isConstantRegisterIndex(virtualRegisterIndex))
1030 addSlowCase(jump());
1031 else
14957cd0 1032 addSlowCase(branch32(NotEqual, tag, TrustedImm32(JSValue::CellTag)));
4e4e5a6f 1033 }
ba379fdc 1034}
9dae56ea 1035
81345200 1036ALWAYS_INLINE bool JIT::isOperandConstantImmediateInt(int src)
9dae56ea 1037{
ba379fdc 1038 return m_codeBlock->isConstantRegisterIndex(src) && getConstantOperand(src).isInt32();
9dae56ea 1039}
ba379fdc 1040
81345200 1041ALWAYS_INLINE bool JIT::getOperandConstantImmediateInt(int op1, int op2, int& op, int32_t& constant)
9dae56ea 1042{
ba379fdc
A
1043 if (isOperandConstantImmediateInt(op1)) {
1044 constant = getConstantOperand(op1).asInt32();
1045 op = op2;
1046 return true;
1047 }
1048
1049 if (isOperandConstantImmediateInt(op2)) {
1050 constant = getConstantOperand(op2).asInt32();
1051 op = op1;
1052 return true;
1053 }
1054
1055 return false;
9dae56ea 1056}
ba379fdc 1057
ba379fdc
A
1058#else // USE(JSVALUE32_64)
1059
ba379fdc
A
1060// get arg puts an arg from the SF register array into a h/w register
1061ALWAYS_INLINE void JIT::emitGetVirtualRegister(int src, RegisterID dst)
9dae56ea 1062{
ed1e77d3 1063 ASSERT(m_bytecodeOffset != std::numeric_limits<unsigned>::max()); // This method should only be called during hot/cold path generation, so that m_bytecodeOffset is set.
9dae56ea 1064
ba379fdc
A
1065 // TODO: we want to reuse values that are already in registers if we can - add a register allocator!
1066 if (m_codeBlock->isConstantRegisterIndex(src)) {
1067 JSValue value = m_codeBlock->getConstant(src);
6fe7ccc8 1068 if (!value.isNumber())
93a37866 1069 move(TrustedImm64(JSValue::encode(value)), dst);
6fe7ccc8 1070 else
93a37866 1071 move(Imm64(JSValue::encode(value)), dst);
14957cd0 1072 return;
ba379fdc
A
1073 }
1074
93a37866 1075 load64(Address(callFrameRegister, src * sizeof(Register)), dst);
81345200
A
1076}
1077
1078ALWAYS_INLINE void JIT::emitGetVirtualRegister(VirtualRegister src, RegisterID dst)
1079{
1080 emitGetVirtualRegister(src.offset(), dst);
ba379fdc
A
1081}
1082
1083ALWAYS_INLINE void JIT::emitGetVirtualRegisters(int src1, RegisterID dst1, int src2, RegisterID dst2)
1084{
81345200
A
1085 emitGetVirtualRegister(src1, dst1);
1086 emitGetVirtualRegister(src2, dst2);
ba379fdc 1087}
9dae56ea 1088
81345200
A
1089ALWAYS_INLINE void JIT::emitGetVirtualRegisters(VirtualRegister src1, RegisterID dst1, VirtualRegister src2, RegisterID dst2)
1090{
1091 emitGetVirtualRegisters(src1.offset(), dst1, src2.offset(), dst2);
1092}
1093
1094ALWAYS_INLINE int32_t JIT::getConstantOperandImmediateInt(int src)
ba379fdc
A
1095{
1096 return getConstantOperand(src).asInt32();
9dae56ea
A
1097}
1098
81345200 1099ALWAYS_INLINE bool JIT::isOperandConstantImmediateInt(int src)
ba379fdc
A
1100{
1101 return m_codeBlock->isConstantRegisterIndex(src) && getConstantOperand(src).isInt32();
1102}
1103
81345200 1104ALWAYS_INLINE void JIT::emitPutVirtualRegister(int dst, RegisterID from)
9dae56ea 1105{
93a37866 1106 store64(from, Address(callFrameRegister, dst * sizeof(Register)));
ba379fdc
A
1107}
1108
81345200
A
1109ALWAYS_INLINE void JIT::emitPutVirtualRegister(VirtualRegister dst, RegisterID from)
1110{
1111 emitPutVirtualRegister(dst.offset(), from);
1112}
1113
1114ALWAYS_INLINE void JIT::emitInitRegister(int dst)
ba379fdc 1115{
93a37866 1116 store64(TrustedImm64(JSValue::encode(jsUndefined())), Address(callFrameRegister, dst * sizeof(Register)));
9dae56ea
A
1117}
1118
1119ALWAYS_INLINE JIT::Jump JIT::emitJumpIfJSCell(RegisterID reg)
1120{
93a37866 1121 return branchTest64(Zero, reg, tagMaskRegister);
9dae56ea
A
1122}
1123
1124ALWAYS_INLINE JIT::Jump JIT::emitJumpIfBothJSCells(RegisterID reg1, RegisterID reg2, RegisterID scratch)
1125{
1126 move(reg1, scratch);
93a37866 1127 or64(reg2, scratch);
9dae56ea
A
1128 return emitJumpIfJSCell(scratch);
1129}
1130
1131ALWAYS_INLINE void JIT::emitJumpSlowCaseIfJSCell(RegisterID reg)
1132{
1133 addSlowCase(emitJumpIfJSCell(reg));
1134}
1135
9dae56ea
A
1136ALWAYS_INLINE void JIT::emitJumpSlowCaseIfNotJSCell(RegisterID reg)
1137{
1138 addSlowCase(emitJumpIfNotJSCell(reg));
1139}
1140
1141ALWAYS_INLINE void JIT::emitJumpSlowCaseIfNotJSCell(RegisterID reg, int vReg)
1142{
1143 if (!m_codeBlock->isKnownNotImmediate(vReg))
1144 emitJumpSlowCaseIfNotJSCell(reg);
1145}
1146
6fe7ccc8 1147inline void JIT::emitLoadDouble(int index, FPRegisterID value)
f9bf01c6
A
1148{
1149 if (m_codeBlock->isConstantRegisterIndex(index)) {
14957cd0 1150 WriteBarrier<Unknown>& inConstantPool = m_codeBlock->constantRegister(index);
81345200 1151 loadDouble(TrustedImmPtr(&inConstantPool), value);
f9bf01c6
A
1152 } else
1153 loadDouble(addressFor(index), value);
1154}
1155
6fe7ccc8 1156inline void JIT::emitLoadInt32ToDouble(int index, FPRegisterID value)
f9bf01c6
A
1157{
1158 if (m_codeBlock->isConstantRegisterIndex(index)) {
14957cd0
A
1159 ASSERT(isOperandConstantImmediateInt(index));
1160 convertInt32ToDouble(Imm32(getConstantOperand(index).asInt32()), value);
f9bf01c6
A
1161 } else
1162 convertInt32ToDouble(addressFor(index), value);
1163}
9dae56ea
A
1164
1165ALWAYS_INLINE JIT::Jump JIT::emitJumpIfImmediateInteger(RegisterID reg)
1166{
93a37866 1167 return branch64(AboveOrEqual, reg, tagTypeNumberRegister);
9dae56ea
A
1168}
1169
1170ALWAYS_INLINE JIT::Jump JIT::emitJumpIfNotImmediateInteger(RegisterID reg)
1171{
93a37866 1172 return branch64(Below, reg, tagTypeNumberRegister);
9dae56ea
A
1173}
1174
1175ALWAYS_INLINE JIT::Jump JIT::emitJumpIfNotImmediateIntegers(RegisterID reg1, RegisterID reg2, RegisterID scratch)
1176{
1177 move(reg1, scratch);
93a37866 1178 and64(reg2, scratch);
9dae56ea
A
1179 return emitJumpIfNotImmediateInteger(scratch);
1180}
1181
1182ALWAYS_INLINE void JIT::emitJumpSlowCaseIfNotImmediateInteger(RegisterID reg)
1183{
1184 addSlowCase(emitJumpIfNotImmediateInteger(reg));
1185}
1186
1187ALWAYS_INLINE void JIT::emitJumpSlowCaseIfNotImmediateIntegers(RegisterID reg1, RegisterID reg2, RegisterID scratch)
1188{
1189 addSlowCase(emitJumpIfNotImmediateIntegers(reg1, reg2, scratch));
1190}
1191
f9bf01c6
A
1192ALWAYS_INLINE void JIT::emitJumpSlowCaseIfNotImmediateNumber(RegisterID reg)
1193{
1194 addSlowCase(emitJumpIfNotImmediateNumber(reg));
1195}
1196
9dae56ea
A
1197ALWAYS_INLINE void JIT::emitFastArithReTagImmediate(RegisterID src, RegisterID dest)
1198{
9dae56ea 1199 emitFastArithIntToImmNoCheck(src, dest);
9dae56ea
A
1200}
1201
1202ALWAYS_INLINE void JIT::emitTagAsBoolImmediate(RegisterID reg)
1203{
14957cd0 1204 or32(TrustedImm32(static_cast<int32_t>(ValueFalse)), reg);
9dae56ea
A
1205}
1206
ba379fdc 1207#endif // USE(JSVALUE32_64)
9dae56ea 1208
81345200
A
1209template <typename T>
1210JIT::Jump JIT::branchStructure(RelationalCondition condition, T leftHandSide, Structure* structure)
1211{
1212#if USE(JSVALUE64)
1213 return branch32(condition, leftHandSide, TrustedImm32(structure->id()));
1214#else
1215 return branchPtr(condition, leftHandSide, TrustedImmPtr(structure));
1216#endif
1217}
1218
1219template <typename T>
1220MacroAssembler::Jump branchStructure(MacroAssembler& jit, MacroAssembler::RelationalCondition condition, T leftHandSide, Structure* structure)
1221{
1222#if USE(JSVALUE64)
1223 return jit.branch32(condition, leftHandSide, MacroAssembler::TrustedImm32(structure->id()));
1224#else
1225 return jit.branchPtr(condition, leftHandSide, MacroAssembler::TrustedImmPtr(structure));
1226#endif
1227}
1228
ba379fdc 1229} // namespace JSC
9dae56ea
A
1230
1231#endif // ENABLE(JIT)
1232
93a37866
A
1233#endif // JITInlines_h
1234