source: webkit/trunk/JavaScriptCore/jit/JIT.cpp@ 39061

Last change on this file since 39061 was 39061, checked in by [email protected], 16 years ago

2008-12-05 Gavin Barraclough <[email protected]>

Reviewed by Oliver Hunt.

Ordering of branch operands in MacroAssembler in unnecessarily inconsistent.

je, jg etc take an immediate operand as the second argument, but for the
equality branches (je, jne) the immediate operand was the first argument. This
was unnecessarily inconsistent. Change je, jne methods to take the immediate
as the second argument.

https://bugs.webkit.org/show_bug.cgi?id=22703

  • assembler/MacroAssembler.h: (JSC::MacroAssembler::je32): (JSC::MacroAssembler::jne32):
  • jit/JIT.cpp: (JSC::JIT::compileOpStrictEq):
  • wrec/WRECGenerator.cpp: (JSC::WREC::Generator::generateEnter): (JSC::WREC::Generator::generateNonGreedyQuantifier): (JSC::WREC::Generator::generateGreedyQuantifier): (JSC::WREC::Generator::generatePatternCharacterPair): (JSC::WREC::Generator::generatePatternCharacter): (JSC::WREC::Generator::generateCharacterClassInvertedRange): (JSC::WREC::Generator::generateCharacterClassInverted): (JSC::WREC::Generator::generateAssertionBOL): (JSC::WREC::Generator::generateAssertionWordBoundary):
