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.
31 #define WTF_USE_CTI_REPATCH_PIC 1
34 #include "RegisterFile.h"
35 #include <masm/X86Assembler.h>
36 #include <profiler/Profiler.h>
37 #include <wtf/AlwaysInline.h>
38 #include <wtf/Vector.h>
41 #define CTI_ARGS void** args
44 #define CTI_ARGS void* args
48 #define CTI_ARGS_code 0x0C
49 #define CTI_ARGS_registerFile 0x0D
50 #define CTI_ARGS_r 0x0E
51 #define CTI_ARGS_exception 0x0F
52 #define CTI_ARGS_profilerReference 0x10
53 #define CTI_ARGS_globalData 0x11
54 #define ARG_registerFile ((RegisterFile*)(ARGS)[CTI_ARGS_registerFile])
55 #define ARG_r ((Register*)(ARGS)[CTI_ARGS_r])
56 #define ARG_exception ((JSValue**)(ARGS)[CTI_ARGS_exception])
57 #define ARG_profilerReference ((Profiler**)(ARGS)[CTI_ARGS_profilerReference])
58 #define ARG_globalData ((JSGlobalData*)(ARGS)[CTI_ARGS_globalData])
60 #define ARG_exec CallFrame::create(ARG_r)
62 #define ARG_setR(newR) (*(Register**)&(ARGS)[CTI_ARGS_r] = newR)
64 #define ARG_src1 ((JSValue*)((ARGS)[1]))
65 #define ARG_src2 ((JSValue*)((ARGS)[2]))
66 #define ARG_src3 ((JSValue*)((ARGS)[3]))
67 #define ARG_src4 ((JSValue*)((ARGS)[4]))
68 #define ARG_src5 ((JSValue*)((ARGS)[5]))
69 #define ARG_id1 ((Identifier*)((ARGS)[1]))
70 #define ARG_id2 ((Identifier*)((ARGS)[2]))
71 #define ARG_id3 ((Identifier*)((ARGS)[3]))
72 #define ARG_id4 ((Identifier*)((ARGS)[4]))
73 #define ARG_int1 ((int)((ARGS)[1]))
74 #define ARG_int2 ((int)((ARGS)[2]))
75 #define ARG_int3 ((int)((ARGS)[3]))
76 #define ARG_int4 ((int)((ARGS)[4]))
77 #define ARG_int5 ((int)((ARGS)[5]))
78 #define ARG_func1 ((FuncDeclNode*)((ARGS)[1]))
79 #define ARG_funcexp1 ((FuncExprNode*)((ARGS)[1]))
80 #define ARG_registers1 ((Register*)((ARGS)[1]))
81 #define ARG_regexp1 ((RegExp*)((ARGS)[1]))
82 #define ARG_pni1 ((JSPropertyNameIterator*)((ARGS)[1]))
83 #define ARG_instr1 ((Instruction*)((ARGS)[1]))
84 #define ARG_instr2 ((Instruction*)((ARGS)[2]))
85 #define ARG_instr3 ((Instruction*)((ARGS)[3]))
86 #define ARG_instr4 ((Instruction*)((ARGS)[4]))
87 #define ARG_instr5 ((Instruction*)((ARGS)[5]))
88 #define ARG_instr6 ((Instruction*)((ARGS)[6]))
90 #define CTI_RETURN_ADDRESS ((ARGS)[-1])
96 class JSPropertyNameIterator;
101 class ScopeChainNode;
102 class SimpleJumpTable;
103 class StringJumpTable;
104 class StructureIDChain;
108 struct VoidPtrPair { void* first; void* second; };
112 #if USE(FAST_CALL_CTI_ARGUMENT)
113 #define SFX_CALL __fastcall
115 #define SFX_CALL __cdecl
122 typedef JSValue* (SFX_CALL *CTIHelper_j)(CTI_ARGS);
123 typedef JSPropertyNameIterator* (SFX_CALL *CTIHelper_p)(CTI_ARGS);
124 typedef void (SFX_CALL *CTIHelper_v)(CTI_ARGS);
125 typedef void* (SFX_CALL *CTIHelper_s)(CTI_ARGS);
126 typedef int (SFX_CALL *CTIHelper_b)(CTI_ARGS);
127 typedef VoidPtrPair (SFX_CALL *CTIHelper_2)(CTI_ARGS);
130 X86Assembler::JmpSrc from;
132 unsigned opcodeIndex;
138 CallRecord(X86Assembler::JmpSrc f, CTIHelper_j t, unsigned i)
145 CallRecord(X86Assembler::JmpSrc f, CTIHelper_p t, unsigned i)
152 CallRecord(X86Assembler::JmpSrc f, CTIHelper_v t, unsigned i)
159 CallRecord(X86Assembler::JmpSrc f, CTIHelper_s t, unsigned i)
166 CallRecord(X86Assembler::JmpSrc f, CTIHelper_b t, unsigned i)
173 CallRecord(X86Assembler::JmpSrc f, CTIHelper_2 t, unsigned i)
180 CallRecord(X86Assembler::JmpSrc f, unsigned i)
189 X86Assembler::JmpSrc from;
192 JmpTable(X86Assembler::JmpSrc f, unsigned t)
199 struct SlowCaseEntry {
200 X86Assembler::JmpSrc from;
204 SlowCaseEntry(X86Assembler::JmpSrc f, unsigned t, unsigned h = 0)
212 struct SwitchRecord {
222 SimpleJumpTable* m_simpleJumpTable;
223 StringJumpTable* m_stringJumpTable;
226 unsigned m_opcodeIndex;
227 unsigned m_defaultOffset;
229 SwitchRecord(SimpleJumpTable* jumpTable, unsigned opcodeIndex, unsigned defaultOffset, Type type)
231 , m_opcodeIndex(opcodeIndex)
232 , m_defaultOffset(defaultOffset)
234 m_jumpTable.m_simpleJumpTable = jumpTable;
237 SwitchRecord(StringJumpTable* jumpTable, unsigned opcodeIndex, unsigned defaultOffset)
239 , m_opcodeIndex(opcodeIndex)
240 , m_defaultOffset(defaultOffset)
242 m_jumpTable.m_stringJumpTable = jumpTable;
246 struct StructureStubCompilationInfo {
247 X86Assembler::JmpSrc callReturnLocation;
248 X86Assembler::JmpDst hotPathBegin;
252 JSValue* ctiTrampoline(void* code, RegisterFile*, Register* callFrame, JSValue** exception, Profiler**, JSGlobalData*);
253 void ctiVMThrowTrampoline();
256 void ctiSetReturnAddress(void** where, void* what);
257 void ctiRepatchCallByReturnAddress(void* where, void* what);
260 static const int repatchGetByIdDefaultStructureID = -1;
261 // Magic number - initial offset cannot be representable as a signed 8bit value, or the X86Assembler
262 // will compress the displacement, and we may not be able to fit a repatched offset.
263 static const int repatchGetByIdDefaultOffset = 256;
265 #if USE(FAST_CALL_CTI_ARGUMENT)
266 static const int ctiArgumentInitSize = 2;
267 #elif USE(CTI_ARGUMENT)
268 static const int ctiArgumentInitSize = 4;
270 static const int ctiArgumentInitSize = 0;
272 // These architecture specific value are used to enable repatching - see comment on op_put_by_id.
273 static const int repatchOffsetPutByIdStructureID = 19;
274 static const int repatchOffsetPutByIdPropertyMapOffset = 34;
275 // These architecture specific value are used to enable repatching - see comment on op_get_by_id.
276 static const int repatchOffsetGetByIdStructureID = 19;
277 static const int repatchOffsetGetByIdBranchToSlowCase = 25;
278 static const int repatchOffsetGetByIdPropertyMapOffset = 34;
279 #if ENABLE(SAMPLING_TOOL)
280 static const int repatchOffsetGetByIdSlowCaseCall = 27 + ctiArgumentInitSize;
282 static const int repatchOffsetGetByIdSlowCaseCall = 17 + ctiArgumentInitSize;
286 static void compile(Machine* machine, ExecState* exec, CodeBlock* codeBlock)
288 CTI cti(machine, exec, codeBlock);
289 cti.privateCompile();
293 static void* compileRegExp(ExecState* exec, const UString& pattern, unsigned* numSubpatterns_ptr, const char** error_ptr, bool ignoreCase = false, bool multiline = false);
296 static void compileGetByIdSelf(Machine* machine, ExecState* exec, CodeBlock* codeBlock, StructureID* structureID, size_t cachedOffset, void* returnAddress)
298 CTI cti(machine, exec, codeBlock);
299 cti.privateCompileGetByIdSelf(structureID, cachedOffset, returnAddress);
302 static void compileGetByIdProto(Machine* machine, ExecState* exec, CodeBlock* codeBlock, StructureID* structureID, StructureID* prototypeStructureID, size_t cachedOffset, void* returnAddress)
304 CTI cti(machine, exec, codeBlock);
305 cti.privateCompileGetByIdProto(structureID, prototypeStructureID, cachedOffset, returnAddress);
308 static void compileGetByIdChain(Machine* machine, ExecState* exec, CodeBlock* codeBlock, StructureID* structureID, StructureIDChain* chain, size_t count, size_t cachedOffset, void* returnAddress)
310 CTI cti(machine, exec, codeBlock);
311 cti.privateCompileGetByIdChain(structureID, chain, count, cachedOffset, returnAddress);
314 static void compilePutByIdReplace(Machine* machine, ExecState* exec, CodeBlock* codeBlock, StructureID* structureID, size_t cachedOffset, void* returnAddress)
316 CTI cti(machine, exec, codeBlock);
317 cti.privateCompilePutByIdReplace(structureID, cachedOffset, returnAddress);
320 static void compilePutByIdTransition(Machine* machine, ExecState* exec, CodeBlock* codeBlock, StructureID* oldStructureID, StructureID* newStructureID, size_t cachedOffset, StructureIDChain* sIDC, void* returnAddress)
322 CTI cti(machine, exec, codeBlock);
323 cti.privateCompilePutByIdTransition(oldStructureID, newStructureID, cachedOffset, sIDC, returnAddress);
326 static void* compileArrayLengthTrampoline(Machine* machine, ExecState* exec, CodeBlock* codeBlock)
328 CTI cti(machine, exec, codeBlock);
329 return cti.privateCompileArrayLengthTrampoline();
332 static void* compileStringLengthTrampoline(Machine* machine, ExecState* exec, CodeBlock* codeBlock)
334 CTI cti(machine, exec, codeBlock);
335 return cti.privateCompileStringLengthTrampoline();
338 static void patchGetByIdSelf(CodeBlock* codeBlock, StructureID* structureID, size_t cachedOffset, void* returnAddress);
339 static void patchPutByIdReplace(CodeBlock* codeBlock, StructureID* structureID, size_t cachedOffset, void* returnAddress);
341 static void compilePatchGetArrayLength(Machine* machine, ExecState* exec, CodeBlock* codeBlock, void* returnAddress)
343 CTI cti(machine, exec, codeBlock);
344 return cti.privateCompilePatchGetArrayLength(returnAddress);
347 inline static JSValue* execute(void* code, RegisterFile* registerFile, Register* r, JSGlobalData* globalData, JSValue** exception)
349 return ctiTrampoline(code, registerFile, r, exception, Profiler::enabledProfilerReference(), globalData);
353 CTI(Machine*, ExecState*, CodeBlock*);
355 bool isConstant(int src);
356 JSValue* getConstant(ExecState*, int src);
358 void privateCompileMainPass();
359 void privateCompileLinkPass();
360 void privateCompileSlowCases();
361 void privateCompile();
362 void privateCompileGetByIdSelf(StructureID*, size_t cachedOffset, void* returnAddress);
363 void privateCompileGetByIdProto(StructureID*, StructureID* prototypeStructureID, size_t cachedOffset, void* returnAddress);
364 void privateCompileGetByIdChain(StructureID*, StructureIDChain*, size_t count, size_t cachedOffset, void* returnAddress);
365 void privateCompilePutByIdReplace(StructureID*, size_t cachedOffset, void* returnAddress);
366 void privateCompilePutByIdTransition(StructureID*, StructureID*, size_t cachedOffset, StructureIDChain*, void* returnAddress);
368 void* privateCompileArrayLengthTrampoline();
369 void* privateCompileStringLengthTrampoline();
370 void privateCompilePatchGetArrayLength(void* returnAddress);
372 enum CompileOpCallType { OpCallNormal, OpCallEval, OpConstruct };
373 void compileOpCall(Instruction* instruction, unsigned i, CompileOpCallType type = OpCallNormal);
374 void compileOpCallInitializeCallFrame(unsigned callee, unsigned argCount);
375 enum CompileOpStrictEqType { OpStrictEq, OpNStrictEq };
376 void compileOpStrictEq(Instruction* instruction, unsigned i, CompileOpStrictEqType type);
377 void putDoubleResultToJSNumberCellOrJSImmediate(X86::XMMRegisterID xmmSource, X86::RegisterID jsNumberCell, unsigned dst, X86Assembler::JmpSrc* wroteJSNumberCell, X86::XMMRegisterID tempXmm, X86::RegisterID tempReg1, X86::RegisterID tempReg2);
378 void compileBinaryArithOp(OpcodeID, unsigned dst, unsigned src1, unsigned src2, OperandTypes opi, unsigned i);
379 void compileBinaryArithOpSlowCase(OpcodeID, Vector<SlowCaseEntry>::iterator& iter, unsigned dst, unsigned src1, unsigned src2, OperandTypes opi, unsigned i);
381 void emitGetArg(int src, X86Assembler::RegisterID dst);
382 void emitGetPutArg(unsigned src, unsigned offset, X86Assembler::RegisterID scratch);
383 void emitPutArg(X86Assembler::RegisterID src, unsigned offset);
384 void emitPutArgConstant(unsigned value, unsigned offset);
385 void emitPutResult(unsigned dst, X86Assembler::RegisterID from = X86::eax);
387 void emitInitRegister(unsigned dst);
389 void emitPutCTIParam(void* value, unsigned name);
390 void emitPutCTIParam(X86Assembler::RegisterID from, unsigned name);
391 void emitGetCTIParam(unsigned name, X86Assembler::RegisterID to);
393 void emitPutToCallFrameHeader(X86Assembler::RegisterID from, RegisterFile::CallFrameHeaderEntry entry);
394 void emitGetFromCallFrameHeader(RegisterFile::CallFrameHeaderEntry entry, X86Assembler::RegisterID to);
396 JSValue* getConstantImmediateNumericArg(unsigned src);
397 unsigned getDeTaggedConstantImmediate(JSValue* imm);
399 void emitJumpSlowCaseIfIsJSCell(X86Assembler::RegisterID reg, unsigned opcodeIndex);
400 void emitJumpSlowCaseIfNotJSCell(X86Assembler::RegisterID reg, unsigned opcodeIndex);
402 void emitJumpSlowCaseIfNotImmNum(X86Assembler::RegisterID, unsigned opcodeIndex);
403 void emitJumpSlowCaseIfNotImmNums(X86Assembler::RegisterID, X86Assembler::RegisterID, unsigned opcodeIndex);
405 void emitFastArithDeTagImmediate(X86Assembler::RegisterID);
406 void emitFastArithReTagImmediate(X86Assembler::RegisterID);
407 void emitFastArithPotentiallyReTagImmediate(X86Assembler::RegisterID);
408 void emitFastArithImmToInt(X86Assembler::RegisterID);
409 void emitFastArithIntToImmOrSlowCase(X86Assembler::RegisterID, unsigned opcodeIndex);
410 void emitFastArithIntToImmNoCheck(X86Assembler::RegisterID);
412 void emitTagAsBoolImmediate(X86Assembler::RegisterID reg);
414 X86Assembler::JmpSrc emitCall(unsigned opcodeIndex, X86::RegisterID);
415 X86Assembler::JmpSrc emitCall(unsigned opcodeIndex, CTIHelper_j);
416 X86Assembler::JmpSrc emitCall(unsigned opcodeIndex, CTIHelper_p);
417 X86Assembler::JmpSrc emitCall(unsigned opcodeIndex, CTIHelper_v);
418 X86Assembler::JmpSrc emitCall(unsigned opcodeIndex, CTIHelper_s);
419 X86Assembler::JmpSrc emitCall(unsigned opcodeIndex, CTIHelper_b);
420 X86Assembler::JmpSrc emitCall(unsigned opcodeIndex, CTIHelper_2);
422 void emitGetVariableObjectRegister(X86Assembler::RegisterID variableObject, int index, X86Assembler::RegisterID dst);
423 void emitPutVariableObjectRegister(X86Assembler::RegisterID src, X86Assembler::RegisterID variableObject, int index);
425 void emitSlowScriptCheck(unsigned opcodeIndex);
427 void printOpcodeOperandTypes(unsigned src1, unsigned src2);
433 CodeBlock* m_codeBlock;
435 Vector<CallRecord> m_calls;
436 Vector<X86Assembler::JmpDst> m_labels;
437 Vector<StructureStubCompilationInfo> m_structureStubCompilationInfo;
438 Vector<JmpTable> m_jmpTable;
441 X86Assembler::JmpDst addrPosition;
442 X86Assembler::JmpDst target;
444 JSRInfo(const X86Assembler::JmpDst& storeLocation, const X86Assembler::JmpDst& targetLocation)
445 : addrPosition(storeLocation)
446 , target(targetLocation)
451 Vector<JSRInfo> m_jsrSites;
452 Vector<SlowCaseEntry> m_slowCases;
453 Vector<SwitchRecord> m_switches;
455 // This limit comes from the limit set in PCRE
456 static const int MaxPatternSize = (1 << 16);
461 #endif // ENABLE(CTI)