2 * Copyright (C) 2008 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
29 #include <wtf/Platform.h>
33 #define WTF_USE_CTI_REPATCH_PIC 1
35 #include "Interpreter.h"
37 #include "RegisterFile.h"
38 #include "X86Assembler.h"
40 #include <wtf/AlwaysInline.h>
41 #include <wtf/Vector.h>
43 #define CTI_ARGS_code 0x0C
44 #define CTI_ARGS_registerFile 0x0D
45 #define CTI_ARGS_callFrame 0x0E
46 #define CTI_ARGS_exception 0x0F
47 #define CTI_ARGS_profilerReference 0x10
48 #define CTI_ARGS_globalData 0x11
50 #define ARG_callFrame static_cast<CallFrame*>(ARGS[CTI_ARGS_callFrame])
51 #define ARG_registerFile static_cast<RegisterFile*>(ARGS[CTI_ARGS_registerFile])
52 #define ARG_exception static_cast<JSValue**>(ARGS[CTI_ARGS_exception])
53 #define ARG_profilerReference static_cast<Profiler**>(ARGS[CTI_ARGS_profilerReference])
54 #define ARG_globalData static_cast<JSGlobalData*>(ARGS[CTI_ARGS_globalData])
56 #define ARG_setCallFrame(newCallFrame) (ARGS[CTI_ARGS_callFrame] = (newCallFrame))
58 #define ARG_src1 static_cast<JSValue*>(ARGS[1])
59 #define ARG_src2 static_cast<JSValue*>(ARGS[2])
60 #define ARG_src3 static_cast<JSValue*>(ARGS[3])
61 #define ARG_src4 static_cast<JSValue*>(ARGS[4])
62 #define ARG_src5 static_cast<JSValue*>(ARGS[5])
63 #define ARG_id1 static_cast<Identifier*>(ARGS[1])
64 #define ARG_id2 static_cast<Identifier*>(ARGS[2])
65 #define ARG_id3 static_cast<Identifier*>(ARGS[3])
66 #define ARG_id4 static_cast<Identifier*>(ARGS[4])
67 #define ARG_int1 reinterpret_cast<intptr_t>(ARGS[1])
68 #define ARG_int2 reinterpret_cast<intptr_t>(ARGS[2])
69 #define ARG_int3 reinterpret_cast<intptr_t>(ARGS[3])
70 #define ARG_int4 reinterpret_cast<intptr_t>(ARGS[4])
71 #define ARG_int5 reinterpret_cast<intptr_t>(ARGS[5])
72 #define ARG_int6 reinterpret_cast<intptr_t>(ARGS[6])
73 #define ARG_func1 static_cast<FuncDeclNode*>(ARGS[1])
74 #define ARG_funcexp1 static_cast<FuncExprNode*>(ARGS[1])
75 #define ARG_registers1 static_cast<Register*>(ARGS[1])
76 #define ARG_regexp1 static_cast<RegExp*>(ARGS[1])
77 #define ARG_pni1 static_cast<JSPropertyNameIterator*>(ARGS[1])
78 #define ARG_instr1 static_cast<Instruction*>(ARGS[1])
79 #define ARG_instr2 static_cast<Instruction*>(ARGS[2])
80 #define ARG_instr3 static_cast<Instruction*>(ARGS[3])
81 #define ARG_instr4 static_cast<Instruction*>(ARGS[4])
82 #define ARG_instr5 static_cast<Instruction*>(ARGS[5])
83 #define ARG_instr6 static_cast<Instruction*>(ARGS[6])
84 #define ARG_returnAddress2 static_cast<void*>(ARGS[2])
85 #define ARG_codeBlock4 static_cast<CodeBlock*>(ARGS[4])
87 #define CTI_RETURN_ADDRESS_SLOT (ARGS[-1])
90 #define FASTCALL __fastcall
92 #define FASTCALL __attribute__ ((fastcall))
94 #error Need to support fastcall calling convention in this compiler
100 class JSPropertyNameIterator;
104 class ScopeChainNode;
105 class SimpleJumpTable;
106 class StringJumpTable;
107 class StructureChain;
112 struct PolymorphicAccessStructureList;
113 struct StructureStubInfo;
115 typedef JSValue* (SFX_CALL *CTIHelper_j)(CTI_ARGS);
116 typedef JSObject* (SFX_CALL *CTIHelper_o)(CTI_ARGS);
117 typedef JSPropertyNameIterator* (SFX_CALL *CTIHelper_p)(CTI_ARGS);
118 typedef void (SFX_CALL *CTIHelper_v)(CTI_ARGS);
119 typedef void* (SFX_CALL *CTIHelper_s)(CTI_ARGS);
120 typedef int (SFX_CALL *CTIHelper_b)(CTI_ARGS);
121 typedef VoidPtrPair (SFX_CALL *CTIHelper_2)(CTI_ARGS);
124 typedef X86Assembler::JmpSrc JmpSrc;
128 unsigned bytecodeIndex;
134 CallRecord(JmpSrc f, CTIHelper_j t, unsigned i)
136 , to(reinterpret_cast<void*>(t))
141 CallRecord(JmpSrc f, CTIHelper_o t, unsigned i)
143 , to(reinterpret_cast<void*>(t))
148 CallRecord(JmpSrc f, CTIHelper_p t, unsigned i)
150 , to(reinterpret_cast<void*>(t))
155 CallRecord(JmpSrc f, CTIHelper_v t, unsigned i)
157 , to(reinterpret_cast<void*>(t))
162 CallRecord(JmpSrc f, CTIHelper_s t, unsigned i)
164 , to(reinterpret_cast<void*>(t))
169 CallRecord(JmpSrc f, CTIHelper_b t, unsigned i)
171 , to(reinterpret_cast<void*>(t))
176 CallRecord(JmpSrc f, CTIHelper_2 t, unsigned i)
178 , to(reinterpret_cast<void*>(t))
183 CallRecord(JmpSrc f, unsigned i)
192 typedef X86Assembler::JmpSrc JmpSrc;
197 JmpTable(JmpSrc f, unsigned t)
204 struct SlowCaseEntry {
205 typedef X86Assembler::JmpSrc JmpSrc;
211 SlowCaseEntry(JmpSrc f, unsigned t, unsigned h = 0)
219 struct SwitchRecord {
229 SimpleJumpTable* simpleJumpTable;
230 StringJumpTable* stringJumpTable;
233 unsigned bytecodeIndex;
234 unsigned defaultOffset;
236 SwitchRecord(SimpleJumpTable* jumpTable, unsigned bytecodeIndex, unsigned defaultOffset, Type type)
238 , bytecodeIndex(bytecodeIndex)
239 , defaultOffset(defaultOffset)
241 this->jumpTable.simpleJumpTable = jumpTable;
244 SwitchRecord(StringJumpTable* jumpTable, unsigned bytecodeIndex, unsigned defaultOffset)
246 , bytecodeIndex(bytecodeIndex)
247 , defaultOffset(defaultOffset)
249 this->jumpTable.stringJumpTable = jumpTable;
253 struct StructureStubCompilationInfo {
254 typedef X86Assembler::JmpSrc JmpSrc;
255 typedef X86Assembler::JmpDst JmpDst;
257 JmpSrc callReturnLocation;
260 JmpDst coldPathOther;
264 JSValue* ctiTrampoline(void* code, RegisterFile*, CallFrame*, JSValue** exception, Profiler**, JSGlobalData*);
265 void ctiVMThrowTrampoline();
268 void ctiSetReturnAddress(void** where, void* what);
269 void ctiRepatchCallByReturnAddress(void* where, void* what);
272 typedef X86Assembler::RegisterID RegisterID;
273 typedef X86Assembler::XMMRegisterID XMMRegisterID;
274 typedef X86Assembler::JmpSrc JmpSrc;
275 typedef X86Assembler::JmpDst JmpDst;
277 static const int repatchGetByIdDefaultStructure = -1;
278 // Magic number - initial offset cannot be representable as a signed 8bit value, or the X86Assembler
279 // will compress the displacement, and we may not be able to fit a repatched offset.
280 static const int repatchGetByIdDefaultOffset = 256;
282 #if USE(FAST_CALL_CTI_ARGUMENT)
283 static const int ctiArgumentInitSize = 2;
284 #elif USE(CTI_ARGUMENT)
285 static const int ctiArgumentInitSize = 4;
287 static const int ctiArgumentInitSize = 0;
289 // These architecture specific value are used to enable repatching - see comment on op_put_by_id.
290 static const int repatchOffsetPutByIdStructure = 7;
291 static const int repatchOffsetPutByIdPropertyMapOffset = 22;
292 // These architecture specific value are used to enable repatching - see comment on op_get_by_id.
293 static const int repatchOffsetGetByIdStructure = 7;
294 static const int repatchOffsetGetByIdBranchToSlowCase = 13;
295 static const int repatchOffsetGetByIdPropertyMapOffset = 22;
296 #if ENABLE(OPCODE_SAMPLING)
297 static const int repatchOffsetGetByIdSlowCaseCall = 27 + 4 + ctiArgumentInitSize;
299 static const int repatchOffsetGetByIdSlowCaseCall = 17 + 4 + ctiArgumentInitSize;
301 static const int repatchOffsetOpCallCall = 6;
304 static void compile(JSGlobalData* globalData, CodeBlock* codeBlock)
306 JIT jit(globalData, codeBlock);
307 jit.privateCompile();
310 static void compileGetByIdSelf(JSGlobalData* globalData, CodeBlock* codeBlock, Structure* structure, size_t cachedOffset, void* returnAddress)
312 JIT jit(globalData, codeBlock);
313 jit.privateCompileGetByIdSelf(structure, cachedOffset, returnAddress);
316 static void compileGetByIdProto(JSGlobalData* globalData, CallFrame* callFrame, CodeBlock* codeBlock, Structure* structure, Structure* prototypeStructure, size_t cachedOffset, void* returnAddress)
318 JIT jit(globalData, codeBlock);
319 jit.privateCompileGetByIdProto(structure, prototypeStructure, cachedOffset, returnAddress, callFrame);
322 #if USE(CTI_REPATCH_PIC)
323 static void compileGetByIdSelfList(JSGlobalData* globalData, CodeBlock* codeBlock, StructureStubInfo* stubInfo, PolymorphicAccessStructureList* polymorphicStructures, int currentIndex, Structure* structure, size_t cachedOffset)
325 JIT jit(globalData, codeBlock);
326 jit.privateCompileGetByIdSelfList(stubInfo, polymorphicStructures, currentIndex, structure, cachedOffset);
328 static void compileGetByIdProtoList(JSGlobalData* globalData, CallFrame* callFrame, CodeBlock* codeBlock, StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructureList, int currentIndex, Structure* structure, Structure* prototypeStructure, size_t cachedOffset)
330 JIT jit(globalData, codeBlock);
331 jit.privateCompileGetByIdProtoList(stubInfo, prototypeStructureList, currentIndex, structure, prototypeStructure, cachedOffset, callFrame);
333 static void compileGetByIdChainList(JSGlobalData* globalData, CallFrame* callFrame, CodeBlock* codeBlock, StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructureList, int currentIndex, Structure* structure, StructureChain* chain, size_t count, size_t cachedOffset)
335 JIT jit(globalData, codeBlock);
336 jit.privateCompileGetByIdChainList(stubInfo, prototypeStructureList, currentIndex, structure, chain, count, cachedOffset, callFrame);
340 static void compileGetByIdChain(JSGlobalData* globalData, CallFrame* callFrame, CodeBlock* codeBlock, Structure* structure, StructureChain* chain, size_t count, size_t cachedOffset, void* returnAddress)
342 JIT jit(globalData, codeBlock);
343 jit.privateCompileGetByIdChain(structure, chain, count, cachedOffset, returnAddress, callFrame);
346 static void compilePutByIdReplace(JSGlobalData* globalData, CodeBlock* codeBlock, Structure* structure, size_t cachedOffset, void* returnAddress)
348 JIT jit(globalData, codeBlock);
349 jit.privateCompilePutByIdReplace(structure, cachedOffset, returnAddress);
352 static void compilePutByIdTransition(JSGlobalData* globalData, CodeBlock* codeBlock, Structure* oldStructure, Structure* newStructure, size_t cachedOffset, StructureChain* chain, void* returnAddress)
354 JIT jit(globalData, codeBlock);
355 jit.privateCompilePutByIdTransition(oldStructure, newStructure, cachedOffset, chain, returnAddress);
358 static void compileCTIMachineTrampolines(JSGlobalData* globalData)
361 jit.privateCompileCTIMachineTrampolines();
363 static void freeCTIMachineTrampolines(Interpreter*);
365 static void patchGetByIdSelf(CodeBlock* codeBlock, Structure* structure, size_t cachedOffset, void* returnAddress);
366 static void patchPutByIdReplace(CodeBlock* codeBlock, Structure* structure, size_t cachedOffset, void* returnAddress);
368 static void compilePatchGetArrayLength(JSGlobalData* globalData, CodeBlock* codeBlock, void* returnAddress)
370 JIT jit(globalData, codeBlock);
371 return jit.privateCompilePatchGetArrayLength(returnAddress);
374 static void linkCall(JSFunction* callee, CodeBlock* calleeCodeBlock, void* ctiCode, CallLinkInfo* callLinkInfo, int callerArgCount);
375 static void unlinkCall(CallLinkInfo*);
377 inline static JSValue* execute(void* code, RegisterFile* registerFile, CallFrame* callFrame, JSGlobalData* globalData, JSValue** exception)
379 return ctiTrampoline(code, registerFile, callFrame, exception, Profiler::enabledProfilerReference(), globalData);
383 JIT(JSGlobalData*, CodeBlock* = 0);
385 void privateCompileMainPass();
386 void privateCompileLinkPass();
387 void privateCompileSlowCases();
388 void privateCompile();
389 void privateCompileGetByIdSelf(Structure*, size_t cachedOffset, void* returnAddress);
390 void privateCompileGetByIdProto(Structure*, Structure* prototypeStructure, size_t cachedOffset, void* returnAddress, CallFrame* callFrame);
391 #if USE(CTI_REPATCH_PIC)
392 void privateCompileGetByIdSelfList(StructureStubInfo*, PolymorphicAccessStructureList*, int, Structure*, size_t cachedOffset);
393 void privateCompileGetByIdProtoList(StructureStubInfo*, PolymorphicAccessStructureList*, int, Structure*, Structure* prototypeStructure, size_t cachedOffset, CallFrame* callFrame);
394 void privateCompileGetByIdChainList(StructureStubInfo*, PolymorphicAccessStructureList*, int, Structure*, StructureChain* chain, size_t count, size_t cachedOffset, CallFrame* callFrame);
396 void privateCompileGetByIdChain(Structure*, StructureChain*, size_t count, size_t cachedOffset, void* returnAddress, CallFrame* callFrame);
397 void privateCompilePutByIdReplace(Structure*, size_t cachedOffset, void* returnAddress);
398 void privateCompilePutByIdTransition(Structure*, Structure*, size_t cachedOffset, StructureChain*, void* returnAddress);
400 void privateCompileCTIMachineTrampolines();
401 void privateCompilePatchGetArrayLength(void* returnAddress);
403 void compileOpCall(OpcodeID, Instruction* instruction, unsigned i, unsigned callLinkInfoIndex);
404 void compileOpCallInitializeCallFrame();
405 void compileOpCallSetupArgs(Instruction*);
406 void compileOpCallEvalSetupArgs(Instruction*);
407 void compileOpConstructSetupArgs(Instruction*);
408 enum CompileOpStrictEqType { OpStrictEq, OpNStrictEq };
409 void compileOpStrictEq(Instruction* instruction, unsigned i, CompileOpStrictEqType type);
410 void putDoubleResultToJSNumberCellOrJSImmediate(XMMRegisterID xmmSource, RegisterID jsNumberCell, unsigned dst, JmpSrc* wroteJSNumberCell, XMMRegisterID tempXmm, RegisterID tempReg1, RegisterID tempReg2);
411 void compileBinaryArithOp(OpcodeID, unsigned dst, unsigned src1, unsigned src2, OperandTypes opi, unsigned i);
412 void compileBinaryArithOpSlowCase(OpcodeID, Vector<SlowCaseEntry>::iterator& iter, unsigned dst, unsigned src1, unsigned src2, OperandTypes opi, unsigned i);
414 void emitGetVirtualRegister(int src, RegisterID dst, unsigned i);
415 void emitGetVirtualRegisters(int src1, RegisterID dst1, int src2, RegisterID dst2, unsigned i);
416 void emitPutVirtualRegister(unsigned dst, RegisterID from = X86::eax);
418 void emitPutCTIArg(RegisterID src, unsigned offset);
419 void emitPutCTIArgFromVirtualRegister(unsigned src, unsigned offset, RegisterID scratch);
420 void emitPutCTIArgConstant(unsigned value, unsigned offset);
421 void emitGetCTIArg(unsigned offset, RegisterID dst);
423 void emitInitRegister(unsigned dst);
425 void emitPutCTIParam(void* value, unsigned name);
426 void emitPutCTIParam(RegisterID from, unsigned name);
427 void emitGetCTIParam(unsigned name, RegisterID to);
429 void emitPutToCallFrameHeader(RegisterID from, RegisterFile::CallFrameHeaderEntry entry);
430 void emitGetFromCallFrameHeader(RegisterFile::CallFrameHeaderEntry entry, RegisterID to);
432 JSValue* getConstantImmediateNumericArg(unsigned src);
433 unsigned getDeTaggedConstantImmediate(JSValue* imm);
435 bool linkSlowCaseIfNotJSCell(const Vector<SlowCaseEntry>::iterator&, int vReg);
436 void emitJumpSlowCaseIfNotJSCell(RegisterID, unsigned bytecodeIndex);
437 void emitJumpSlowCaseIfNotJSCell(RegisterID, unsigned bytecodeIndex, int VReg);
439 void emitJumpSlowCaseIfNotImmNum(RegisterID, unsigned bytecodeIndex);
440 void emitJumpSlowCaseIfNotImmNums(RegisterID, RegisterID, unsigned bytecodeIndex);
442 JmpSrc checkStructure(RegisterID reg, Structure* structure);
444 void emitFastArithDeTagImmediate(RegisterID);
445 JmpSrc emitFastArithDeTagImmediateJumpIfZero(RegisterID);
446 void emitFastArithReTagImmediate(RegisterID);
447 void emitFastArithPotentiallyReTagImmediate(RegisterID);
448 void emitFastArithImmToInt(RegisterID);
449 void emitFastArithIntToImmOrSlowCase(RegisterID, unsigned bytecodeIndex);
450 void emitFastArithIntToImmNoCheck(RegisterID);
451 JmpSrc emitArithIntToImmWithJump(RegisterID reg);
453 void emitTagAsBoolImmediate(RegisterID reg);
455 void emitAllocateNumber(JSGlobalData*, unsigned);
457 JmpSrc emitNakedCall(unsigned bytecodeIndex, RegisterID);
458 JmpSrc emitNakedCall(unsigned bytecodeIndex, void* function);
459 JmpSrc emitNakedFastCall(unsigned bytecodeIndex, void*);
460 JmpSrc emitCTICall(unsigned bytecodeIndex, CTIHelper_j);
461 JmpSrc emitCTICall(unsigned bytecodeIndex, CTIHelper_o);
462 JmpSrc emitCTICall(unsigned bytecodeIndex, CTIHelper_p);
463 JmpSrc emitCTICall(unsigned bytecodeIndex, CTIHelper_v);
464 JmpSrc emitCTICall(unsigned bytecodeIndex, CTIHelper_s);
465 JmpSrc emitCTICall(unsigned bytecodeIndex, CTIHelper_b);
466 JmpSrc emitCTICall(unsigned bytecodeIndex, CTIHelper_2);
468 void emitGetVariableObjectRegister(RegisterID variableObject, int index, RegisterID dst);
469 void emitPutVariableObjectRegister(RegisterID src, RegisterID variableObject, int index);
471 void emitSlowScriptCheck(unsigned bytecodeIndex);
473 void printBytecodeOperandTypes(unsigned src1, unsigned src2);
476 void killLastResultRegister();
478 X86Assembler m_assembler;
479 Interpreter* m_interpreter;
480 JSGlobalData* m_globalData;
481 CodeBlock* m_codeBlock;
483 Vector<CallRecord> m_calls;
484 Vector<JmpDst> m_labels;
485 Vector<StructureStubCompilationInfo> m_propertyAccessCompilationInfo;
486 Vector<StructureStubCompilationInfo> m_callStructureStubCompilationInfo;
487 Vector<JmpTable> m_jmpTable;
493 JSRInfo(const JmpDst& storeLocation, const JmpDst& targetLocation)
494 : addrPosition(storeLocation)
495 , target(targetLocation)
500 Vector<JSRInfo> m_jsrSites;
501 Vector<SlowCaseEntry> m_slowCases;
502 Vector<SwitchRecord> m_switches;
504 int m_lastResultBytecodeRegister;
505 unsigned m_jumpTargetsPosition;
509 #endif // ENABLE(JIT)