File size: 95.4 KB
Line 
1/*
2 * Copyright (C) 2008 Apple Inc. All rights reserved.
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
26#include "config.h"
27#include "JIT.h"
28
29#if ENABLE(JIT)
30
31#include "CodeBlock.h"
32#include "JITInlineMethods.h"
33#include "JSArray.h"
34#include "JSFunction.h"
35#include "Interpreter.h"
36#include "ResultType.h"
37#include "SamplingTool.h"
38
39#ifndef NDEBUG
40#include <stdio.h>
41#endif
42
43using namespace std;
44
45namespace JSC {
46
47COMPILE_ASSERT(CTI_ARGS_code == 0xC, CTI_ARGS_code_is_C);
48COMPILE_ASSERT(CTI_ARGS_callFrame == 0xE, CTI_ARGS_callFrame_is_E);
49
50#if COMPILER(GCC) && PLATFORM(X86)
51
52#if PLATFORM(DARWIN)
53#define SYMBOL_STRING(name) "_" #name
54#else
55#define SYMBOL_STRING(name) #name
56#endif
57
58asm(
59".globl " SYMBOL_STRING(ctiTrampoline) "\n"
60SYMBOL_STRING(ctiTrampoline) ":" "\n"
61 "pushl %esi" "\n"
62 "pushl %edi" "\n"
63 "pushl %ebx" "\n"
64 "subl $0x20, %esp" "\n"
65 "movl $512, %esi" "\n"
66 "movl 0x38(%esp), %edi" "\n" // Ox38 = 0x0E * 4, 0x0E = CTI_ARGS_callFrame (see assertion above)
67 "call *0x30(%esp)" "\n" // Ox30 = 0x0C * 4, 0x0C = CTI_ARGS_code (see assertion above)
68 "addl $0x20, %esp" "\n"
69 "popl %ebx" "\n"
70 "popl %edi" "\n"
71 "popl %esi" "\n"
72 "ret" "\n"
73);
74
75asm(
76".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
77SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
78#if USE(CTI_ARGUMENT)
79#if USE(FAST_CALL_CTI_ARGUMENT)
80 "movl %esp, %ecx" "\n"
81#else
82 "movl %esp, 0(%esp)" "\n"
83#endif
84 "call " SYMBOL_STRING(_ZN3JSC11Interpreter12cti_vm_throwEPPv) "\n"
85#else
86 "call " SYMBOL_STRING(_ZN3JSC11Interpreter12cti_vm_throwEPvz) "\n"
87#endif
88 "addl $0x20, %esp" "\n"
89 "popl %ebx" "\n"
90 "popl %edi" "\n"
91 "popl %esi" "\n"
92 "ret" "\n"
93);
94
95#elif COMPILER(MSVC)
96
97extern "C" {
98
99 __declspec(naked) JSValue* ctiTrampoline(void* code, RegisterFile*, CallFrame*, JSValue** exception, Profiler**, JSGlobalData*)
100 {
101 __asm {
102 push esi;
103 push edi;
104 push ebx;
105 sub esp, 0x20;
106 mov esi, 512;
107 mov ecx, esp;
108 mov edi, [esp + 0x38];
109 call [esp + 0x30]; // Ox30 = 0x0C * 4, 0x0C = CTI_ARGS_code (see assertion above)
110 add esp, 0x20;
111 pop ebx;
112 pop edi;
113 pop esi;
114 ret;
115 }
116 }
117
118 __declspec(naked) void ctiVMThrowTrampoline()
119 {
120 __asm {
121 mov ecx, esp;
122 call JSC::Interpreter::cti_vm_throw;
123 add esp, 0x20;
124 pop ebx;
125 pop edi;
126 pop esi;
127 ret;
128 }
129 }
130
131}
132
133#endif
134
135void ctiSetReturnAddress(void** where, void* what)
136{
137 *where = what;
138}
139
140void ctiRepatchCallByReturnAddress(void* where, void* what)
141{
142 (static_cast<void**>(where))[-1] = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(what) - reinterpret_cast<uintptr_t>(where));
143}
144
145#ifndef NDEBUG
146
147void JIT::printBytecodeOperandTypes(unsigned src1, unsigned src2)
148{
149 char which1 = '*';
150 if (m_codeBlock->isConstantRegisterIndex(src1)) {
151 JSValue* value = m_codeBlock->getConstant(src1);
152 which1 =
153 JSImmediate::isImmediate(value) ?
154 (JSImmediate::isNumber(value) ? 'i' :
155 JSImmediate::isBoolean(value) ? 'b' :
156 value->isUndefined() ? 'u' :
157 value->isNull() ? 'n' : '?')
158 :
159 (value->isString() ? 's' :
160 value->isObject() ? 'o' :
161 'k');
162 }
163 char which2 = '*';
164 if (m_codeBlock->isConstantRegisterIndex(src2)) {
165 JSValue* value = m_codeBlock->getConstant(src2);
166 which2 =
167 JSImmediate::isImmediate(value) ?
168 (JSImmediate::isNumber(value) ? 'i' :
169 JSImmediate::isBoolean(value) ? 'b' :
170 value->isUndefined() ? 'u' :
171 value->isNull() ? 'n' : '?')
172 :
173 (value->isString() ? 's' :
174 value->isObject() ? 'o' :
175 'k');
176 }
177 if ((which1 != '*') | (which2 != '*'))
178 fprintf(stderr, "Types %c %c\n", which1, which2);
179}
180
181#endif
182
183JIT::JIT(JSGlobalData* globalData, CodeBlock* codeBlock)
184 : m_interpreter(globalData->interpreter)
185 , m_globalData(globalData)
186 , m_codeBlock(codeBlock)
187 , m_labels(codeBlock ? codeBlock->instructions.size() : 0)
188 , m_propertyAccessCompilationInfo(codeBlock ? codeBlock->propertyAccessInstructions.size() : 0)
189 , m_callStructureStubCompilationInfo(codeBlock ? codeBlock->callLinkInfos.size() : 0)
190 , m_lastResultBytecodeRegister(std::numeric_limits<int>::max())
191 , m_jumpTargetsPosition(0)
192{
193}
194
195#define CTI_COMPILE_BINARY_OP(name) \
196 case name: { \
197 emitPutCTIArgFromVirtualRegister(instruction[i + 2].u.operand, 0, X86::ecx); \
198 emitPutCTIArgFromVirtualRegister(instruction[i + 3].u.operand, 4, X86::ecx); \
199 emitCTICall(i, Interpreter::cti_##name); \
200 emitPutVirtualRegister(instruction[i + 1].u.operand); \
201 i += 4; \
202 break; \
203 }
204
205#define CTI_COMPILE_UNARY_OP(name) \
206 case name: { \
207 emitPutCTIArgFromVirtualRegister(instruction[i + 2].u.operand, 0, X86::ecx); \
208 emitCTICall(i, Interpreter::cti_##name); \
209 emitPutVirtualRegister(instruction[i + 1].u.operand); \
210 i += 3; \
211 break; \
212 }
213
214void JIT::compileOpStrictEq(Instruction* instruction, unsigned i, CompileOpStrictEqType type)
215{
216 bool negated = (type == OpNStrictEq);
217
218 unsigned dst = instruction[1].u.operand;
219 unsigned src1 = instruction[2].u.operand;
220 unsigned src2 = instruction[3].u.operand;
221
222 emitGetVirtualRegisters(src1, X86::eax, src2, X86::edx, i);
223
224 // Check that bot are immediates, if so check if they're equal
225 Jump firstNotImmediate = emitJumpIfJSCell(X86::eax);
226 Jump secondNotImmediate = emitJumpIfJSCell(X86::edx);
227 Jump bothWereImmediatesButNotEqual = jne32(X86::edx, X86::eax);
228
229 // They are equal - set the result to true. (Or false, if negated).
230 move(Imm32(asInteger(jsBoolean(!negated))), X86::eax);
231 Jump bothWereImmediatesAndEqual = jump();
232
233 // eax was not an immediate, we haven't yet checked edx.
234 // If edx is also a JSCell, or is 0, then jump to a slow case,
235 // otherwise these values are not equal.
236 firstNotImmediate.link(this);
237 emitJumpSlowCaseIfJSCell(X86::edx, i);
238 m_slowCases.append(SlowCaseEntry(je32(X86::edx, Imm32(asInteger(JSImmediate::zeroImmediate()))), i));
239 Jump firstWasNotImmediate = jump();
240
241 // eax was an immediate, but edx wasn't.
242 // If eax is 0 jump to a slow case, otherwise these values are not equal.
243 secondNotImmediate.link(this);
244 m_slowCases.append(SlowCaseEntry(je32(X86::eax, Imm32(asInteger(JSImmediate::zeroImmediate()))), i));
245
246 // We get here if the two values are different immediates, or one is 0 and the other is a JSCell.
247 // Vaelues are not equal, set the result to false.
248 bothWereImmediatesButNotEqual.link(this);
249 firstWasNotImmediate.link(this);
250 move(Imm32(asInteger(jsBoolean(negated))), X86::eax);
251
252 bothWereImmediatesAndEqual.link(this);
253 emitPutVirtualRegister(dst);
254}
255
256void JIT::emitSlowScriptCheck(unsigned bytecodeIndex)
257{
258 Jump skipTimeout = jnzSub32(Imm32(1), X86::esi);
259 emitCTICall(bytecodeIndex, Interpreter::cti_timeout_check);
260 move(X86::eax, X86::esi);
261 skipTimeout.link(this);
262
263 killLastResultRegister();
264}
265
266void JIT::privateCompileMainPass()
267{
268 Instruction* instruction = m_codeBlock->instructions.begin();
269 unsigned instructionCount = m_codeBlock->instructions.size();
270
271 unsigned propertyAccessInstructionIndex = 0;
272 unsigned callLinkInfoIndex = 0;
273
274 for (unsigned i = 0; i < instructionCount; ) {
275 ASSERT_WITH_MESSAGE(m_interpreter->isOpcode(instruction[i].u.opcode), "privateCompileMainPass gone bad @ %d", i);
276
277#if ENABLE(OPCODE_SAMPLING)
278 if (i > 0) // Avoid the overhead of sampling op_enter twice.
279 store32(m_interpreter->sampler()->encodeSample(instruction + i), m_interpreter->sampler()->sampleSlot());
280#endif
281
282 m_labels[i] = __ label();
283 OpcodeID opcodeID = m_interpreter->getOpcodeID(instruction[i].u.opcode);
284 switch (opcodeID) {
285 case op_mov: {
286 emitGetVirtualRegister(instruction[i + 2].u.operand, X86::eax, i);
287 emitPutVirtualRegister(instruction[i + 1].u.operand);
288 i += 3;
289 break;
290 }
291 case op_add: {
292 unsigned dst = instruction[i + 1].u.operand;
293 unsigned src1 = instruction[i + 2].u.operand;
294 unsigned src2 = instruction[i + 3].u.operand;
295
296 if (JSValue* value = getConstantImmediateNumericArg(src1)) {
297 emitGetVirtualRegister(src2, X86::eax, i);
298 emitJumpSlowCaseIfNotImmNum(X86::eax, i);
299 m_slowCases.append(SlowCaseEntry(joAdd32(Imm32(getDeTaggedConstantImmediate(value)), X86::eax), i));
300 emitPutVirtualRegister(dst);
301 } else if (JSValue* value = getConstantImmediateNumericArg(src2)) {
302 emitGetVirtualRegister(src1, X86::eax, i);
303 emitJumpSlowCaseIfNotImmNum(X86::eax, i);
304 m_slowCases.append(SlowCaseEntry(joAdd32(Imm32(getDeTaggedConstantImmediate(value)), X86::eax), i));
305 emitPutVirtualRegister(dst);
306 } else {
307 OperandTypes types = OperandTypes::fromInt(instruction[i + 4].u.operand);
308 if (types.first().mightBeNumber() && types.second().mightBeNumber())
309 compileBinaryArithOp(op_add, instruction[i + 1].u.operand, instruction[i + 2].u.operand, instruction[i + 3].u.operand, OperandTypes::fromInt(instruction[i + 4].u.operand), i);
310 else {
311 emitPutCTIArgFromVirtualRegister(instruction[i + 2].u.operand, 0, X86::ecx);
312 emitPutCTIArgFromVirtualRegister(instruction[i + 3].u.operand, 4, X86::ecx);
313 emitCTICall(i, Interpreter::cti_op_add);
314 emitPutVirtualRegister(instruction[i + 1].u.operand);
315 }
316 }
317
318 i += 5;
319 break;
320 }
321 case op_end: {
322 if (m_codeBlock->needsFullScopeChain)
323 emitCTICall(i, Interpreter::cti_op_end);
324 emitGetVirtualRegister(instruction[i + 1].u.operand, X86::eax, i);
325 __ pushl_m(RegisterFile::ReturnPC * static_cast<int>(sizeof(Register)), X86::edi);
326 __ ret();
327 i += 2;
328 break;
329 }
330 case op_jmp: {
331 unsigned target = instruction[i + 1].u.operand;
332 m_jmpTable.append(JmpTable(jump(), i + 1 + target));
333 i += 2;
334 break;
335 }
336 case op_pre_inc: {
337 int srcDst = instruction[i + 1].u.operand;
338 emitGetVirtualRegister(srcDst, X86::eax, i);
339 emitJumpSlowCaseIfNotImmNum(X86::eax, i);
340 m_slowCases.append(SlowCaseEntry(joAdd32(Imm32(getDeTaggedConstantImmediate(JSImmediate::oneImmediate())), X86::eax), i));
341 emitPutVirtualRegister(srcDst);
342 i += 2;
343 break;
344 }
345 case op_loop: {
346 emitSlowScriptCheck(i);
347
348 unsigned target = instruction[i + 1].u.operand;
349 m_jmpTable.append(JmpTable(jump(), i + 1 + target));
350 i += 2;
351 break;
352 }
353 case op_loop_if_less: {
354 emitSlowScriptCheck(i);
355
356 unsigned target = instruction[i + 3].u.operand;
357 JSValue* src2imm = getConstantImmediateNumericArg(instruction[i + 2].u.operand);
358 if (src2imm) {
359 emitGetVirtualRegister(instruction[i + 1].u.operand, X86::eax, i);
360 emitJumpSlowCaseIfNotImmNum(X86::eax, i);
361 m_jmpTable.append(JmpTable(jl32(X86::eax, Imm32(asInteger(src2imm))), i + 3 + target));
362 } else {
363 emitGetVirtualRegisters(instruction[i + 1].u.operand, X86::eax, instruction[i + 2].u.operand, X86::edx, i);
364 emitJumpSlowCaseIfNotImmNum(X86::eax, i);
365 emitJumpSlowCaseIfNotImmNum(X86::edx, i);
366 m_jmpTable.append(JmpTable(jl32(X86::eax, X86::edx), i + 3 + target));
367 }
368 i += 4;
369 break;
370 }
371 case op_loop_if_lesseq: {
372 emitSlowScriptCheck(i);
373
374 unsigned target = instruction[i + 3].u.operand;
375 JSValue* src2imm = getConstantImmediateNumericArg(instruction[i + 2].u.operand);
376 if (src2imm) {
377 emitGetVirtualRegister(instruction[i + 1].u.operand, X86::eax, i);
378 emitJumpSlowCaseIfNotImmNum(X86::eax, i);
379 m_jmpTable.append(JmpTable(jle32(X86::eax, Imm32(asInteger(src2imm))), i + 3 + target));
380 } else {
381 emitGetVirtualRegisters(instruction[i + 1].u.operand, X86::eax, instruction[i + 2].u.operand, X86::edx, i);
382 emitJumpSlowCaseIfNotImmNum(X86::eax, i);
383 emitJumpSlowCaseIfNotImmNum(X86::edx, i);
384 m_jmpTable.append(JmpTable(jle32(X86::eax, X86::edx), i + 3 + target));
385 }
386 i += 4;
387 break;
388 }
389 case op_new_object: {
390 emitCTICall(i, Interpreter::cti_op_new_object);
391 emitPutVirtualRegister(instruction[i + 1].u.operand);
392 i += 2;
393 break;
394 }
395 case op_put_by_id: {
396 compilePutByIdHotPath(instruction[i + 1].u.operand, &(m_codeBlock->identifiers[instruction[i + 2].u.operand]), instruction[i + 3].u.operand, i, propertyAccessInstructionIndex++);
397 i += 8;
398 break;
399 }
400 case op_get_by_id: {
401 compileGetByIdHotPath(instruction[i + 1].u.operand, instruction[i + 2].u.operand, &(m_codeBlock->identifiers[instruction[i + 3].u.operand]), i, propertyAccessInstructionIndex++);
402 i += 8;
403 break;
404 }
405 case op_instanceof: {
406 emitGetVirtualRegister(instruction[i + 2].u.operand, X86::eax, i); // value
407 emitGetVirtualRegister(instruction[i + 3].u.operand, X86::ecx, i); // baseVal
408 emitGetVirtualRegister(instruction[i + 4].u.operand, X86::edx, i); // proto
409
410 // check if any are immediates
411 __ orl_rr(X86::eax, X86::ecx);
412 __ orl_rr(X86::edx, X86::ecx);
413 emitJumpSlowCaseIfNotJSCell(X86::ecx, i);
414
415 // check that all are object type - this is a bit of a bithack to avoid excess branching;
416 // we check that the sum of the three type codes from Structures is exactly 3 * ObjectType,
417 // this works because NumberType and StringType are smaller
418 __ movl_i32r(3 * ObjectType, X86::ecx);
419 __ movl_mr(FIELD_OFFSET(JSCell, m_structure), X86::eax, X86::eax);
420 __ movl_mr(FIELD_OFFSET(JSCell, m_structure), X86::edx, X86::edx);
421 __ subl_mr(FIELD_OFFSET(Structure, m_typeInfo.m_type), X86::eax, X86::ecx);
422 __ subl_mr(FIELD_OFFSET(Structure, m_typeInfo.m_type), X86::edx, X86::ecx);
423 emitGetVirtualRegister(instruction[i + 3].u.operand, X86::edx, i); // reload baseVal
424 __ movl_mr(FIELD_OFFSET(JSCell, m_structure), X86::edx, X86::edx);
425 __ cmpl_rm(X86::ecx, FIELD_OFFSET(Structure, m_typeInfo.m_type), X86::edx);
426
427 m_slowCases.append(SlowCaseEntry(__ jne(), i));
428
429 // check that baseVal's flags include ImplementsHasInstance but not OverridesHasInstance
430 __ movl_mr(FIELD_OFFSET(Structure, m_typeInfo.m_flags), X86::edx, X86::ecx);
431 __ andl_i32r(ImplementsHasInstance | OverridesHasInstance, X86::ecx);
432 __ cmpl_i32r(ImplementsHasInstance, X86::ecx);
433
434 m_slowCases.append(SlowCaseEntry(__ jne(), i));
435
436 emitGetVirtualRegister(instruction[i + 2].u.operand, X86::ecx, i); // reload value
437 emitGetVirtualRegister(instruction[i + 4].u.operand, X86::edx, i); // reload proto
438
439 // optimistically load true result
440 __ movl_i32r(asInteger(jsBoolean(true)), X86::eax);
441
442 JmpDst loop = __ label();
443
444 // load value's prototype
445 __ movl_mr(FIELD_OFFSET(JSCell, m_structure), X86::ecx, X86::ecx);
446 __ movl_mr(FIELD_OFFSET(Structure, m_prototype), X86::ecx, X86::ecx);
447
448 __ cmpl_rr(X86::ecx, X86::edx);
449 JmpSrc exit = __ je();
450
451 __ cmpl_i32r(asInteger(jsNull()), X86::ecx);
452 JmpSrc goToLoop = __ jne();
453 __ link(goToLoop, loop);
454
455 __ movl_i32r(asInteger(jsBoolean(false)), X86::eax);
456
457 __ link(exit, __ label());
458
459 emitPutVirtualRegister(instruction[i + 1].u.operand);
460
461 i += 5;
462 break;
463 }
464 case op_del_by_id: {
465 emitPutCTIArgFromVirtualRegister(instruction[i + 2].u.operand, 0, X86::ecx);
466 Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 3].u.operand]);
467 emitPutCTIArgConstant(reinterpret_cast<unsigned>(ident), 4);
468 emitCTICall(i, Interpreter::cti_op_del_by_id);
469 emitPutVirtualRegister(instruction[i + 1].u.operand);
470 i += 4;
471 break;
472 }
473 case op_mul: {
474 unsigned dst = instruction[i + 1].u.operand;
475 unsigned src1 = instruction[i + 2].u.operand;
476 unsigned src2 = instruction[i + 3].u.operand;
477
478 // For now, only plant a fast int case if the constant operand is greater than zero.
479 JSValue* src1Value = getConstantImmediateNumericArg(src1);
480 JSValue* src2Value = getConstantImmediateNumericArg(src2);
481 int32_t value;
482 if (src1Value && ((value = JSImmediate::intValue(src1Value)) > 0)) {
483 emitGetVirtualRegister(src2, X86::eax, i);
484 emitJumpSlowCaseIfNotImmNum(X86::eax, i);
485 emitFastArithDeTagImmediate(X86::eax);
486 m_slowCases.append(SlowCaseEntry(joMul32(Imm32(value), X86::eax, X86::eax), i));
487 emitFastArithReTagImmediate(X86::eax);
488 emitPutVirtualRegister(dst);
489 } else if (src2Value && ((value = JSImmediate::intValue(src2Value)) > 0)) {
490 emitGetVirtualRegister(src1, X86::eax, i);
491 emitJumpSlowCaseIfNotImmNum(X86::eax, i);
492 emitFastArithDeTagImmediate(X86::eax);
493 m_slowCases.append(SlowCaseEntry(joMul32(Imm32(value), X86::eax, X86::eax), i));
494 emitFastArithReTagImmediate(X86::eax);
495 emitPutVirtualRegister(dst);
496 } else
497 compileBinaryArithOp(op_mul, instruction[i + 1].u.operand, instruction[i + 2].u.operand, instruction[i + 3].u.operand, OperandTypes::fromInt(instruction[i + 4].u.operand), i);
498
499 i += 5;
500 break;
501 }
502 case op_new_func: {
503 FuncDeclNode* func = (m_codeBlock->functions[instruction[i + 2].u.operand]).get();
504 emitPutCTIArgConstant(reinterpret_cast<unsigned>(func), 0);
505 emitCTICall(i, Interpreter::cti_op_new_func);
506 emitPutVirtualRegister(instruction[i + 1].u.operand);
507 i += 3;
508 break;
509 }
510 case op_call:
511 case op_call_eval:
512 case op_construct: {
513 compileOpCall(opcodeID, instruction + i, i, callLinkInfoIndex++);
514 i += (opcodeID == op_construct ? 7 : 5);
515 break;
516 }
517 case op_get_global_var: {
518 JSVariableObject* globalObject = static_cast<JSVariableObject*>(instruction[i + 2].u.jsCell);
519 move(globalObject, X86::eax);
520 emitGetVariableObjectRegister(X86::eax, instruction[i + 3].u.operand, X86::eax);
521 emitPutVirtualRegister(instruction[i + 1].u.operand);
522 i += 4;
523 break;
524 }
525 case op_put_global_var: {
526 emitGetVirtualRegister(instruction[i + 3].u.operand, X86::edx, i);
527 JSVariableObject* globalObject = static_cast<JSVariableObject*>(instruction[i + 1].u.jsCell);
528 move(globalObject, X86::eax);
529 emitPutVariableObjectRegister(X86::edx, X86::eax, instruction[i + 2].u.operand);
530 i += 4;
531 break;
532 }
533 case op_get_scoped_var: {
534 int skip = instruction[i + 3].u.operand + m_codeBlock->needsFullScopeChain;
535
536 emitGetFromCallFrameHeader(RegisterFile::ScopeChain, X86::eax);
537 while (skip--)
538 loadPtr(Address(X86::eax, FIELD_OFFSET(ScopeChainNode, next)), X86::eax);
539
540 loadPtr(Address(X86::eax, FIELD_OFFSET(ScopeChainNode, object)), X86::eax);
541 emitGetVariableObjectRegister(X86::eax, instruction[i + 2].u.operand, X86::eax);
542 emitPutVirtualRegister(instruction[i + 1].u.operand);
543 i += 4;
544 break;
545 }
546 case op_put_scoped_var: {
547 int skip = instruction[i + 2].u.operand + m_codeBlock->needsFullScopeChain;
548
549 emitGetFromCallFrameHeader(RegisterFile::ScopeChain, X86::edx);
550 emitGetVirtualRegister(instruction[i + 3].u.operand, X86::eax, i);
551 while (skip--)
552 loadPtr(Address(X86::edx, FIELD_OFFSET(ScopeChainNode, next)), X86::edx);
553
554 loadPtr(Address(X86::edx, FIELD_OFFSET(ScopeChainNode, object)), X86::edx);
555 emitPutVariableObjectRegister(X86::eax, X86::edx, instruction[i + 1].u.operand);
556 i += 4;
557 break;
558 }
559 case op_tear_off_activation: {
560 emitPutCTIArgFromVirtualRegister(instruction[i + 1].u.operand, 0, X86::ecx);
561 emitCTICall(i, Interpreter::cti_op_tear_off_activation);
562 i += 2;
563 break;
564 }
565 case op_tear_off_arguments: {
566 emitCTICall(i, Interpreter::cti_op_tear_off_arguments);
567 i += 1;
568 break;
569 }
570 case op_ret: {
571 // We could JIT generate the deref, only calling out to C when the refcount hits zero.
572 if (m_codeBlock->needsFullScopeChain)
573 emitCTICall(i, Interpreter::cti_op_ret_scopeChain);
574
575 // Return the result in %eax.
576 emitGetVirtualRegister(instruction[i + 1].u.operand, X86::eax, i);
577
578 // Grab the return address.
579 emitGetFromCallFrameHeader(RegisterFile::ReturnPC, X86::edx);
580
581 // Restore our caller's "r".
582 emitGetFromCallFrameHeader(RegisterFile::CallerFrame, X86::edi);
583
584 // Return.
585 __ pushl_r(X86::edx);
586 __ ret();
587
588 i += 2;
589 break;
590 }
591 case op_new_array: {
592 __ leal_mr(sizeof(Register) * instruction[i + 2].u.operand, X86::edi, X86::edx);
593 emitPutCTIArg(X86::edx, 0);
594 emitPutCTIArgConstant(instruction[i + 3].u.operand, 4);
595 emitCTICall(i, Interpreter::cti_op_new_array);
596 emitPutVirtualRegister(instruction[i + 1].u.operand);
597 i += 4;
598 break;
599 }
600 case op_resolve: {
601 Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 2].u.operand]);
602 emitPutCTIArgConstant(reinterpret_cast<unsigned>(ident), 0);
603 emitCTICall(i, Interpreter::cti_op_resolve);
604 emitPutVirtualRegister(instruction[i + 1].u.operand);
605 i += 3;
606 break;
607 }
608 case op_construct_verify: {
609 emitGetVirtualRegister(instruction[i + 1].u.operand, X86::eax, i);
610
611 JmpSrc isImmediate = emitJumpIfNotJSCell(X86::eax);
612 __ movl_mr(FIELD_OFFSET(JSCell, m_structure), X86::eax, X86::ecx);
613 __ cmpl_i32m(ObjectType, FIELD_OFFSET(Structure, m_typeInfo) + FIELD_OFFSET(TypeInfo, m_type), X86::ecx);
614 JmpSrc isObject = __ je();
615
616 __ link(isImmediate, __ label());
617 emitGetVirtualRegister(instruction[i + 2].u.operand, X86::eax, i);
618 emitPutVirtualRegister(instruction[i + 1].u.operand);
619 __ link(isObject, __ label());
620
621 i += 3;
622 break;
623 }
624 case op_get_by_val: {
625 emitGetVirtualRegisters(instruction[i + 2].u.operand, X86::eax, instruction[i + 3].u.operand, X86::edx, i);
626 emitJumpSlowCaseIfNotImmNum(X86::edx, i);
627 emitFastArithImmToInt(X86::edx);
628 emitJumpSlowCaseIfNotJSCell(X86::eax, i);
629 __ cmpl_i32m(reinterpret_cast<unsigned>(m_interpreter->m_jsArrayVptr), X86::eax);
630 m_slowCases.append(SlowCaseEntry(__ jne(), i));
631
632 // This is an array; get the m_storage pointer into ecx, then check if the index is below the fast cutoff
633 __ movl_mr(FIELD_OFFSET(JSArray, m_storage), X86::eax, X86::ecx);
634 __ cmpl_rm(X86::edx, FIELD_OFFSET(JSArray, m_fastAccessCutoff), X86::eax);
635 m_slowCases.append(SlowCaseEntry(__ jbe(), i));
636
637 // Get the value from the vector
638 __ movl_mr(FIELD_OFFSET(ArrayStorage, m_vector[0]), X86::ecx, X86::edx, sizeof(JSValue*), X86::eax);
639 emitPutVirtualRegister(instruction[i + 1].u.operand);
640 i += 4;
641 break;
642 }
643 case op_resolve_func: {
644 Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 3].u.operand]);
645 emitPutCTIArgConstant(reinterpret_cast<unsigned>(ident), 0);
646 emitCTICall(i, Interpreter::cti_op_resolve_func);
647 emitPutVirtualRegister(instruction[i + 2].u.operand, X86::edx);
648 emitPutVirtualRegister(instruction[i + 1].u.operand);
649 i += 4;
650 break;
651 }
652 case op_sub: {
653 compileBinaryArithOp(op_sub, instruction[i + 1].u.operand, instruction[i + 2].u.operand, instruction[i + 3].u.operand, OperandTypes::fromInt(instruction[i + 4].u.operand), i);
654 i += 5;
655 break;
656 }
657 case op_put_by_val: {
658 emitGetVirtualRegisters(instruction[i + 1].u.operand, X86::eax, instruction[i + 2].u.operand, X86::edx, i);
659 emitJumpSlowCaseIfNotImmNum(X86::edx, i);
660 emitFastArithImmToInt(X86::edx);
661 emitJumpSlowCaseIfNotJSCell(X86::eax, i);
662 __ cmpl_i32m(reinterpret_cast<unsigned>(m_interpreter->m_jsArrayVptr), X86::eax);
663 m_slowCases.append(SlowCaseEntry(__ jne(), i));
664
665 // This is an array; get the m_storage pointer into ecx, then check if the index is below the fast cutoff
666 __ movl_mr(FIELD_OFFSET(JSArray, m_storage), X86::eax, X86::ecx);
667 __ cmpl_rm(X86::edx, FIELD_OFFSET(JSArray, m_fastAccessCutoff), X86::eax);
668 JmpSrc inFastVector = __ ja();
669 // No; oh well, check if the access if within the vector - if so, we may still be okay.
670 __ cmpl_rm(X86::edx, FIELD_OFFSET(ArrayStorage, m_vectorLength), X86::ecx);
671 m_slowCases.append(SlowCaseEntry(__ jbe(), i));
672
673 // This is a write to the slow part of the vector; first, we have to check if this would be the first write to this location.
674 // FIXME: should be able to handle initial write to array; increment the the number of items in the array, and potentially update fast access cutoff.
675 __ cmpl_i8m(0, FIELD_OFFSET(ArrayStorage, m_vector[0]), X86::ecx, X86::edx, sizeof(JSValue*));
676 m_slowCases.append(SlowCaseEntry(__ je(), i));
677
678 // All good - put the value into the array.
679 __ link(inFastVector, __ label());
680 emitGetVirtualRegister(instruction[i + 3].u.operand, X86::eax, i);
681 __ movl_rm(X86::eax, FIELD_OFFSET(ArrayStorage, m_vector[0]), X86::ecx, X86::edx, sizeof(JSValue*));
682 i += 4;
683 break;
684 }
685 CTI_COMPILE_BINARY_OP(op_lesseq)
686 case op_loop_if_true: {
687 emitSlowScriptCheck(i);
688
689 unsigned target = instruction[i + 2].u.operand;
690 emitGetVirtualRegister(instruction[i + 1].u.operand, X86::eax, i);
691
692 __ cmpl_i32r(asInteger(JSImmediate::zeroImmediate()), X86::eax);
693 JmpSrc isZero = __ je();
694 __ testl_i32r(JSImmediate::TagBitTypeInteger, X86::eax);
695 m_jmpTable.append(JmpTable(__ jne(), i + 2 + target));
696
697 __ cmpl_i32r(asInteger(JSImmediate::trueImmediate()), X86::eax);
698 m_jmpTable.append(JmpTable(__ je(), i + 2 + target));
699 __ cmpl_i32r(asInteger(JSImmediate::falseImmediate()), X86::eax);
700 m_slowCases.append(SlowCaseEntry(__ jne(), i));
701
702 __ link(isZero, __ label());
703 i += 3;
704 break;
705 };
706 case op_resolve_base: {
707 Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 2].u.operand]);
708 emitPutCTIArgConstant(reinterpret_cast<unsigned>(ident), 0);
709 emitCTICall(i, Interpreter::cti_op_resolve_base);
710 emitPutVirtualRegister(instruction[i + 1].u.operand);
711 i += 3;
712 break;
713 }
714 case op_negate: {
715 emitPutCTIArgFromVirtualRegister(instruction[i + 2].u.operand, 0, X86::ecx);
716 emitCTICall(i, Interpreter::cti_op_negate);
717 emitPutVirtualRegister(instruction[i + 1].u.operand);
718 i += 3;
719 break;
720 }
721 case op_resolve_skip: {
722 Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 2].u.operand]);
723 emitPutCTIArgConstant(reinterpret_cast<unsigned>(ident), 0);
724 emitPutCTIArgConstant(instruction[i + 3].u.operand + m_codeBlock->needsFullScopeChain, 4);
725 emitCTICall(i, Interpreter::cti_op_resolve_skip);
726 emitPutVirtualRegister(instruction[i + 1].u.operand);
727 i += 4;
728 break;
729 }
730 case op_resolve_global: {
731 // Fast case
732 unsigned globalObject = asInteger(instruction[i + 2].u.jsCell);
733 Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 3].u.operand]);
734 void* structureAddress = reinterpret_cast<void*>(instruction + i + 4);
735 void* offsetAddr = reinterpret_cast<void*>(instruction + i + 5);
736
737 // Check Structure of global object
738 __ movl_i32r(globalObject, X86::eax);
739 __ movl_mr(structureAddress, X86::edx);
740 __ cmpl_rm(X86::edx, FIELD_OFFSET(JSCell, m_structure), X86::eax);
741 JmpSrc noMatch = __ jne(); // Structures don't match
742
743 // Load cached property
744 __ movl_mr(FIELD_OFFSET(JSGlobalObject, m_propertyStorage), X86::eax, X86::eax);
745 __ movl_mr(offsetAddr, X86::edx);
746 __ movl_mr(0, X86::eax, X86::edx, sizeof(JSValue*), X86::eax);
747 emitPutVirtualRegister(instruction[i + 1].u.operand);
748 JmpSrc end = __ jmp();
749
750 // Slow case
751 __ link(noMatch, __ label());
752 emitPutCTIArgConstant(globalObject, 0);
753 emitPutCTIArgConstant(reinterpret_cast<unsigned>(ident), 4);
754 emitPutCTIArgConstant(reinterpret_cast<unsigned>(instruction + i), 8);
755 emitCTICall(i, Interpreter::cti_op_resolve_global);
756 emitPutVirtualRegister(instruction[i + 1].u.operand);
757 __ link(end, __ label());
758 i += 6;
759 break;
760 }
761 CTI_COMPILE_BINARY_OP(op_div)
762 case op_pre_dec: {
763 int srcDst = instruction[i + 1].u.operand;
764 emitGetVirtualRegister(srcDst, X86::eax, i);
765 emitJumpSlowCaseIfNotImmNum(X86::eax, i);
766 __ subl_i8r(getDeTaggedConstantImmediate(JSImmediate::oneImmediate()), X86::eax);
767 m_slowCases.append(SlowCaseEntry(__ jo(), i));
768 emitPutVirtualRegister(srcDst);
769 i += 2;
770 break;
771 }
772 case op_jnless: {
773 unsigned target = instruction[i + 3].u.operand;
774 JSValue* src2imm = getConstantImmediateNumericArg(instruction[i + 2].u.operand);
775 if (src2imm) {
776 emitGetVirtualRegister(instruction[i + 1].u.operand, X86::edx, i);
777 emitJumpSlowCaseIfNotImmNum(X86::edx, i);
778 __ cmpl_i32r(asInteger(src2imm), X86::edx);
779 m_jmpTable.append(JmpTable(__ jge(), i + 3 + target));
780 } else {
781 emitGetVirtualRegisters(instruction[i + 1].u.operand, X86::eax, instruction[i + 2].u.operand, X86::edx, i);
782 emitJumpSlowCaseIfNotImmNum(X86::eax, i);
783 emitJumpSlowCaseIfNotImmNum(X86::edx, i);
784 __ cmpl_rr(X86::edx, X86::eax);
785 m_jmpTable.append(JmpTable(__ jge(), i + 3 + target));
786 }
787 i += 4;
788 break;
789 }
790 case op_not: {
791 emitGetVirtualRegister(instruction[i + 2].u.operand, X86::eax, i);
792 __ xorl_i8r(JSImmediate::FullTagTypeBool, X86::eax);
793 __ testl_i32r(JSImmediate::FullTagTypeMask, X86::eax); // i8?
794 m_slowCases.append(SlowCaseEntry(__ jne(), i));
795 __ xorl_i8r((JSImmediate::FullTagTypeBool | JSImmediate::ExtendedPayloadBitBoolValue), X86::eax);
796 emitPutVirtualRegister(instruction[i + 1].u.operand);
797 i += 3;
798 break;
799 }
800 case op_jfalse: {
801 unsigned target = instruction[i + 2].u.operand;
802 emitGetVirtualRegister(instruction[i + 1].u.operand, X86::eax, i);
803
804 __ cmpl_i32r(asInteger(JSImmediate::zeroImmediate()), X86::eax);
805 m_jmpTable.append(JmpTable(__ je(), i + 2 + target));
806 __ testl_i32r(JSImmediate::TagBitTypeInteger, X86::eax);
807 JmpSrc isNonZero = __ jne();
808
809 __ cmpl_i32r(asInteger(JSImmediate::falseImmediate()), X86::eax);
810 m_jmpTable.append(JmpTable(__ je(), i + 2 + target));
811 __ cmpl_i32r(asInteger(JSImmediate::trueImmediate()), X86::eax);
812 m_slowCases.append(SlowCaseEntry(__ jne(), i));
813
814 __ link(isNonZero, __ label());
815 i += 3;
816 break;
817 };
818 case op_jeq_null: {
819 unsigned src = instruction[i + 1].u.operand;
820 unsigned target = instruction[i + 2].u.operand;
821
822 emitGetVirtualRegister(src, X86::eax, i);
823 JmpSrc isImmediate = emitJumpIfNotJSCell(X86::eax);
824
825 __ movl_mr(FIELD_OFFSET(JSCell, m_structure), X86::eax, X86::ecx);
826 __ testl_i32m(MasqueradesAsUndefined, FIELD_OFFSET(Structure, m_typeInfo.m_flags), X86::ecx);
827 __ setnz_r(X86::eax);
828
829 JmpSrc wasNotImmediate = __ jmp();
830
831 __ link(isImmediate, __ label());
832
833 __ movl_i32r(~JSImmediate::ExtendedTagBitUndefined, X86::ecx);
834 __ andl_rr(X86::eax, X86::ecx);
835 __ cmpl_i32r(JSImmediate::FullTagTypeNull, X86::ecx);
836 __ sete_r(X86::eax);
837
838 __ link(wasNotImmediate, __ label());
839
840 __ movzbl_rr(X86::eax, X86::eax);
841 __ cmpl_i32r(0, X86::eax);
842 m_jmpTable.append(JmpTable(__ jnz(), i + 2 + target));
843
844 i += 3;
845 break;
846 };
847 case op_jneq_null: {
848 unsigned src = instruction[i + 1].u.operand;
849 unsigned target = instruction[i + 2].u.operand;
850
851 emitGetVirtualRegister(src, X86::eax, i);
852 JmpSrc isImmediate = emitJumpIfNotJSCell(X86::eax);
853
854 __ movl_mr(FIELD_OFFSET(JSCell, m_structure), X86::eax, X86::ecx);
855 __ testl_i32m(MasqueradesAsUndefined, FIELD_OFFSET(Structure, m_typeInfo.m_flags), X86::ecx);
856 __ setz_r(X86::eax);
857
858 JmpSrc wasNotImmediate = __ jmp();
859
860 __ link(isImmediate, __ label());
861
862 __ movl_i32r(~JSImmediate::ExtendedTagBitUndefined, X86::ecx);
863 __ andl_rr(X86::eax, X86::ecx);
864 __ cmpl_i32r(JSImmediate::FullTagTypeNull, X86::ecx);
865 __ setne_r(X86::eax);
866
867 __ link(wasNotImmediate, __ label());
868
869 __ movzbl_rr(X86::eax, X86::eax);
870 __ cmpl_i32r(0, X86::eax);
871 m_jmpTable.append(JmpTable(__ jnz(), i + 2 + target));
872
873 i += 3;
874 break;
875 }
876 case op_post_inc: {
877 int srcDst = instruction[i + 2].u.operand;
878 emitGetVirtualRegister(srcDst, X86::eax, i);
879 __ movl_rr(X86::eax, X86::edx);
880 emitJumpSlowCaseIfNotImmNum(X86::eax, i);
881 __ addl_i8r(getDeTaggedConstantImmediate(JSImmediate::oneImmediate()), X86::edx);
882 m_slowCases.append(SlowCaseEntry(__ jo(), i));
883 emitPutVirtualRegister(srcDst, X86::edx);
884 emitPutVirtualRegister(instruction[i + 1].u.operand);
885 i += 3;
886 break;
887 }
888 case op_unexpected_load: {
889 JSValue* v = m_codeBlock->unexpectedConstants[instruction[i + 2].u.operand];
890 __ movl_i32r(asInteger(v), X86::eax);
891 emitPutVirtualRegister(instruction[i + 1].u.operand);
892 i += 3;
893 break;
894 }
895 case op_jsr: {
896 int retAddrDst = instruction[i + 1].u.operand;
897 int target = instruction[i + 2].u.operand;
898 __ movl_i32m(0, sizeof(Register) * retAddrDst, X86::edi);
899 JmpDst addrPosition = __ label();
900 m_jmpTable.append(JmpTable(__ jmp(), i + 2 + target));
901 JmpDst sretTarget = __ label();
902 m_jsrSites.append(JSRInfo(addrPosition, sretTarget));
903 i += 3;
904 break;
905 }
906 case op_sret: {
907 __ jmp_m(sizeof(Register) * instruction[i + 1].u.operand, X86::edi);
908 i += 2;
909 break;
910 }
911 case op_eq: {
912 emitGetVirtualRegisters(instruction[i + 2].u.operand, X86::eax, instruction[i + 3].u.operand, X86::edx, i);
913 emitJumpSlowCaseIfNotImmNums(X86::eax, X86::edx, X86::ecx, i);
914 __ cmpl_rr(X86::edx, X86::eax);
915 __ sete_r(X86::eax);
916 __ movzbl_rr(X86::eax, X86::eax);
917 emitTagAsBoolImmediate(X86::eax);
918 emitPutVirtualRegister(instruction[i + 1].u.operand);
919 i += 4;
920 break;
921 }
922 case op_lshift: {
923 emitGetVirtualRegisters(instruction[i + 2].u.operand, X86::eax, instruction[i + 3].u.operand, X86::ecx, i);
924 emitJumpSlowCaseIfNotImmNum(X86::eax, i);
925 emitJumpSlowCaseIfNotImmNum(X86::ecx, i);
926 emitFastArithImmToInt(X86::eax);
927 emitFastArithImmToInt(X86::ecx);
928 __ shll_CLr(X86::eax);
929 emitFastArithIntToImmOrSlowCase(X86::eax, i);
930 emitPutVirtualRegister(instruction[i + 1].u.operand);
931 i += 4;
932 break;
933 }
934 case op_bitand: {
935 unsigned src1 = instruction[i + 2].u.operand;
936 unsigned src2 = instruction[i + 3].u.operand;
937 unsigned dst = instruction[i + 1].u.operand;
938 if (JSValue* value = getConstantImmediateNumericArg(src1)) {
939 emitGetVirtualRegister(src2, X86::eax, i);
940 emitJumpSlowCaseIfNotImmNum(X86::eax, i);
941 __ andl_i32r(asInteger(value), X86::eax); // FIXME: make it more obvious this is relying on the format of JSImmediate
942 emitPutVirtualRegister(dst);
943 } else if (JSValue* value = getConstantImmediateNumericArg(src2)) {
944 emitGetVirtualRegister(src1, X86::eax, i);
945 emitJumpSlowCaseIfNotImmNum(X86::eax, i);
946 __ andl_i32r(asInteger(value), X86::eax);
947 emitPutVirtualRegister(dst);
948 } else {
949 emitGetVirtualRegisters(src1, X86::eax, src2, X86::edx, i);
950 __ andl_rr(X86::edx, X86::eax);
951 emitJumpSlowCaseIfNotImmNum(X86::eax, i);
952 emitPutVirtualRegister(dst);
953 }
954 i += 5;
955 break;
956 }
957 case op_rshift: {
958 unsigned src1 = instruction[i + 2].u.operand;
959 unsigned src2 = instruction[i + 3].u.operand;
960 if (JSValue* value = getConstantImmediateNumericArg(src2)) {
961 emitGetVirtualRegister(src1, X86::eax, i);
962 emitJumpSlowCaseIfNotImmNum(X86::eax, i);
963 // Mask with 0x1f as per ecma-262 11.7.2 step 7.
964 __ sarl_i8r(JSImmediate::getTruncatedUInt32(value) & 0x1f, X86::eax);
965 } else {
966 emitGetVirtualRegisters(src1, X86::eax, src2, X86::ecx, i);
967 emitJumpSlowCaseIfNotImmNum(X86::eax, i);
968 emitJumpSlowCaseIfNotImmNum(X86::ecx, i);
969 emitFastArithImmToInt(X86::ecx);
970 __ sarl_CLr(X86::eax);
971 }
972 emitFastArithPotentiallyReTagImmediate(X86::eax);
973 emitPutVirtualRegister(instruction[i + 1].u.operand);
974 i += 4;
975 break;
976 }
977 case op_bitnot: {
978 emitGetVirtualRegister(instruction[i + 2].u.operand, X86::eax, i);
979 emitJumpSlowCaseIfNotImmNum(X86::eax, i);
980 __ xorl_i8r(~JSImmediate::TagBitTypeInteger, X86::eax);
981 emitPutVirtualRegister(instruction[i + 1].u.operand);
982 i += 3;
983 break;
984 }
985 case op_resolve_with_base: {
986 Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 3].u.operand]);
987 emitPutCTIArgConstant(reinterpret_cast<unsigned>(ident), 0);
988 emitCTICall(i, Interpreter::cti_op_resolve_with_base);
989 emitPutVirtualRegister(instruction[i + 2].u.operand, X86::edx);
990 emitPutVirtualRegister(instruction[i + 1].u.operand);
991 i += 4;
992 break;
993 }
994 case op_new_func_exp: {
995 FuncExprNode* func = (m_codeBlock->functionExpressions[instruction[i + 2].u.operand]).get();
996 emitPutCTIArgConstant(reinterpret_cast<unsigned>(func), 0);
997 emitCTICall(i, Interpreter::cti_op_new_func_exp);
998 emitPutVirtualRegister(instruction[i + 1].u.operand);
999 i += 3;
1000 break;
1001 }
1002 case op_mod: {
1003 emitGetVirtualRegisters(instruction[i + 2].u.operand, X86::eax, instruction[i + 3].u.operand, X86::ecx, i);
1004 emitJumpSlowCaseIfNotImmNum(X86::eax, i);
1005 emitJumpSlowCaseIfNotImmNum(X86::ecx, i);
1006 emitFastArithDeTagImmediate(X86::eax);
1007 m_slowCases.append(SlowCaseEntry(emitFastArithDeTagImmediateJumpIfZero(X86::ecx), i));
1008 __ cdq();
1009 __ idivl_r(X86::ecx);
1010 emitFastArithReTagImmediate(X86::edx);
1011 __ movl_rr(X86::edx, X86::eax);
1012 emitPutVirtualRegister(instruction[i + 1].u.operand);
1013 i += 4;
1014 break;
1015 }
1016 case op_jtrue: {
1017 unsigned target = instruction[i + 2].u.operand;
1018 emitGetVirtualRegister(instruction[i + 1].u.operand, X86::eax, i);
1019
1020 __ cmpl_i32r(asInteger(JSImmediate::zeroImmediate()), X86::eax);
1021 JmpSrc isZero = __ je();
1022 __ testl_i32r(JSImmediate::TagBitTypeInteger, X86::eax);
1023 m_jmpTable.append(JmpTable(__ jne(), i + 2 + target));
1024
1025 __ cmpl_i32r(asInteger(JSImmediate::trueImmediate()), X86::eax);
1026 m_jmpTable.append(JmpTable(__ je(), i + 2 + target));
1027 __ cmpl_i32r(asInteger(JSImmediate::falseImmediate()), X86::eax);
1028 m_slowCases.append(SlowCaseEntry(__ jne(), i));
1029
1030 __ link(isZero, __ label());
1031 i += 3;
1032 break;
1033 }
1034 CTI_COMPILE_BINARY_OP(op_less)
1035 case op_neq: {
1036 emitGetVirtualRegisters(instruction[i + 2].u.operand, X86::eax, instruction[i + 3].u.operand, X86::edx, i);
1037 emitJumpSlowCaseIfNotImmNums(X86::eax, X86::edx, X86::ecx, i);
1038 __ cmpl_rr(X86::eax, X86::edx);
1039
1040 __ setne_r(X86::eax);
1041 __ movzbl_rr(X86::eax, X86::eax);
1042 emitTagAsBoolImmediate(X86::eax);
1043
1044 emitPutVirtualRegister(instruction[i + 1].u.operand);
1045
1046 i += 4;
1047 break;
1048 }
1049 case op_post_dec: {
1050 int srcDst = instruction[i + 2].u.operand;
1051 emitGetVirtualRegister(srcDst, X86::eax, i);
1052 __ movl_rr(X86::eax, X86::edx);
1053 emitJumpSlowCaseIfNotImmNum(X86::eax, i);
1054 __ subl_i8r(getDeTaggedConstantImmediate(JSImmediate::oneImmediate()), X86::edx);
1055 m_slowCases.append(SlowCaseEntry(__ jo(), i));
1056 emitPutVirtualRegister(srcDst, X86::edx);
1057 emitPutVirtualRegister(instruction[i + 1].u.operand);
1058 i += 3;
1059 break;
1060 }
1061 CTI_COMPILE_BINARY_OP(op_urshift)
1062 case op_bitxor: {
1063 emitGetVirtualRegisters(instruction[i + 2].u.operand, X86::eax, instruction[i + 3].u.operand, X86::edx, i);
1064 emitJumpSlowCaseIfNotImmNums(X86::eax, X86::edx, X86::ecx, i);
1065 __ xorl_rr(X86::edx, X86::eax);
1066 emitFastArithReTagImmediate(X86::eax);
1067 emitPutVirtualRegister(instruction[i + 1].u.operand);
1068 i += 5;
1069 break;
1070 }
1071 case op_new_regexp: {
1072 RegExp* regExp = m_codeBlock->regexps[instruction[i + 2].u.operand].get();
1073 emitPutCTIArgConstant(reinterpret_cast<unsigned>(regExp), 0);
1074 emitCTICall(i, Interpreter::cti_op_new_regexp);
1075 emitPutVirtualRegister(instruction[i + 1].u.operand);
1076 i += 3;
1077 break;
1078 }
1079 case op_bitor: {
1080 emitGetVirtualRegisters(instruction[i + 2].u.operand, X86::eax, instruction[i + 3].u.operand, X86::edx, i);
1081 emitJumpSlowCaseIfNotImmNums(X86::eax, X86::edx, X86::ecx, i);
1082 __ orl_rr(X86::edx, X86::eax);
1083 emitPutVirtualRegister(instruction[i + 1].u.operand);
1084 i += 5;
1085 break;
1086 }
1087 case op_throw: {
1088 emitPutCTIArgFromVirtualRegister(instruction[i + 1].u.operand, 0, X86::ecx);
1089 emitCTICall(i, Interpreter::cti_op_throw);
1090 __ addl_i8r(0x20, X86::esp);
1091 __ popl_r(X86::ebx);
1092 __ popl_r(X86::edi);
1093 __ popl_r(X86::esi);
1094 __ ret();
1095 i += 2;
1096 break;
1097 }
1098 case op_get_pnames: {
1099 emitPutCTIArgFromVirtualRegister(instruction[i + 2].u.operand, 0, X86::ecx);
1100 emitCTICall(i, Interpreter::cti_op_get_pnames);
1101 emitPutVirtualRegister(instruction[i + 1].u.operand);
1102 i += 3;
1103 break;
1104 }
1105 case op_next_pname: {
1106 emitPutCTIArgFromVirtualRegister(instruction[i + 2].u.operand, 0, X86::ecx);
1107 unsigned target = instruction[i + 3].u.operand;
1108 emitCTICall(i, Interpreter::cti_op_next_pname);
1109 __ testl_rr(X86::eax, X86::eax);
1110 JmpSrc endOfIter = __ je();
1111 emitPutVirtualRegister(instruction[i + 1].u.operand);
1112 m_jmpTable.append(JmpTable(__ jmp(), i + 3 + target));
1113 __ link(endOfIter, __ label());
1114 i += 4;
1115 break;
1116 }
1117 case op_push_scope: {
1118 emitPutCTIArgFromVirtualRegister(instruction[i + 1].u.operand, 0, X86::ecx);
1119 emitCTICall(i, Interpreter::cti_op_push_scope);
1120 i += 2;
1121 break;
1122 }
1123 case op_pop_scope: {
1124 emitCTICall(i, Interpreter::cti_op_pop_scope);
1125 i += 1;
1126 break;
1127 }
1128 CTI_COMPILE_UNARY_OP(op_typeof)
1129 CTI_COMPILE_UNARY_OP(op_is_undefined)
1130 CTI_COMPILE_UNARY_OP(op_is_boolean)
1131 CTI_COMPILE_UNARY_OP(op_is_number)
1132 CTI_COMPILE_UNARY_OP(op_is_string)
1133 CTI_COMPILE_UNARY_OP(op_is_object)
1134 CTI_COMPILE_UNARY_OP(op_is_function)
1135 case op_stricteq: {
1136 compileOpStrictEq(instruction + i, i, OpStrictEq);
1137 i += 4;
1138 break;
1139 }
1140 case op_nstricteq: {
1141 compileOpStrictEq(instruction + i, i, OpNStrictEq);
1142 i += 4;
1143 break;
1144 }
1145 case op_to_jsnumber: {
1146 int srcVReg = instruction[i + 2].u.operand;
1147 emitGetVirtualRegister(srcVReg, X86::eax, i);
1148
1149 __ testl_i32r(JSImmediate::TagBitTypeInteger, X86::eax);
1150 JmpSrc wasImmediate = __ jnz();
1151
1152 emitJumpSlowCaseIfNotJSCell(X86::eax, i, srcVReg);
1153
1154 __ movl_mr(FIELD_OFFSET(JSCell, m_structure), X86::eax, X86::ecx);
1155 __ cmpl_i32m(NumberType, FIELD_OFFSET(Structure, m_typeInfo.m_type), X86::ecx);
1156
1157 m_slowCases.append(SlowCaseEntry(__ jne(), i));
1158
1159 __ link(wasImmediate, __ label());
1160
1161 emitPutVirtualRegister(instruction[i + 1].u.operand);
1162 i += 3;
1163 break;
1164 }
1165 case op_in: {
1166 emitPutCTIArgFromVirtualRegister(instruction[i + 2].u.operand, 0, X86::ecx);
1167 emitPutCTIArgFromVirtualRegister(instruction[i + 3].u.operand, 4, X86::ecx);
1168 emitCTICall(i, Interpreter::cti_op_in);
1169 emitPutVirtualRegister(instruction[i + 1].u.operand);
1170 i += 4;
1171 break;
1172 }
1173 case op_push_new_scope: {
1174 Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 2].u.operand]);
1175 emitPutCTIArgConstant(reinterpret_cast<unsigned>(ident), 0);
1176 emitPutCTIArgFromVirtualRegister(instruction[i + 3].u.operand, 4, X86::ecx);
1177 emitCTICall(i, Interpreter::cti_op_push_new_scope);
1178 emitPutVirtualRegister(instruction[i + 1].u.operand);
1179 i += 4;
1180 break;
1181 }
1182 case op_catch: {
1183 emitGetCTIParam(CTI_ARGS_callFrame, X86::edi); // edi := r
1184 emitPutVirtualRegister(instruction[i + 1].u.operand);
1185 i += 2;
1186 break;
1187 }
1188 case op_jmp_scopes: {
1189 unsigned count = instruction[i + 1].u.operand;
1190 emitPutCTIArgConstant(count, 0);
1191 emitCTICall(i, Interpreter::cti_op_jmp_scopes);
1192 unsigned target = instruction[i + 2].u.operand;
1193 m_jmpTable.append(JmpTable(__ jmp(), i + 2 + target));
1194 i += 3;
1195 break;
1196 }
1197 case op_put_by_index: {
1198 emitPutCTIArgFromVirtualRegister(instruction[i + 1].u.operand, 0, X86::ecx);
1199 emitPutCTIArgConstant(instruction[i + 2].u.operand, 4);
1200 emitPutCTIArgFromVirtualRegister(instruction[i + 3].u.operand, 8, X86::ecx);
1201 emitCTICall(i, Interpreter::cti_op_put_by_index);
1202 i += 4;
1203 break;
1204 }
1205 case op_switch_imm: {
1206 unsigned tableIndex = instruction[i + 1].u.operand;
1207 unsigned defaultOffset = instruction[i + 2].u.operand;
1208 unsigned scrutinee = instruction[i + 3].u.operand;
1209
1210 // create jump table for switch destinations, track this switch statement.
1211 SimpleJumpTable* jumpTable = &m_codeBlock->immediateSwitchJumpTable(tableIndex);
1212 m_switches.append(SwitchRecord(jumpTable, i, defaultOffset, SwitchRecord::Immediate));
1213 jumpTable->ctiOffsets.grow(jumpTable->branchOffsets.size());
1214
1215 emitPutCTIArgFromVirtualRegister(scrutinee, 0, X86::ecx);
1216 emitPutCTIArgConstant(tableIndex, 4);
1217 emitCTICall(i, Interpreter::cti_op_switch_imm);
1218 __ jmp_r(X86::eax);
1219 i += 4;
1220 break;
1221 }
1222 case op_switch_char: {
1223 unsigned tableIndex = instruction[i + 1].u.operand;
1224 unsigned defaultOffset = instruction[i + 2].u.operand;
1225 unsigned scrutinee = instruction[i + 3].u.operand;
1226
1227 // create jump table for switch destinations, track this switch statement.
1228 SimpleJumpTable* jumpTable = &m_codeBlock->characterSwitchJumpTable(tableIndex);
1229 m_switches.append(SwitchRecord(jumpTable, i, defaultOffset, SwitchRecord::Character));
1230 jumpTable->ctiOffsets.grow(jumpTable->branchOffsets.size());
1231
1232 emitPutCTIArgFromVirtualRegister(scrutinee, 0, X86::ecx);
1233 emitPutCTIArgConstant(tableIndex, 4);
1234 emitCTICall(i, Interpreter::cti_op_switch_char);
1235 __ jmp_r(X86::eax);
1236 i += 4;
1237 break;
1238 }
1239 case op_switch_string: {
1240 unsigned tableIndex = instruction[i + 1].u.operand;
1241 unsigned defaultOffset = instruction[i + 2].u.operand;
1242 unsigned scrutinee = instruction[i + 3].u.operand;
1243
1244 // create jump table for switch destinations, track this switch statement.
1245 StringJumpTable* jumpTable = &m_codeBlock->stringSwitchJumpTable(tableIndex);
1246 m_switches.append(SwitchRecord(jumpTable, i, defaultOffset));
1247
1248 emitPutCTIArgFromVirtualRegister(scrutinee, 0, X86::ecx);
1249 emitPutCTIArgConstant(tableIndex, 4);
1250 emitCTICall(i, Interpreter::cti_op_switch_string);
1251 __ jmp_r(X86::eax);
1252 i += 4;
1253 break;
1254 }
1255 case op_del_by_val: {
1256 emitPutCTIArgFromVirtualRegister(instruction[i + 2].u.operand, 0, X86::ecx);
1257 emitPutCTIArgFromVirtualRegister(instruction[i + 3].u.operand, 4, X86::ecx);
1258 emitCTICall(i, Interpreter::cti_op_del_by_val);
1259 emitPutVirtualRegister(instruction[i + 1].u.operand);
1260 i += 4;
1261 break;
1262 }
1263 case op_put_getter: {
1264 emitPutCTIArgFromVirtualRegister(instruction[i + 1].u.operand, 0, X86::ecx);
1265 Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 2].u.operand]);
1266 emitPutCTIArgConstant(reinterpret_cast<unsigned>(ident), 4);
1267 emitPutCTIArgFromVirtualRegister(instruction[i + 3].u.operand, 8, X86::ecx);
1268 emitCTICall(i, Interpreter::cti_op_put_getter);
1269 i += 4;
1270 break;
1271 }
1272 case op_put_setter: {
1273 emitPutCTIArgFromVirtualRegister(instruction[i + 1].u.operand, 0, X86::ecx);
1274 Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 2].u.operand]);
1275 emitPutCTIArgConstant(reinterpret_cast<unsigned>(ident), 4);
1276 emitPutCTIArgFromVirtualRegister(instruction[i + 3].u.operand, 8, X86::ecx);
1277 emitCTICall(i, Interpreter::cti_op_put_setter);
1278 i += 4;
1279 break;
1280 }
1281 case op_new_error: {
1282 JSValue* message = m_codeBlock->unexpectedConstants[instruction[i + 3].u.operand];
1283 emitPutCTIArgConstant(instruction[i + 2].u.operand, 0);
1284 emitPutCTIArgConstant(asInteger(message), 4);
1285 emitPutCTIArgConstant(m_codeBlock->lineNumberForVPC(&instruction[i]), 8);
1286 emitCTICall(i, Interpreter::cti_op_new_error);
1287 emitPutVirtualRegister(instruction[i + 1].u.operand);
1288 i += 4;
1289 break;
1290 }
1291 case op_debug: {
1292 emitPutCTIArgConstant(instruction[i + 1].u.operand, 0);
1293 emitPutCTIArgConstant(instruction[i + 2].u.operand, 4);
1294 emitPutCTIArgConstant(instruction[i + 3].u.operand, 8);
1295 emitCTICall(i, Interpreter::cti_op_debug);
1296 i += 4;
1297 break;
1298 }
1299 case op_eq_null: {
1300 unsigned dst = instruction[i + 1].u.operand;
1301 unsigned src1 = instruction[i + 2].u.operand;
1302
1303 emitGetVirtualRegister(src1, X86::eax, i);
1304 JmpSrc isImmediate = emitJumpIfNotJSCell(X86::eax);
1305
1306 __ movl_mr(FIELD_OFFSET(JSCell, m_structure), X86::eax, X86::ecx);
1307 __ testl_i32m(MasqueradesAsUndefined, FIELD_OFFSET(Structure, m_typeInfo.m_flags), X86::ecx);
1308 __ setnz_r(X86::eax);
1309
1310 JmpSrc wasNotImmediate = __ jmp();
1311
1312 __ link(isImmediate, __ label());
1313
1314 __ movl_i32r(~JSImmediate::ExtendedTagBitUndefined, X86::ecx);
1315 __ andl_rr(X86::eax, X86::ecx);
1316 __ cmpl_i32r(JSImmediate::FullTagTypeNull, X86::ecx);
1317 __ sete_r(X86::eax);
1318
1319 __ link(wasNotImmediate, __ label());
1320
1321 __ movzbl_rr(X86::eax, X86::eax);
1322 emitTagAsBoolImmediate(X86::eax);
1323 emitPutVirtualRegister(dst);
1324
1325 i += 3;
1326 break;
1327 }
1328 case op_neq_null: {
1329 unsigned dst = instruction[i + 1].u.operand;
1330 unsigned src1 = instruction[i + 2].u.operand;
1331
1332 emitGetVirtualRegister(src1, X86::eax, i);
1333 JmpSrc isImmediate = emitJumpIfNotJSCell(X86::eax);
1334
1335 __ movl_mr(FIELD_OFFSET(JSCell, m_structure), X86::eax, X86::ecx);
1336 __ testl_i32m(MasqueradesAsUndefined, FIELD_OFFSET(Structure, m_typeInfo.m_flags), X86::ecx);
1337 __ setz_r(X86::eax);
1338
1339 JmpSrc wasNotImmediate = __ jmp();
1340
1341 __ link(isImmediate, __ label());
1342
1343 __ movl_i32r(~JSImmediate::ExtendedTagBitUndefined, X86::ecx);
1344 __ andl_rr(X86::eax, X86::ecx);
1345 __ cmpl_i32r(JSImmediate::FullTagTypeNull, X86::ecx);
1346 __ setne_r(X86::eax);
1347
1348 __ link(wasNotImmediate, __ label());
1349
1350 __ movzbl_rr(X86::eax, X86::eax);
1351 emitTagAsBoolImmediate(X86::eax);
1352 emitPutVirtualRegister(dst);
1353
1354 i += 3;
1355 break;
1356 }
1357 case op_enter: {
1358 // Even though CTI doesn't use them, we initialize our constant
1359 // registers to zap stale pointers, to avoid unnecessarily prolonging
1360 // object lifetime and increasing GC pressure.
1361 size_t count = m_codeBlock->numVars + m_codeBlock->constantRegisters.size();
1362 for (size_t j = 0; j < count; ++j)
1363 emitInitRegister(j);
1364
1365 i+= 1;
1366 break;
1367 }
1368 case op_enter_with_activation: {
1369 // Even though CTI doesn't use them, we initialize our constant
1370 // registers to zap stale pointers, to avoid unnecessarily prolonging
1371 // object lifetime and increasing GC pressure.
1372 size_t count = m_codeBlock->numVars + m_codeBlock->constantRegisters.size();
1373 for (size_t j = 0; j < count; ++j)
1374 emitInitRegister(j);
1375
1376 emitCTICall(i, Interpreter::cti_op_push_activation);
1377 emitPutVirtualRegister(instruction[i + 1].u.operand);
1378
1379 i+= 2;
1380 break;
1381 }
1382 case op_create_arguments: {
1383 emitCTICall(i, (m_codeBlock->numParameters == 1) ? Interpreter::cti_op_create_arguments_no_params : Interpreter::cti_op_create_arguments);
1384 i += 1;
1385 break;
1386 }
1387 case op_convert_this: {
1388 emitGetVirtualRegister(instruction[i + 1].u.operand, X86::eax, i);
1389
1390 emitJumpSlowCaseIfNotJSCell(X86::eax, i);
1391 __ movl_mr(FIELD_OFFSET(JSCell, m_structure), X86::eax, X86::edx);
1392 __ testl_i32m(NeedsThisConversion, FIELD_OFFSET(Structure, m_typeInfo.m_flags), X86::edx);
1393 m_slowCases.append(SlowCaseEntry(__ jnz(), i));
1394
1395 i += 2;
1396 break;
1397 }
1398 case op_profile_will_call: {
1399 emitGetCTIParam(CTI_ARGS_profilerReference, X86::eax);
1400 __ cmpl_i32m(0, X86::eax);
1401 JmpSrc noProfiler = __ je();
1402 emitPutCTIArgFromVirtualRegister(instruction[i + 1].u.operand, 0, X86::eax);
1403 emitCTICall(i, Interpreter::cti_op_profile_will_call);
1404 __ link(noProfiler, __ label());
1405
1406 i += 2;
1407 break;
1408 }
1409 case op_profile_did_call: {
1410 emitGetCTIParam(CTI_ARGS_profilerReference, X86::eax);
1411 __ cmpl_i32m(0, X86::eax);
1412 JmpSrc noProfiler = __ je();
1413 emitPutCTIArgFromVirtualRegister(instruction[i + 1].u.operand, 0, X86::eax);
1414 emitCTICall(i, Interpreter::cti_op_profile_did_call);
1415 __ link(noProfiler, __ label());
1416
1417 i += 2;
1418 break;
1419 }
1420 case op_get_array_length:
1421 case op_get_by_id_chain:
1422 case op_get_by_id_generic:
1423 case op_get_by_id_proto:
1424 case op_get_by_id_proto_list:
1425 case op_get_by_id_self:
1426 case op_get_by_id_self_list:
1427 case op_get_string_length:
1428 case op_put_by_id_generic:
1429 case op_put_by_id_replace:
1430 case op_put_by_id_transition:
1431 ASSERT_NOT_REACHED();
1432 }
1433 }
1434
1435 ASSERT(propertyAccessInstructionIndex == m_codeBlock->propertyAccessInstructions.size());
1436 ASSERT(callLinkInfoIndex == m_codeBlock->callLinkInfos.size());
1437}
1438
1439
1440void JIT::privateCompileLinkPass()
1441{
1442 unsigned jmpTableCount = m_jmpTable.size();
1443 for (unsigned i = 0; i < jmpTableCount; ++i)
1444 __ link(m_jmpTable[i].from, m_labels[m_jmpTable[i].to]);
1445 m_jmpTable.clear();
1446}
1447
1448#define CTI_COMPILE_BINARY_OP_SLOW_CASE(name) \
1449 case name: { \
1450 __ link(iter->from, __ label()); \
1451 emitPutCTIArgFromVirtualRegister(instruction[i + 2].u.operand, 0, X86::ecx); \
1452 emitPutCTIArgFromVirtualRegister(instruction[i + 3].u.operand, 4, X86::ecx); \
1453 emitCTICall(i, Interpreter::cti_##name); \
1454 emitPutVirtualRegister(instruction[i + 1].u.operand); \
1455 i += 4; \
1456 break; \
1457 }
1458
1459void JIT::privateCompileSlowCases()
1460{
1461 unsigned propertyAccessInstructionIndex = 0;
1462 unsigned callLinkInfoIndex = 0;
1463
1464 Instruction* instruction = m_codeBlock->instructions.begin();
1465 for (Vector<SlowCaseEntry>::iterator iter = m_slowCases.begin(); iter != m_slowCases.end(); ++iter) {
1466 // FIXME: enable peephole optimizations for slow cases when applicable
1467 killLastResultRegister();
1468
1469 unsigned i = iter->to;
1470#ifndef NDEBUG
1471 unsigned firstTo = i;
1472#endif
1473
1474 switch (OpcodeID opcodeID = m_interpreter->getOpcodeID(instruction[i].u.opcode)) {
1475 case op_convert_this: {
1476 __ link(iter->from, __ label());
1477 __ link((++iter)->from, __ label());
1478 emitPutCTIArg(X86::eax, 0);
1479 emitCTICall(i, Interpreter::cti_op_convert_this);
1480 emitPutVirtualRegister(instruction[i + 1].u.operand);
1481 i += 2;
1482 break;
1483 }
1484 case op_add: {
1485 unsigned dst = instruction[i + 1].u.operand;
1486 unsigned src1 = instruction[i + 2].u.operand;
1487 unsigned src2 = instruction[i + 3].u.operand;
1488 if (JSValue* value = getConstantImmediateNumericArg(src1)) {
1489 JmpSrc notImm = iter->from;
1490 __ link((++iter)->from, __ label());
1491 __ subl_i32r(getDeTaggedConstantImmediate(value), X86::eax);
1492 __ link(notImm, __ label());
1493 emitPutCTIArgFromVirtualRegister(src1, 0, X86::ecx);
1494 emitPutCTIArg(X86::eax, 4);
1495 emitCTICall(i, Interpreter::cti_op_add);
1496 emitPutVirtualRegister(dst);
1497 } else if (JSValue* value = getConstantImmediateNumericArg(src2)) {
1498 JmpSrc notImm = iter->from;
1499 __ link((++iter)->from, __ label());
1500 __ subl_i32r(getDeTaggedConstantImmediate(value), X86::eax);
1501 __ link(notImm, __ label());
1502 emitPutCTIArg(X86::eax, 0);
1503 emitPutCTIArgFromVirtualRegister(src2, 4, X86::ecx);
1504 emitCTICall(i, Interpreter::cti_op_add);
1505 emitPutVirtualRegister(dst);
1506 } else {
1507 OperandTypes types = OperandTypes::fromInt(instruction[i + 4].u.operand);
1508 if (types.first().mightBeNumber() && types.second().mightBeNumber())
1509 compileBinaryArithOpSlowCase(op_add, iter, dst, src1, src2, types, i);
1510 else
1511 ASSERT_NOT_REACHED();
1512 }
1513
1514 i += 5;
1515 break;
1516 }
1517 case op_get_by_val: {
1518 // The slow case that handles accesses to arrays (below) may jump back up to here.
1519 JmpDst beginGetByValSlow = __ label();
1520
1521 JmpSrc notImm = iter->from;
1522 __ link((++iter)->from, __ label());
1523 __ link((++iter)->from, __ label());
1524 emitFastArithIntToImmNoCheck(X86::edx);
1525 __ link(notImm, __ label());
1526 emitPutCTIArg(X86::eax, 0);
1527 emitPutCTIArg(X86::edx, 4);
1528 emitCTICall(i, Interpreter::cti_op_get_by_val);
1529 emitPutVirtualRegister(instruction[i + 1].u.operand);
1530 __ link(__ jmp(), m_labels[i + 4]);
1531
1532 // This is slow case that handles accesses to arrays above the fast cut-off.
1533 // First, check if this is an access to the vector
1534 __ link((++iter)->from, __ label());
1535 __ cmpl_rm(X86::edx, FIELD_OFFSET(ArrayStorage, m_vectorLength), X86::ecx);
1536 __ link(__ jbe(), beginGetByValSlow);
1537
1538 // okay, missed the fast region, but it is still in the vector. Get the value.
1539 __ movl_mr(FIELD_OFFSET(ArrayStorage, m_vector[0]), X86::ecx, X86::edx, sizeof(JSValue*), X86::ecx);
1540 // Check whether the value loaded is zero; if so we need to return undefined.
1541 __ testl_rr(X86::ecx, X86::ecx);
1542 __ link(__ je(), beginGetByValSlow);
1543 __ movl_rr(X86::ecx, X86::eax);
1544 emitPutVirtualRegister(instruction[i + 1].u.operand, X86::eax);
1545
1546 i += 4;
1547 break;
1548 }
1549 case op_sub: {
1550 compileBinaryArithOpSlowCase(op_sub, iter, instruction[i + 1].u.operand, instruction[i + 2].u.operand, instruction[i + 3].u.operand, OperandTypes::fromInt(instruction[i + 4].u.operand), i);
1551 i += 5;
1552 break;
1553 }
1554 case op_rshift: {
1555 unsigned src2 = instruction[i + 3].u.operand;
1556 __ link(iter->from, __ label());
1557 if (getConstantImmediateNumericArg(src2))
1558 emitPutCTIArgFromVirtualRegister(src2, 4, X86::ecx);
1559 else {
1560 __ link((++iter)->from, __ label());
1561 emitPutCTIArg(X86::ecx, 4);
1562 }
1563
1564 emitPutCTIArg(X86::eax, 0);
1565 emitCTICall(i, Interpreter::cti_op_rshift);
1566 emitPutVirtualRegister(instruction[i + 1].u.operand);
1567 i += 4;
1568 break;
1569 }
1570 case op_lshift: {
1571 JmpSrc notImm1 = iter->from;
1572 JmpSrc notImm2 = (++iter)->from;
1573 __ link((++iter)->from, __ label());
1574 emitGetVirtualRegisters(instruction[i + 2].u.operand, X86::eax, instruction[i + 3].u.operand, X86::ecx, i);
1575 __ link(notImm1, __ label());
1576 __ link(notImm2, __ label());
1577 emitPutCTIArg(X86::eax, 0);
1578 emitPutCTIArg(X86::ecx, 4);
1579 emitCTICall(i, Interpreter::cti_op_lshift);
1580 emitPutVirtualRegister(instruction[i + 1].u.operand);
1581 i += 4;
1582 break;
1583 }
1584 case op_loop_if_less: {
1585 unsigned target = instruction[i + 3].u.operand;
1586 JSValue* src2imm = getConstantImmediateNumericArg(instruction[i + 2].u.operand);
1587 if (src2imm) {
1588 __ link(iter->from, __ label());
1589 emitPutCTIArg(X86::eax, 0);
1590 emitPutCTIArgFromVirtualRegister(instruction[i + 2].u.operand, 4, X86::ecx);
1591 emitCTICall(i, Interpreter::cti_op_loop_if_less);
1592 __ testl_rr(X86::eax, X86::eax);
1593 __ link(__ jne(), m_labels[i + 3 + target]);
1594 } else {
1595 __ link(iter->from, __ label());
1596 __ link((++iter)->from, __ label());
1597 emitPutCTIArg(X86::eax, 0);
1598 emitPutCTIArg(X86::edx, 4);
1599 emitCTICall(i, Interpreter::cti_op_loop_if_less);
1600 __ testl_rr(X86::eax, X86::eax);
1601 __ link(__ jne(), m_labels[i + 3 + target]);
1602 }
1603 i += 4;
1604 break;
1605 }
1606 case op_put_by_id: {
1607 compilePutByIdSlowCase(instruction[i + 1].u.operand, &(m_codeBlock->identifiers[instruction[i + 2].u.operand]), instruction[i + 3].u.operand, i, iter, propertyAccessInstructionIndex++);
1608 i += 8;
1609 break;
1610 }
1611 case op_get_by_id: {
1612 compileGetByIdSlowCase(instruction[i + 1].u.operand, instruction[i + 2].u.operand, &(m_codeBlock->identifiers[instruction[i + 3].u.operand]), i, iter, propertyAccessInstructionIndex++);
1613 i += 8;
1614 break;
1615 }
1616 case op_loop_if_lesseq: {
1617 unsigned target = instruction[i + 3].u.operand;
1618 JSValue* src2imm = getConstantImmediateNumericArg(instruction[i + 2].u.operand);
1619 if (src2imm) {
1620 __ link(iter->from, __ label());
1621 emitPutCTIArg(X86::eax, 0);
1622 emitPutCTIArgFromVirtualRegister(instruction[i + 2].u.operand, 4, X86::ecx);
1623 emitCTICall(i, Interpreter::cti_op_loop_if_lesseq);
1624 __ testl_rr(X86::eax, X86::eax);
1625 __ link(__ jne(), m_labels[i + 3 + target]);
1626 } else {
1627 __ link(iter->from, __ label());
1628 __ link((++iter)->from, __ label());
1629 emitPutCTIArg(X86::eax, 0);
1630 emitPutCTIArg(X86::edx, 4);
1631 emitCTICall(i, Interpreter::cti_op_loop_if_lesseq);
1632 __ testl_rr(X86::eax, X86::eax);
1633 __ link(__ jne(), m_labels[i + 3 + target]);
1634 }
1635 i += 4;
1636 break;
1637 }
1638 case op_pre_inc: {
1639 unsigned srcDst = instruction[i + 1].u.operand;
1640 JmpSrc notImm = iter->from;
1641 __ link((++iter)->from, __ label());
1642 __ subl_i8r(getDeTaggedConstantImmediate(JSImmediate::oneImmediate()), X86::eax);
1643 __ link(notImm, __ label());
1644 emitPutCTIArg(X86::eax, 0);
1645 emitCTICall(i, Interpreter::cti_op_pre_inc);
1646 emitPutVirtualRegister(srcDst);
1647 i += 2;
1648 break;
1649 }
1650 case op_put_by_val: {
1651 // Normal slow cases - either is not an immediate imm, or is an array.
1652 JmpSrc notImm = iter->from;
1653 __ link((++iter)->from, __ label());
1654 __ link((++iter)->from, __ label());
1655 emitFastArithIntToImmNoCheck(X86::edx);
1656 __ link(notImm, __ label());
1657 emitGetVirtualRegister(instruction[i + 3].u.operand, X86::ecx, i);
1658 emitPutCTIArg(X86::eax, 0);
1659 emitPutCTIArg(X86::edx, 4);
1660 emitPutCTIArg(X86::ecx, 8);
1661 emitCTICall(i, Interpreter::cti_op_put_by_val);
1662 __ link(__ jmp(), m_labels[i + 4]);
1663
1664 // slow cases for immediate int accesses to arrays
1665 __ link((++iter)->from, __ label());
1666 __ link((++iter)->from, __ label());
1667 emitGetVirtualRegister(instruction[i + 3].u.operand, X86::ecx, i);
1668 emitPutCTIArg(X86::eax, 0);
1669 emitPutCTIArg(X86::edx, 4);
1670 emitPutCTIArg(X86::ecx, 8);
1671 emitCTICall(i, Interpreter::cti_op_put_by_val_array);
1672
1673 i += 4;
1674 break;
1675 }
1676 case op_loop_if_true: {
1677 __ link(iter->from, __ label());
1678 emitPutCTIArg(X86::eax, 0);
1679 emitCTICall(i, Interpreter::cti_op_jtrue);
1680 __ testl_rr(X86::eax, X86::eax);
1681 unsigned target = instruction[i + 2].u.operand;
1682 __ link(__ jne(), m_labels[i + 2 + target]);
1683 i += 3;
1684 break;
1685 }
1686 case op_pre_dec: {
1687 unsigned srcDst = instruction[i + 1].u.operand;
1688 JmpSrc notImm = iter->from;
1689 __ link((++iter)->from, __ label());
1690 __ addl_i8r(getDeTaggedConstantImmediate(JSImmediate::oneImmediate()), X86::eax);
1691 __ link(notImm, __ label());
1692 emitPutCTIArg(X86::eax, 0);
1693 emitCTICall(i, Interpreter::cti_op_pre_dec);
1694 emitPutVirtualRegister(srcDst);
1695 i += 2;
1696 break;
1697 }
1698 case op_jnless: {
1699 unsigned target = instruction[i + 3].u.operand;
1700 JSValue* src2imm = getConstantImmediateNumericArg(instruction[i + 2].u.operand);
1701 if (src2imm) {
1702 __ link(iter->from, __ label());
1703 emitPutCTIArg(X86::edx, 0);
1704 emitPutCTIArgFromVirtualRegister(instruction[i + 2].u.operand, 4, X86::ecx);
1705 emitCTICall(i, Interpreter::cti_op_jless);
1706 __ testl_rr(X86::eax, X86::eax);
1707 __ link(__ je(), m_labels[i + 3 + target]);
1708 } else {
1709 __ link(iter->from, __ label());
1710 __ link((++iter)->from, __ label());
1711 emitPutCTIArg(X86::eax, 0);
1712 emitPutCTIArg(X86::edx, 4);
1713 emitCTICall(i, Interpreter::cti_op_jless);
1714 __ testl_rr(X86::eax, X86::eax);
1715 __ link(__ je(), m_labels[i + 3 + target]);
1716 }
1717 i += 4;
1718 break;
1719 }
1720 case op_not: {
1721 __ link(iter->from, __ label());
1722 __ xorl_i8r(JSImmediate::FullTagTypeBool, X86::eax);
1723 emitPutCTIArg(X86::eax, 0);
1724 emitCTICall(i, Interpreter::cti_op_not);
1725 emitPutVirtualRegister(instruction[i + 1].u.operand);
1726 i += 3;
1727 break;
1728 }
1729 case op_jfalse: {
1730 __ link(iter->from, __ label());
1731 emitPutCTIArg(X86::eax, 0);
1732 emitCTICall(i, Interpreter::cti_op_jtrue);
1733 __ testl_rr(X86::eax, X86::eax);
1734 unsigned target = instruction[i + 2].u.operand;
1735 __ link(__ je(), m_labels[i + 2 + target]); // inverted!
1736 i += 3;
1737 break;
1738 }
1739 case op_post_inc: {
1740 unsigned srcDst = instruction[i + 2].u.operand;
1741 __ link(iter->from, __ label());
1742 __ link((++iter)->from, __ label());
1743 emitPutCTIArg(X86::eax, 0);
1744 emitCTICall(i, Interpreter::cti_op_post_inc);
1745 emitPutVirtualRegister(srcDst, X86::edx);
1746 emitPutVirtualRegister(instruction[i + 1].u.operand);
1747 i += 3;
1748 break;
1749 }
1750 case op_bitnot: {
1751 __ link(iter->from, __ label());
1752 emitPutCTIArg(X86::eax, 0);
1753 emitCTICall(i, Interpreter::cti_op_bitnot);
1754 emitPutVirtualRegister(instruction[i + 1].u.operand);
1755 i += 3;
1756 break;
1757 }
1758 case op_bitand: {
1759 unsigned src1 = instruction[i + 2].u.operand;
1760 unsigned src2 = instruction[i + 3].u.operand;
1761 unsigned dst = instruction[i + 1].u.operand;
1762 if (getConstantImmediateNumericArg(src1)) {
1763 __ link(iter->from, __ label());
1764 emitPutCTIArgFromVirtualRegister(src1, 0, X86::ecx);
1765 emitPutCTIArg(X86::eax, 4);
1766 emitCTICall(i, Interpreter::cti_op_bitand);
1767 emitPutVirtualRegister(dst);
1768 } else if (getConstantImmediateNumericArg(src2)) {
1769 __ link(iter->from, __ label());
1770 emitPutCTIArg(X86::eax, 0);
1771 emitPutCTIArgFromVirtualRegister(src2, 4, X86::ecx);
1772 emitCTICall(i, Interpreter::cti_op_bitand);
1773 emitPutVirtualRegister(dst);
1774 } else {
1775 __ link(iter->from, __ label());
1776 emitPutCTIArgFromVirtualRegister(src1, 0, X86::ecx);
1777 emitPutCTIArg(X86::edx, 4);
1778 emitCTICall(i, Interpreter::cti_op_bitand);
1779 emitPutVirtualRegister(dst);
1780 }
1781 i += 5;
1782 break;
1783 }
1784 case op_jtrue: {
1785 __ link(iter->from, __ label());
1786 emitPutCTIArg(X86::eax, 0);
1787 emitCTICall(i, Interpreter::cti_op_jtrue);
1788 __ testl_rr(X86::eax, X86::eax);
1789 unsigned target = instruction[i + 2].u.operand;
1790 __ link(__ jne(), m_labels[i + 2 + target]);
1791 i += 3;
1792 break;
1793 }
1794 case op_post_dec: {
1795 unsigned srcDst = instruction[i + 2].u.operand;
1796 __ link(iter->from, __ label());
1797 __ link((++iter)->from, __ label());
1798 emitPutCTIArg(X86::eax, 0);
1799 emitCTICall(i, Interpreter::cti_op_post_dec);
1800 emitPutVirtualRegister(srcDst, X86::edx);
1801 emitPutVirtualRegister(instruction[i + 1].u.operand);
1802 i += 3;
1803 break;
1804 }
1805 case op_bitxor: {
1806 __ link(iter->from, __ label());
1807 emitPutCTIArg(X86::eax, 0);
1808 emitPutCTIArg(X86::edx, 4);
1809 emitCTICall(i, Interpreter::cti_op_bitxor);
1810 emitPutVirtualRegister(instruction[i + 1].u.operand);
1811 i += 5;
1812 break;
1813 }
1814 case op_bitor: {
1815 __ link(iter->from, __ label());
1816 emitPutCTIArg(X86::eax, 0);
1817 emitPutCTIArg(X86::edx, 4);
1818 emitCTICall(i, Interpreter::cti_op_bitor);
1819 emitPutVirtualRegister(instruction[i + 1].u.operand);
1820 i += 5;
1821 break;
1822 }
1823 case op_eq: {
1824 __ link(iter->from, __ label());
1825 emitPutCTIArg(X86::eax, 0);
1826 emitPutCTIArg(X86::edx, 4);
1827 emitCTICall(i, Interpreter::cti_op_eq);
1828 emitPutVirtualRegister(instruction[i + 1].u.operand);
1829 i += 4;
1830 break;
1831 }
1832 case op_neq: {
1833 __ link(iter->from, __ label());
1834 emitPutCTIArg(X86::eax, 0);
1835 emitPutCTIArg(X86::edx, 4);
1836 emitCTICall(i, Interpreter::cti_op_neq);
1837 emitPutVirtualRegister(instruction[i + 1].u.operand);
1838 i += 4;
1839 break;
1840 }
1841 case op_stricteq: {
1842 __ link(iter->from, __ label());
1843 __ link((++iter)->from, __ label());
1844 __ link((++iter)->from, __ label());
1845 emitPutCTIArg(X86::eax, 0);
1846 emitPutCTIArg(X86::edx, 4);
1847 emitCTICall(i, Interpreter::cti_op_stricteq);
1848 emitPutVirtualRegister(instruction[i + 1].u.operand);
1849 i += 4;
1850 break;
1851 }
1852 case op_nstricteq: {
1853 __ link(iter->from, __ label());
1854 __ link((++iter)->from, __ label());
1855 __ link((++iter)->from, __ label());
1856 emitPutCTIArg(X86::eax, 0);
1857 emitPutCTIArg(X86::edx, 4);
1858 emitCTICall(i, Interpreter::cti_op_nstricteq);
1859 emitPutVirtualRegister(instruction[i + 1].u.operand);
1860 i += 4;
1861 break;
1862 }
1863 case op_instanceof: {
1864 __ link(iter->from, __ label());
1865 __ link((++iter)->from, __ label());
1866 __ link((++iter)->from, __ label());
1867 emitPutCTIArgFromVirtualRegister(instruction[i + 2].u.operand, 0, X86::ecx);
1868 emitPutCTIArgFromVirtualRegister(instruction[i + 3].u.operand, 4, X86::ecx);
1869 emitPutCTIArgFromVirtualRegister(instruction[i + 4].u.operand, 8, X86::ecx);
1870 emitCTICall(i, Interpreter::cti_op_instanceof);
1871 emitPutVirtualRegister(instruction[i + 1].u.operand);
1872 i += 5;
1873 break;
1874 }
1875 case op_mod: {
1876 JmpSrc notImm1 = iter->from;
1877 JmpSrc notImm2 = (++iter)->from;
1878 __ link((++iter)->from, __ label());
1879 emitFastArithReTagImmediate(X86::eax);
1880 emitFastArithReTagImmediate(X86::ecx);
1881 __ link(notImm1, __ label());
1882 __ link(notImm2, __ label());
1883 emitPutCTIArg(X86::eax, 0);
1884 emitPutCTIArg(X86::ecx, 4);
1885 emitCTICall(i, Interpreter::cti_op_mod);
1886 emitPutVirtualRegister(instruction[i + 1].u.operand);
1887 i += 4;
1888 break;
1889 }
1890 case op_mul: {
1891 int dst = instruction[i + 1].u.operand;
1892 int src1 = instruction[i + 2].u.operand;
1893 int src2 = instruction[i + 3].u.operand;
1894 JSValue* src1Value = getConstantImmediateNumericArg(src1);
1895 JSValue* src2Value = getConstantImmediateNumericArg(src2);
1896 int32_t value;
1897 if (src1Value && ((value = JSImmediate::intValue(src1Value)) > 0)) {
1898 __ link(iter->from, __ label());
1899 __ link((++iter)->from, __ label());
1900 // There is an extra slow case for (op1 * -N) or (-N * op2), to check for 0 since this should produce a result of -0.
1901 emitPutCTIArgFromVirtualRegister(src1, 0, X86::ecx);
1902 emitPutCTIArgFromVirtualRegister(src2, 4, X86::ecx);
1903 emitCTICall(i, Interpreter::cti_op_mul);
1904 emitPutVirtualRegister(dst);
1905 } else if (src2Value && ((value = JSImmediate::intValue(src2Value)) > 0)) {
1906 __ link(iter->from, __ label());
1907 __ link((++iter)->from, __ label());
1908 // There is an extra slow case for (op1 * -N) or (-N * op2), to check for 0 since this should produce a result of -0.
1909 emitPutCTIArgFromVirtualRegister(src1, 0, X86::ecx);
1910 emitPutCTIArgFromVirtualRegister(src2, 4, X86::ecx);
1911 emitCTICall(i, Interpreter::cti_op_mul);
1912 emitPutVirtualRegister(dst);
1913 } else
1914 compileBinaryArithOpSlowCase(op_mul, iter, dst, src1, src2, OperandTypes::fromInt(instruction[i + 4].u.operand), i);
1915 i += 5;
1916 break;
1917 }
1918
1919 case op_call:
1920 case op_call_eval:
1921 case op_construct: {
1922 compileOpCallSlowCase(instruction + i, i, iter, callLinkInfoIndex++, opcodeID);
1923 i += (opcodeID == op_construct ? 7 : 5);
1924 break;
1925 }
1926 case op_to_jsnumber: {
1927 if (linkSlowCaseIfNotJSCell(iter, instruction[i + 2].u.operand))
1928 ++iter;
1929 __ link(iter->from, __ label());
1930
1931 emitPutCTIArg(X86::eax, 0);
1932 emitCTICall(i, Interpreter::cti_op_to_jsnumber);
1933
1934 emitPutVirtualRegister(instruction[i + 1].u.operand);
1935 i += 3;
1936 break;
1937 }
1938
1939 default:
1940 ASSERT_NOT_REACHED();
1941 break;
1942 }
1943
1944 ASSERT_WITH_MESSAGE((iter + 1) == m_slowCases.end() || firstTo != (iter + 1)->to,"Not enough jumps linked in slow case codegen.");
1945 ASSERT_WITH_MESSAGE(firstTo == iter->to, "Too many jumps linked in slow case codegen.");
1946
1947 __ link(__ jmp(), m_labels[i]);
1948 }
1949
1950 ASSERT(propertyAccessInstructionIndex == m_codeBlock->propertyAccessInstructions.size());
1951 ASSERT(callLinkInfoIndex == m_codeBlock->callLinkInfos.size());
1952}
1953
1954void JIT::privateCompile()
1955{
1956#if ENABLE(CODEBLOCK_SAMPLING)
1957 __ movl_i32m(reinterpret_cast<unsigned>(m_codeBlock), m_interpreter->sampler()->codeBlockSlot());
1958#endif
1959#if ENABLE(OPCODE_SAMPLING)
1960 __ movl_i32m(m_interpreter->sampler()->encodeSample(m_codeBlock->instructions.begin()), m_interpreter->sampler()->sampleSlot());
1961#endif
1962
1963 // Could use a popl_m, but would need to offset the following instruction if so.
1964 __ popl_r(X86::ecx);
1965 emitPutToCallFrameHeader(X86::ecx, RegisterFile::ReturnPC);
1966
1967 JmpSrc slowRegisterFileCheck;
1968 JmpDst afterRegisterFileCheck;
1969 if (m_codeBlock->codeType == FunctionCode) {
1970 // In the case of a fast linked call, we do not set this up in the caller.
1971 emitPutImmediateToCallFrameHeader(m_codeBlock, RegisterFile::CodeBlock);
1972
1973 emitGetCTIParam(CTI_ARGS_registerFile, X86::eax);
1974 __ leal_mr(m_codeBlock->numCalleeRegisters * sizeof(Register), X86::edi, X86::edx);
1975 __ cmpl_mr(FIELD_OFFSET(RegisterFile, m_end), X86::eax, X86::edx);
1976 slowRegisterFileCheck = __ jg();
1977 afterRegisterFileCheck = __ label();
1978 }
1979
1980 privateCompileMainPass();
1981 privateCompileLinkPass();
1982 privateCompileSlowCases();
1983
1984 if (m_codeBlock->codeType == FunctionCode) {
1985 __ link(slowRegisterFileCheck, __ label());
1986 emitCTICall(0, Interpreter::cti_register_file_check);
1987 JmpSrc backToBody = __ jmp();
1988 __ link(backToBody, afterRegisterFileCheck);
1989 }
1990
1991 ASSERT(m_jmpTable.isEmpty());
1992
1993 void* code = __ executableCopy();
1994
1995 // Translate vPC offsets into addresses in JIT generated code, for switch tables.
1996 for (unsigned i = 0; i < m_switches.size(); ++i) {
1997 SwitchRecord record = m_switches[i];
1998 unsigned bytecodeIndex = record.bytecodeIndex;
1999
2000 if (record.type != SwitchRecord::String) {
2001 ASSERT(record.type == SwitchRecord::Immediate || record.type == SwitchRecord::Character);
2002 ASSERT(record.jumpTable.simpleJumpTable->branchOffsets.size() == record.jumpTable.simpleJumpTable->ctiOffsets.size());
2003
2004 record.jumpTable.simpleJumpTable->ctiDefault = __ getRelocatedAddress(code, m_labels[bytecodeIndex + 3 + record.defaultOffset]);
2005
2006 for (unsigned j = 0; j < record.jumpTable.simpleJumpTable->branchOffsets.size(); ++j) {
2007 unsigned offset = record.jumpTable.simpleJumpTable->branchOffsets[j];
2008 record.jumpTable.simpleJumpTable->ctiOffsets[j] = offset ? __ getRelocatedAddress(code, m_labels[bytecodeIndex + 3 + offset]) : record.jumpTable.simpleJumpTable->ctiDefault;
2009 }
2010 } else {
2011 ASSERT(record.type == SwitchRecord::String);
2012
2013 record.jumpTable.stringJumpTable->ctiDefault = __ getRelocatedAddress(code, m_labels[bytecodeIndex + 3 + record.defaultOffset]);
2014
2015 StringJumpTable::StringOffsetTable::iterator end = record.jumpTable.stringJumpTable->offsetTable.end();
2016 for (StringJumpTable::StringOffsetTable::iterator it = record.jumpTable.stringJumpTable->offsetTable.begin(); it != end; ++it) {
2017 unsigned offset = it->second.branchOffset;
2018 it->second.ctiOffset = offset ? __ getRelocatedAddress(code, m_labels[bytecodeIndex + 3 + offset]) : record.jumpTable.stringJumpTable->ctiDefault;
2019 }
2020 }
2021 }
2022
2023 for (Vector<HandlerInfo>::iterator iter = m_codeBlock->exceptionHandlers.begin(); iter != m_codeBlock->exceptionHandlers.end(); ++iter)
2024 iter->nativeCode = __ getRelocatedAddress(code, m_labels[iter->target]);
2025
2026 for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter) {
2027 if (iter->to)
2028 X86Assembler::link(code, iter->from, iter->to);
2029 m_codeBlock->ctiReturnAddressVPCMap.add(__ getRelocatedAddress(code, iter->from), iter->bytecodeIndex);
2030 }
2031
2032 // Link absolute addresses for jsr
2033 for (Vector<JSRInfo>::iterator iter = m_jsrSites.begin(); iter != m_jsrSites.end(); ++iter)
2034 X86Assembler::linkAbsoluteAddress(code, iter->addrPosition, iter->target);
2035
2036 for (unsigned i = 0; i < m_codeBlock->propertyAccessInstructions.size(); ++i) {
2037 StructureStubInfo& info = m_codeBlock->propertyAccessInstructions[i];
2038 info.callReturnLocation = X86Assembler::getRelocatedAddress(code, m_propertyAccessCompilationInfo[i].callReturnLocation);
2039 info.hotPathBegin = X86Assembler::getRelocatedAddress(code, m_propertyAccessCompilationInfo[i].hotPathBegin);
2040 }
2041 for (unsigned i = 0; i < m_codeBlock->callLinkInfos.size(); ++i) {
2042 CallLinkInfo& info = m_codeBlock->callLinkInfos[i];
2043 info.callReturnLocation = X86Assembler::getRelocatedAddress(code, m_callStructureStubCompilationInfo[i].callReturnLocation);
2044 info.hotPathBegin = X86Assembler::getRelocatedAddress(code, m_callStructureStubCompilationInfo[i].hotPathBegin);
2045 info.hotPathOther = X86Assembler::getRelocatedAddress(code, m_callStructureStubCompilationInfo[i].hotPathOther);
2046 info.coldPathOther = X86Assembler::getRelocatedAddress(code, m_callStructureStubCompilationInfo[i].coldPathOther);
2047 }
2048
2049 m_codeBlock->ctiCode = code;
2050}
2051
2052void JIT::privateCompileCTIMachineTrampolines()
2053{
2054 // (1) The first function provides fast property access for array length
2055
2056 // Check eax is an array
2057 JmpSrc array_failureCases1 = emitJumpIfNotJSCell(X86::eax);
2058 __ cmpl_i32m(reinterpret_cast<unsigned>(m_interpreter->m_jsArrayVptr), X86::eax);
2059 JmpSrc array_failureCases2 = __ jne();
2060
2061 // Checks out okay! - get the length from the storage
2062 __ movl_mr(FIELD_OFFSET(JSArray, m_storage), X86::eax, X86::eax);
2063 __ movl_mr(FIELD_OFFSET(ArrayStorage, m_length), X86::eax, X86::eax);
2064
2065 __ cmpl_i32r(JSImmediate::maxImmediateInt, X86::eax);
2066 JmpSrc array_failureCases3 = __ ja();
2067
2068 __ addl_rr(X86::eax, X86::eax);
2069 __ addl_i8r(1, X86::eax);
2070
2071 __ ret();
2072
2073 // (2) The second function provides fast property access for string length
2074
2075 JmpDst stringLengthBegin = __ align(16);
2076
2077 // Check eax is a string
2078 JmpSrc string_failureCases1 = emitJumpIfNotJSCell(X86::eax);
2079 __ cmpl_i32m(reinterpret_cast<unsigned>(m_interpreter->m_jsStringVptr), X86::eax);
2080 JmpSrc string_failureCases2 = __ jne();
2081
2082 // Checks out okay! - get the length from the Ustring.
2083 __ movl_mr(FIELD_OFFSET(JSString, m_value) + FIELD_OFFSET(UString, m_rep), X86::eax, X86::eax);
2084 __ movl_mr(FIELD_OFFSET(UString::Rep, len), X86::eax, X86::eax);
2085
2086 __ cmpl_i32r(JSImmediate::maxImmediateInt, X86::eax);
2087 JmpSrc string_failureCases3 = __ ja();
2088
2089 __ addl_rr(X86::eax, X86::eax);
2090 __ addl_i8r(1, X86::eax);
2091
2092 __ ret();
2093
2094 // (3) Trampolines for the slow cases of op_call / op_call_eval / op_construct.
2095
2096 JmpDst virtualCallPreLinkBegin = __ align(16);
2097
2098 // Load the callee CodeBlock* into eax
2099 __ movl_mr(FIELD_OFFSET(JSFunction, m_body), X86::ecx, X86::eax);
2100 __ movl_mr(FIELD_OFFSET(FunctionBodyNode, m_code), X86::eax, X86::eax);
2101 __ testl_rr(X86::eax, X86::eax);
2102 JmpSrc hasCodeBlock1 = __ jne();
2103 __ popl_r(X86::ebx);
2104 restoreArgumentReference();
2105 emitPutCTIParam(X86::edi, CTI_ARGS_callFrame);
2106 JmpSrc callJSFunction1 = __ call();
2107 emitGetCTIArg(0, X86::ecx);
2108 emitGetCTIArg(8, X86::edx);
2109 __ pushl_r(X86::ebx);
2110 __ link(hasCodeBlock1, __ label());
2111
2112 // Check argCount matches callee arity.
2113 __ cmpl_rm(X86::edx, FIELD_OFFSET(CodeBlock, numParameters), X86::eax);
2114 JmpSrc arityCheckOkay1 = __ je();
2115 __ popl_r(X86::ebx);
2116 emitPutCTIArg(X86::ebx, 4);
2117 emitPutCTIArg(X86::eax, 12);
2118 restoreArgumentReference();
2119 emitPutCTIParam(X86::edi, CTI_ARGS_callFrame);
2120 JmpSrc callArityCheck1 = __ call();
2121 __ movl_rr(X86::edx, X86::edi);
2122 emitGetCTIArg(0, X86::ecx);
2123 emitGetCTIArg(8, X86::edx);
2124 __ pushl_r(X86::ebx);
2125 __ link(arityCheckOkay1, __ label());
2126
2127 compileOpCallInitializeCallFrame();
2128
2129 __ popl_r(X86::ebx);
2130 emitPutCTIArg(X86::ebx, 4);
2131 restoreArgumentReference();
2132 emitPutCTIParam(X86::edi, CTI_ARGS_callFrame);
2133 JmpSrc callDontLazyLinkCall = __ call();
2134 __ pushl_r(X86::ebx);
2135
2136 __ jmp_r(X86::eax);
2137
2138 JmpDst virtualCallLinkBegin = __ align(16);
2139
2140 // Load the callee CodeBlock* into eax
2141 __ movl_mr(FIELD_OFFSET(JSFunction, m_body), X86::ecx, X86::eax);
2142 __ movl_mr(FIELD_OFFSET(FunctionBodyNode, m_code), X86::eax, X86::eax);
2143 __ testl_rr(X86::eax, X86::eax);
2144 JmpSrc hasCodeBlock2 = __ jne();
2145 __ popl_r(X86::ebx);
2146 restoreArgumentReference();
2147 emitPutCTIParam(X86::edi, CTI_ARGS_callFrame);
2148 JmpSrc callJSFunction2 = __ call();
2149 emitGetCTIArg(0, X86::ecx);
2150 emitGetCTIArg(8, X86::edx);
2151 __ pushl_r(X86::ebx);
2152 __ link(hasCodeBlock2, __ label());
2153
2154 // Check argCount matches callee arity.
2155 __ cmpl_rm(X86::edx, FIELD_OFFSET(CodeBlock, numParameters), X86::eax);
2156 JmpSrc arityCheckOkay2 = __ je();
2157 __ popl_r(X86::ebx);
2158 emitPutCTIArg(X86::ebx, 4);
2159 emitPutCTIArg(X86::eax, 12);
2160 restoreArgumentReference();
2161 emitPutCTIParam(X86::edi, CTI_ARGS_callFrame);
2162 JmpSrc callArityCheck2 = __ call();
2163 __ movl_rr(X86::edx, X86::edi);
2164 emitGetCTIArg(0, X86::ecx);
2165 emitGetCTIArg(8, X86::edx);
2166 __ pushl_r(X86::ebx);
2167 __ link(arityCheckOkay2, __ label());
2168
2169 compileOpCallInitializeCallFrame();
2170
2171 __ popl_r(X86::ebx);
2172 emitPutCTIArg(X86::ebx, 4);
2173 restoreArgumentReference();
2174 emitPutCTIParam(X86::edi, CTI_ARGS_callFrame);
2175 JmpSrc callLazyLinkCall = __ call();
2176 __ pushl_r(X86::ebx);
2177
2178 __ jmp_r(X86::eax);
2179
2180 JmpDst virtualCallBegin = __ align(16);
2181
2182 // Load the callee CodeBlock* into eax
2183 __ movl_mr(FIELD_OFFSET(JSFunction, m_body), X86::ecx, X86::eax);
2184 __ movl_mr(FIELD_OFFSET(FunctionBodyNode, m_code), X86::eax, X86::eax);
2185 __ testl_rr(X86::eax, X86::eax);
2186 JmpSrc hasCodeBlock3 = __ jne();
2187 __ popl_r(X86::ebx);
2188 restoreArgumentReference();
2189 emitPutCTIParam(X86::edi, CTI_ARGS_callFrame);
2190 JmpSrc callJSFunction3 = __ call();
2191 emitGetCTIArg(0, X86::ecx);
2192 emitGetCTIArg(8, X86::edx);
2193 __ pushl_r(X86::ebx);
2194 __ link(hasCodeBlock3, __ label());
2195
2196 // Check argCount matches callee arity.
2197 __ cmpl_rm(X86::edx, FIELD_OFFSET(CodeBlock, numParameters), X86::eax);
2198 JmpSrc arityCheckOkay3 = __ je();
2199 __ popl_r(X86::ebx);
2200 emitPutCTIArg(X86::ebx, 4);
2201 emitPutCTIArg(X86::eax, 12);
2202 restoreArgumentReference();
2203 emitPutCTIParam(X86::edi, CTI_ARGS_callFrame);
2204 JmpSrc callArityCheck3 = __ call();
2205 __ movl_rr(X86::edx, X86::edi);
2206 emitGetCTIArg(0, X86::ecx);
2207 emitGetCTIArg(8, X86::edx);
2208 __ pushl_r(X86::ebx);
2209 __ link(arityCheckOkay3, __ label());
2210
2211 compileOpCallInitializeCallFrame();
2212
2213 // load ctiCode from the new codeBlock.
2214 __ movl_mr(FIELD_OFFSET(CodeBlock, ctiCode), X86::eax, X86::eax);
2215
2216 __ jmp_r(X86::eax);
2217
2218 // All trampolines constructed! copy the code, link up calls, and set the pointers on the Machine object.
2219
2220 void* code = __ executableCopy();
2221
2222 X86Assembler::link(code, array_failureCases1, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_array_fail));
2223 X86Assembler::link(code, array_failureCases2, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_array_fail));
2224 X86Assembler::link(code, array_failureCases3, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_array_fail));
2225 X86Assembler::link(code, string_failureCases1, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_string_fail));
2226 X86Assembler::link(code, string_failureCases2, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_string_fail));
2227 X86Assembler::link(code, string_failureCases3, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_string_fail));
2228 X86Assembler::link(code, callArityCheck1, reinterpret_cast<void*>(Interpreter::cti_op_call_arityCheck));
2229 X86Assembler::link(code, callArityCheck2, reinterpret_cast<void*>(Interpreter::cti_op_call_arityCheck));
2230 X86Assembler::link(code, callArityCheck3, reinterpret_cast<void*>(Interpreter::cti_op_call_arityCheck));
2231 X86Assembler::link(code, callJSFunction1, reinterpret_cast<void*>(Interpreter::cti_op_call_JSFunction));
2232 X86Assembler::link(code, callJSFunction2, reinterpret_cast<void*>(Interpreter::cti_op_call_JSFunction));
2233 X86Assembler::link(code, callJSFunction3, reinterpret_cast<void*>(Interpreter::cti_op_call_JSFunction));
2234 X86Assembler::link(code, callDontLazyLinkCall, reinterpret_cast<void*>(Interpreter::cti_vm_dontLazyLinkCall));
2235 X86Assembler::link(code, callLazyLinkCall, reinterpret_cast<void*>(Interpreter::cti_vm_lazyLinkCall));
2236
2237 m_interpreter->m_ctiArrayLengthTrampoline = code;
2238 m_interpreter->m_ctiStringLengthTrampoline = X86Assembler::getRelocatedAddress(code, stringLengthBegin);
2239 m_interpreter->m_ctiVirtualCallPreLink = X86Assembler::getRelocatedAddress(code, virtualCallPreLinkBegin);
2240 m_interpreter->m_ctiVirtualCallLink = X86Assembler::getRelocatedAddress(code, virtualCallLinkBegin);
2241 m_interpreter->m_ctiVirtualCall = X86Assembler::getRelocatedAddress(code, virtualCallBegin);
2242}
2243
2244void JIT::freeCTIMachineTrampolines(Interpreter* interpreter)
2245{
2246 WTF::fastFreeExecutable(interpreter->m_ctiArrayLengthTrampoline);
2247}
2248
2249void JIT::emitGetVariableObjectRegister(RegisterID variableObject, int index, RegisterID dst)
2250{
2251 __ movl_mr(FIELD_OFFSET(JSVariableObject, d), variableObject, dst);
2252 __ movl_mr(FIELD_OFFSET(JSVariableObject::JSVariableObjectData, registers), dst, dst);
2253 __ movl_mr(index * sizeof(Register), dst, dst);
2254}
2255
2256void JIT::emitPutVariableObjectRegister(RegisterID src, RegisterID variableObject, int index)
2257{
2258 __ movl_mr(FIELD_OFFSET(JSVariableObject, d), variableObject, variableObject);
2259 __ movl_mr(FIELD_OFFSET(JSVariableObject::JSVariableObjectData, registers), variableObject, variableObject);
2260 __ movl_rm(src, index * sizeof(Register), variableObject);
2261}
2262
2263} // namespace JSC
2264
2265#endif // ENABLE(JIT)
Note: See TracBrowser for help on using the repository browser.