]> git.saurik.com Git - apple/javascriptcore.git/blame - llint/LowLevelInterpreter64.asm
JavaScriptCore-1097.3.3.tar.gz
[apple/javascriptcore.git] / llint / LowLevelInterpreter64.asm
CommitLineData
6fe7ccc8
A
1# Copyright (C) 2011, 2012 Apple Inc. All rights reserved.
2#
3# Redistribution and use in source and binary forms, with or without
4# modification, are permitted provided that the following conditions
5# are met:
6# 1. Redistributions of source code must retain the above copyright
7# notice, this list of conditions and the following disclaimer.
8# 2. Redistributions in binary form must reproduce the above copyright
9# notice, this list of conditions and the following disclaimer in the
10# documentation and/or other materials provided with the distribution.
11#
12# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
13# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
14# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
15# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
16# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
17# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
18# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
19# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
20# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
21# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
22# THE POSSIBILITY OF SUCH DAMAGE.
23
24
25# Some value representation constants.
26const TagBitTypeOther = 0x2
27const TagBitBool = 0x4
28const TagBitUndefined = 0x8
29const ValueEmpty = 0x0
30const ValueFalse = TagBitTypeOther | TagBitBool
31const ValueTrue = TagBitTypeOther | TagBitBool | 1
32const ValueUndefined = TagBitTypeOther | TagBitUndefined
33const ValueNull = TagBitTypeOther
34
35# Utilities.
36macro dispatch(advance)
37 addp advance, PC
38 jmp [PB, PC, 8]
39end
40
41macro dispatchInt(advance)
42 addi advance, PC
43 jmp [PB, PC, 8]
44end
45
46macro dispatchAfterCall()
47 loadi ArgumentCount + TagOffset[cfr], PC
48 loadp CodeBlock[cfr], PB
49 loadp CodeBlock::m_instructions[PB], PB
50 jmp [PB, PC, 8]
51end
52
53macro cCall2(function, arg1, arg2)
54 move arg1, t5
55 move arg2, t4
56 call function
57end
58
59# This barely works. arg3 and arg4 should probably be immediates.
60macro cCall4(function, arg1, arg2, arg3, arg4)
61 move arg1, t5
62 move arg2, t4
63 move arg3, t1
64 move arg4, t2
65 call function
66end
67
68macro prepareStateForCCall()
69 leap [PB, PC, 8], PC
70 move PB, t3
71end
72
73macro restoreStateAfterCCall()
74 move t0, PC
75 move t1, cfr
76 move t3, PB
77 subp PB, PC
78 urshiftp 3, PC
79end
80
81macro callSlowPath(slowPath)
82 prepareStateForCCall()
83 cCall2(slowPath, cfr, PC)
84 restoreStateAfterCCall()
85end
86
87macro traceOperand(fromWhere, operand)
88 prepareStateForCCall()
89 cCall4(_llint_trace_operand, cfr, PC, fromWhere, operand)
90 restoreStateAfterCCall()
91end
92
93macro traceValue(fromWhere, operand)
94 prepareStateForCCall()
95 cCall4(_llint_trace_value, cfr, PC, fromWhere, operand)
96 restoreStateAfterCCall()
97end
98
99# Call a slow path for call call opcodes.
100macro callCallSlowPath(advance, slowPath, action)
101 addi advance, PC, t0
102 storei t0, ArgumentCount + TagOffset[cfr]
103 prepareStateForCCall()
104 cCall2(slowPath, cfr, PC)
105 move t1, cfr
106 action(t0)
107end
108
109macro checkSwitchToJITForLoop()
110 checkSwitchToJIT(
111 1,
112 macro()
113 storei PC, ArgumentCount + TagOffset[cfr]
114 prepareStateForCCall()
115 cCall2(_llint_loop_osr, cfr, PC)
116 move t1, cfr
117 btpz t0, .recover
118 jmp t0
119 .recover:
120 move t3, PB
121 loadi ArgumentCount + TagOffset[cfr], PC
122 end)
123end
124
125# Index and value must be different registers. Index may be clobbered.
126macro loadConstantOrVariable(index, value)
127 bpgteq index, FirstConstantRegisterIndex, .constant
128 loadp [cfr, index, 8], value
129 jmp .done
130.constant:
131 loadp CodeBlock[cfr], value
132 loadp CodeBlock::m_constantRegisters + VectorBufferOffset[value], value
133 subp FirstConstantRegisterIndex, index
134 loadp [value, index, 8], value
135.done:
136end
137
138macro loadConstantOrVariableInt32(index, value, slow)
139 loadConstantOrVariable(index, value)
140 bpb value, tagTypeNumber, slow
141end
142
143macro loadConstantOrVariableCell(index, value, slow)
144 loadConstantOrVariable(index, value)
145 btpnz value, tagMask, slow
146end
147
148macro writeBarrier(value)
149 # Nothing to do, since we don't have a generational or incremental collector.
150end
151
152macro valueProfile(value, profile)
153 if VALUE_PROFILER
154 storep value, ValueProfile::m_buckets[profile]
155 end
156end
157
158
159# Entrypoints into the interpreter.
160
161# Expects that CodeBlock is in t1, which is what prologue() leaves behind.
162macro functionArityCheck(doneLabel, slow_path)
163 loadi PayloadOffset + ArgumentCount[cfr], t0
164 biaeq t0, CodeBlock::m_numParameters[t1], doneLabel
165 prepareStateForCCall()
166 cCall2(slow_path, cfr, PC) # This slow_path has a simple protocol: t0 = 0 => no error, t0 != 0 => error
167 move t1, cfr
168 btiz t0, .continue
169 loadp JITStackFrame::globalData[sp], t1
170 loadp JSGlobalData::callFrameForThrow[t1], t0
171 jmp JSGlobalData::targetMachinePCForThrow[t1]
172.continue:
173 # Reload CodeBlock and reset PC, since the slow_path clobbered them.
174 loadp CodeBlock[cfr], t1
175 loadp CodeBlock::m_instructions[t1], PB
176 move 0, PC
177 jmp doneLabel
178end
179
180
181# Instruction implementations
182
183_llint_op_enter:
184 traceExecution()
185 loadp CodeBlock[cfr], t2
186 loadi CodeBlock::m_numVars[t2], t2
187 btiz t2, .opEnterDone
188 move ValueUndefined, t0
189.opEnterLoop:
190 subi 1, t2
191 storep t0, [cfr, t2, 8]
192 btinz t2, .opEnterLoop
193.opEnterDone:
194 dispatch(1)
195
196
197_llint_op_create_activation:
198 traceExecution()
199 loadis 8[PB, PC, 8], t0
200 bpneq [cfr, t0, 8], ValueEmpty, .opCreateActivationDone
201 callSlowPath(_llint_slow_path_create_activation)
202.opCreateActivationDone:
203 dispatch(2)
204
205
206_llint_op_init_lazy_reg:
207 traceExecution()
208 loadis 8[PB, PC, 8], t0
209 storep ValueEmpty, [cfr, t0, 8]
210 dispatch(2)
211
212
213_llint_op_create_arguments:
214 traceExecution()
215 loadis 8[PB, PC, 8], t0
216 bpneq [cfr, t0, 8], ValueEmpty, .opCreateArgumentsDone
217 callSlowPath(_llint_slow_path_create_arguments)
218.opCreateArgumentsDone:
219 dispatch(2)
220
221
222_llint_op_create_this:
223 traceExecution()
224 loadis 16[PB, PC, 8], t0
225 assertNotConstant(t0)
226 loadp [cfr, t0, 8], t0
227 btpnz t0, tagMask, .opCreateThisSlow
228 loadp JSCell::m_structure[t0], t1
229 bbb Structure::m_typeInfo + TypeInfo::m_type[t1], ObjectType, .opCreateThisSlow
230 loadp JSObject::m_inheritorID[t0], t2
231 btpz t2, .opCreateThisSlow
232 allocateBasicJSObject(JSFinalObjectSizeClassIndex, JSGlobalData::jsFinalObjectClassInfo, t2, t0, t1, t3, .opCreateThisSlow)
233 loadis 8[PB, PC, 8], t1
234 storep t0, [cfr, t1, 8]
235 dispatch(3)
236
237.opCreateThisSlow:
238 callSlowPath(_llint_slow_path_create_this)
239 dispatch(3)
240
241
242_llint_op_get_callee:
243 traceExecution()
244 loadis 8[PB, PC, 8], t0
245 loadp Callee[cfr], t1
246 storep t1, [cfr, t0, 8]
247 dispatch(2)
248
249
250_llint_op_convert_this:
251 traceExecution()
252 loadis 8[PB, PC, 8], t0
253 loadp [cfr, t0, 8], t0
254 btpnz t0, tagMask, .opConvertThisSlow
255 loadp JSCell::m_structure[t0], t0
256 bbb Structure::m_typeInfo + TypeInfo::m_type[t0], ObjectType, .opConvertThisSlow
257 dispatch(2)
258
259.opConvertThisSlow:
260 callSlowPath(_llint_slow_path_convert_this)
261 dispatch(2)
262
263
264_llint_op_new_object:
265 traceExecution()
266 loadp CodeBlock[cfr], t0
267 loadp CodeBlock::m_globalObject[t0], t0
268 loadp JSGlobalObject::m_emptyObjectStructure[t0], t1
269 allocateBasicJSObject(JSFinalObjectSizeClassIndex, JSGlobalData::jsFinalObjectClassInfo, t1, t0, t2, t3, .opNewObjectSlow)
270 loadis 8[PB, PC, 8], t1
271 storep t0, [cfr, t1, 8]
272 dispatch(2)
273
274.opNewObjectSlow:
275 callSlowPath(_llint_slow_path_new_object)
276 dispatch(2)
277
278
279_llint_op_mov:
280 traceExecution()
281 loadis 16[PB, PC, 8], t1
282 loadis 8[PB, PC, 8], t0
283 loadConstantOrVariable(t1, t2)
284 storep t2, [cfr, t0, 8]
285 dispatch(3)
286
287
288_llint_op_not:
289 traceExecution()
290 loadis 16[PB, PC, 8], t0
291 loadis 8[PB, PC, 8], t1
292 loadConstantOrVariable(t0, t2)
293 xorp ValueFalse, t2
294 btpnz t2, ~1, .opNotSlow
295 xorp ValueTrue, t2
296 storep t2, [cfr, t1, 8]
297 dispatch(3)
298
299.opNotSlow:
300 callSlowPath(_llint_slow_path_not)
301 dispatch(3)
302
303
304macro equalityComparison(integerComparison, slowPath)
305 traceExecution()
306 loadis 24[PB, PC, 8], t0
307 loadis 16[PB, PC, 8], t2
308 loadis 8[PB, PC, 8], t3
309 loadConstantOrVariableInt32(t0, t1, .slow)
310 loadConstantOrVariableInt32(t2, t0, .slow)
311 integerComparison(t0, t1, t0)
312 orp ValueFalse, t0
313 storep t0, [cfr, t3, 8]
314 dispatch(4)
315
316.slow:
317 callSlowPath(slowPath)
318 dispatch(4)
319end
320
321_llint_op_eq:
322 equalityComparison(
323 macro (left, right, result) cieq left, right, result end,
324 _llint_slow_path_eq)
325
326
327_llint_op_neq:
328 equalityComparison(
329 macro (left, right, result) cineq left, right, result end,
330 _llint_slow_path_neq)
331
332
333macro equalNullComparison()
334 loadis 16[PB, PC, 8], t0
335 loadp [cfr, t0, 8], t0
336 btpnz t0, tagMask, .immediate
337 loadp JSCell::m_structure[t0], t2
338 tbnz Structure::m_typeInfo + TypeInfo::m_flags[t2], MasqueradesAsUndefined, t0
339 jmp .done
340.immediate:
341 andp ~TagBitUndefined, t0
342 cpeq t0, ValueNull, t0
343.done:
344end
345
346_llint_op_eq_null:
347 traceExecution()
348 equalNullComparison()
349 loadis 8[PB, PC, 8], t1
350 orp ValueFalse, t0
351 storep t0, [cfr, t1, 8]
352 dispatch(3)
353
354
355_llint_op_neq_null:
356 traceExecution()
357 equalNullComparison()
358 loadis 8[PB, PC, 8], t1
359 xorp ValueTrue, t0
360 storep t0, [cfr, t1, 8]
361 dispatch(3)
362
363
364macro strictEq(equalityOperation, slowPath)
365 traceExecution()
366 loadis 24[PB, PC, 8], t0
367 loadis 16[PB, PC, 8], t2
368 loadConstantOrVariable(t0, t1)
369 loadConstantOrVariable(t2, t0)
370 move t0, t2
371 orp t1, t2
372 btpz t2, tagMask, .slow
373 bpaeq t0, tagTypeNumber, .leftOK
374 btpnz t0, tagTypeNumber, .slow
375.leftOK:
376 bpaeq t1, tagTypeNumber, .rightOK
377 btpnz t1, tagTypeNumber, .slow
378.rightOK:
379 equalityOperation(t0, t1, t0)
380 loadis 8[PB, PC, 8], t1
381 orp ValueFalse, t0
382 storep t0, [cfr, t1, 8]
383 dispatch(4)
384
385.slow:
386 callSlowPath(slowPath)
387 dispatch(4)
388end
389
390_llint_op_stricteq:
391 strictEq(
392 macro (left, right, result) cpeq left, right, result end,
393 _llint_slow_path_stricteq)
394
395
396_llint_op_nstricteq:
397 strictEq(
398 macro (left, right, result) cpneq left, right, result end,
399 _llint_slow_path_nstricteq)
400
401
402macro preOp(arithmeticOperation, slowPath)
403 traceExecution()
404 loadis 8[PB, PC, 8], t0
405 loadp [cfr, t0, 8], t1
406 bpb t1, tagTypeNumber, .slow
407 arithmeticOperation(t1, .slow)
408 orp tagTypeNumber, t1
409 storep t1, [cfr, t0, 8]
410 dispatch(2)
411
412.slow:
413 callSlowPath(slowPath)
414 dispatch(2)
415end
416
417_llint_op_pre_inc:
418 preOp(
419 macro (value, slow) baddio 1, value, slow end,
420 _llint_slow_path_pre_inc)
421
422
423_llint_op_pre_dec:
424 preOp(
425 macro (value, slow) bsubio 1, value, slow end,
426 _llint_slow_path_pre_dec)
427
428
429macro postOp(arithmeticOperation, slowPath)
430 traceExecution()
431 loadis 16[PB, PC, 8], t0
432 loadis 8[PB, PC, 8], t1
433 loadp [cfr, t0, 8], t2
434 bieq t0, t1, .done
435 bpb t2, tagTypeNumber, .slow
436 move t2, t3
437 arithmeticOperation(t3, .slow)
438 orp tagTypeNumber, t3
439 storep t2, [cfr, t1, 8]
440 storep t3, [cfr, t0, 8]
441.done:
442 dispatch(3)
443
444.slow:
445 callSlowPath(slowPath)
446 dispatch(3)
447end
448
449_llint_op_post_inc:
450 postOp(
451 macro (value, slow) baddio 1, value, slow end,
452 _llint_slow_path_post_inc)
453
454
455_llint_op_post_dec:
456 postOp(
457 macro (value, slow) bsubio 1, value, slow end,
458 _llint_slow_path_post_dec)
459
460
461_llint_op_to_jsnumber:
462 traceExecution()
463 loadis 16[PB, PC, 8], t0
464 loadis 8[PB, PC, 8], t1
465 loadConstantOrVariable(t0, t2)
466 bpaeq t2, tagTypeNumber, .opToJsnumberIsImmediate
467 btpz t2, tagTypeNumber, .opToJsnumberSlow
468.opToJsnumberIsImmediate:
469 storep t2, [cfr, t1, 8]
470 dispatch(3)
471
472.opToJsnumberSlow:
473 callSlowPath(_llint_slow_path_to_jsnumber)
474 dispatch(3)
475
476
477_llint_op_negate:
478 traceExecution()
479 loadis 16[PB, PC, 8], t0
480 loadis 8[PB, PC, 8], t1
481 loadConstantOrVariable(t0, t2)
482 bpb t2, tagTypeNumber, .opNegateNotInt
483 btiz t2, 0x7fffffff, .opNegateSlow
484 negi t2
485 orp tagTypeNumber, t2
486 storep t2, [cfr, t1, 8]
487 dispatch(3)
488.opNegateNotInt:
489 btpz t2, tagTypeNumber, .opNegateSlow
490 xorp 0x8000000000000000, t2
491 storep t2, [cfr, t1, 8]
492 dispatch(3)
493
494.opNegateSlow:
495 callSlowPath(_llint_slow_path_negate)
496 dispatch(3)
497
498
499macro binaryOpCustomStore(integerOperationAndStore, doubleOperation, slowPath)
500 loadis 24[PB, PC, 8], t0
501 loadis 16[PB, PC, 8], t2
502 loadConstantOrVariable(t0, t1)
503 loadConstantOrVariable(t2, t0)
504 bpb t0, tagTypeNumber, .op1NotInt
505 bpb t1, tagTypeNumber, .op2NotInt
506 loadis 8[PB, PC, 8], t2
507 integerOperationAndStore(t1, t0, .slow, t2)
508 dispatch(5)
509
510.op1NotInt:
511 # First operand is definitely not an int, the second operand could be anything.
512 btpz t0, tagTypeNumber, .slow
513 bpaeq t1, tagTypeNumber, .op1NotIntOp2Int
514 btpz t1, tagTypeNumber, .slow
515 addp tagTypeNumber, t1
516 fp2d t1, ft1
517 jmp .op1NotIntReady
518.op1NotIntOp2Int:
519 ci2d t1, ft1
520.op1NotIntReady:
521 loadis 8[PB, PC, 8], t2
522 addp tagTypeNumber, t0
523 fp2d t0, ft0
524 doubleOperation(ft1, ft0)
525 fd2p ft0, t0
526 subp tagTypeNumber, t0
527 storep t0, [cfr, t2, 8]
528 dispatch(5)
529
530.op2NotInt:
531 # First operand is definitely an int, the second is definitely not.
532 loadis 8[PB, PC, 8], t2
533 btpz t1, tagTypeNumber, .slow
534 ci2d t0, ft0
535 addp tagTypeNumber, t1
536 fp2d t1, ft1
537 doubleOperation(ft1, ft0)
538 fd2p ft0, t0
539 subp tagTypeNumber, t0
540 storep t0, [cfr, t2, 8]
541 dispatch(5)
542
543.slow:
544 callSlowPath(slowPath)
545 dispatch(5)
546end
547
548macro binaryOp(integerOperation, doubleOperation, slowPath)
549 binaryOpCustomStore(
550 macro (left, right, slow, index)
551 integerOperation(left, right, slow)
552 orp tagTypeNumber, right
553 storep right, [cfr, index, 8]
554 end,
555 doubleOperation, slowPath)
556end
557
558_llint_op_add:
559 traceExecution()
560 binaryOp(
561 macro (left, right, slow) baddio left, right, slow end,
562 macro (left, right) addd left, right end,
563 _llint_slow_path_add)
564
565
566_llint_op_mul:
567 traceExecution()
568 binaryOpCustomStore(
569 macro (left, right, slow, index)
570 # Assume t3 is scratchable.
571 move right, t3
572 bmulio left, t3, slow
573 btinz t3, .done
574 bilt left, 0, slow
575 bilt right, 0, slow
576 .done:
577 orp tagTypeNumber, t3
578 storep t3, [cfr, index, 8]
579 end,
580 macro (left, right) muld left, right end,
581 _llint_slow_path_mul)
582
583
584_llint_op_sub:
585 traceExecution()
586 binaryOp(
587 macro (left, right, slow) bsubio left, right, slow end,
588 macro (left, right) subd left, right end,
589 _llint_slow_path_sub)
590
591
592_llint_op_div:
593 traceExecution()
594 binaryOpCustomStore(
595 macro (left, right, slow, index)
596 # Assume t3 is scratchable.
597 btiz left, slow
598 bineq left, -1, .notNeg2TwoThe31DivByNeg1
599 bieq right, -2147483648, .slow
600 .notNeg2TwoThe31DivByNeg1:
601 btinz right, .intOK
602 bilt left, 0, slow
603 .intOK:
604 move left, t3
605 move right, t0
606 cdqi
607 idivi t3
608 btinz t1, slow
609 orp tagTypeNumber, t0
610 storep t0, [cfr, index, 8]
611 end,
612 macro (left, right) divd left, right end,
613 _llint_slow_path_div)
614
615
616macro bitOp(operation, slowPath, advance)
617 loadis 24[PB, PC, 8], t0
618 loadis 16[PB, PC, 8], t2
619 loadis 8[PB, PC, 8], t3
620 loadConstantOrVariable(t0, t1)
621 loadConstantOrVariable(t2, t0)
622 bpb t0, tagTypeNumber, .slow
623 bpb t1, tagTypeNumber, .slow
624 operation(t1, t0, .slow)
625 orp tagTypeNumber, t0
626 storep t0, [cfr, t3, 8]
627 dispatch(advance)
628
629.slow:
630 callSlowPath(slowPath)
631 dispatch(advance)
632end
633
634_llint_op_lshift:
635 traceExecution()
636 bitOp(
637 macro (left, right, slow) lshifti left, right end,
638 _llint_slow_path_lshift,
639 4)
640
641
642_llint_op_rshift:
643 traceExecution()
644 bitOp(
645 macro (left, right, slow) rshifti left, right end,
646 _llint_slow_path_rshift,
647 4)
648
649
650_llint_op_urshift:
651 traceExecution()
652 bitOp(
653 macro (left, right, slow)
654 urshifti left, right
655 bilt right, 0, slow
656 end,
657 _llint_slow_path_urshift,
658 4)
659
660
661_llint_op_bitand:
662 traceExecution()
663 bitOp(
664 macro (left, right, slow) andi left, right end,
665 _llint_slow_path_bitand,
666 5)
667
668
669_llint_op_bitxor:
670 traceExecution()
671 bitOp(
672 macro (left, right, slow) xori left, right end,
673 _llint_slow_path_bitxor,
674 5)
675
676
677_llint_op_bitor:
678 traceExecution()
679 bitOp(
680 macro (left, right, slow) ori left, right end,
681 _llint_slow_path_bitor,
682 5)
683
684
685_llint_op_check_has_instance:
686 traceExecution()
687 loadis 8[PB, PC, 8], t1
688 loadConstantOrVariableCell(t1, t0, .opCheckHasInstanceSlow)
689 loadp JSCell::m_structure[t0], t0
690 btbz Structure::m_typeInfo + TypeInfo::m_flags[t0], ImplementsHasInstance, .opCheckHasInstanceSlow
691 dispatch(2)
692
693.opCheckHasInstanceSlow:
694 callSlowPath(_llint_slow_path_check_has_instance)
695 dispatch(2)
696
697
698_llint_op_instanceof:
699 traceExecution()
700 # Check that baseVal implements the default HasInstance behavior.
701 # FIXME: This should be deprecated.
702 loadis 24[PB, PC, 8], t1
703 loadConstantOrVariable(t1, t0)
704 loadp JSCell::m_structure[t0], t0
705 btbz Structure::m_typeInfo + TypeInfo::m_flags[t0], ImplementsDefaultHasInstance, .opInstanceofSlow
706
707 # Actually do the work.
708 loadis 32[PB, PC, 8], t0
709 loadis 8[PB, PC, 8], t3
710 loadConstantOrVariableCell(t0, t1, .opInstanceofSlow)
711 loadp JSCell::m_structure[t1], t2
712 bbb Structure::m_typeInfo + TypeInfo::m_type[t2], ObjectType, .opInstanceofSlow
713 loadis 16[PB, PC, 8], t0
714 loadConstantOrVariableCell(t0, t2, .opInstanceofSlow)
715
716 # Register state: t1 = prototype, t2 = value
717 move 1, t0
718.opInstanceofLoop:
719 loadp JSCell::m_structure[t2], t2
720 loadp Structure::m_prototype[t2], t2
721 bpeq t2, t1, .opInstanceofDone
722 btpz t2, tagMask, .opInstanceofLoop
723
724 move 0, t0
725.opInstanceofDone:
726 orp ValueFalse, t0
727 storep t0, [cfr, t3, 8]
728 dispatch(5)
729
730.opInstanceofSlow:
731 callSlowPath(_llint_slow_path_instanceof)
732 dispatch(5)
733
734
735_llint_op_is_undefined:
736 traceExecution()
737 loadis 16[PB, PC, 8], t1
738 loadis 8[PB, PC, 8], t2
739 loadConstantOrVariable(t1, t0)
740 btpz t0, tagMask, .opIsUndefinedCell
741 cpeq t0, ValueUndefined, t3
742 orp ValueFalse, t3
743 storep t3, [cfr, t2, 8]
744 dispatch(3)
745.opIsUndefinedCell:
746 loadp JSCell::m_structure[t0], t0
747 tbnz Structure::m_typeInfo + TypeInfo::m_flags[t0], MasqueradesAsUndefined, t1
748 orp ValueFalse, t1
749 storep t1, [cfr, t2, 8]
750 dispatch(3)
751
752
753_llint_op_is_boolean:
754 traceExecution()
755 loadis 16[PB, PC, 8], t1
756 loadis 8[PB, PC, 8], t2
757 loadConstantOrVariable(t1, t0)
758 xorp ValueFalse, t0
759 tpz t0, ~1, t0
760 orp ValueFalse, t0
761 storep t0, [cfr, t2, 8]
762 dispatch(3)
763
764
765_llint_op_is_number:
766 traceExecution()
767 loadis 16[PB, PC, 8], t1
768 loadis 8[PB, PC, 8], t2
769 loadConstantOrVariable(t1, t0)
770 tpnz t0, tagTypeNumber, t1
771 orp ValueFalse, t1
772 storep t1, [cfr, t2, 8]
773 dispatch(3)
774
775
776_llint_op_is_string:
777 traceExecution()
778 loadis 16[PB, PC, 8], t1
779 loadis 8[PB, PC, 8], t2
780 loadConstantOrVariable(t1, t0)
781 btpnz t0, tagMask, .opIsStringNotCell
782 loadp JSCell::m_structure[t0], t0
783 cbeq Structure::m_typeInfo + TypeInfo::m_type[t0], StringType, t1
784 orp ValueFalse, t1
785 storep t1, [cfr, t2, 8]
786 dispatch(3)
787.opIsStringNotCell:
788 storep ValueFalse, [cfr, t2, 8]
789 dispatch(3)
790
791
792macro resolveGlobal(size, slow)
793 # Operands are as follows:
794 # 8[PB, PC, 8] Destination for the load.
795 # 16[PB, PC, 8] Property identifier index in the code block.
796 # 24[PB, PC, 8] Structure pointer, initialized to 0 by bytecode generator.
797 # 32[PB, PC, 8] Offset in global object, initialized to 0 by bytecode generator.
798 loadp CodeBlock[cfr], t0
799 loadp CodeBlock::m_globalObject[t0], t0
800 loadp JSCell::m_structure[t0], t1
801 bpneq t1, 24[PB, PC, 8], slow
802 loadis 32[PB, PC, 8], t1
803 loadp JSObject::m_propertyStorage[t0], t0
804 loadp [t0, t1, 8], t2
805 loadis 8[PB, PC, 8], t0
806 storep t2, [cfr, t0, 8]
807 loadp (size - 1) * 8[PB, PC, 8], t0
808 valueProfile(t2, t0)
809end
810
811_llint_op_resolve_global:
812 traceExecution()
813 resolveGlobal(6, .opResolveGlobalSlow)
814 dispatch(6)
815
816.opResolveGlobalSlow:
817 callSlowPath(_llint_slow_path_resolve_global)
818 dispatch(6)
819
820
821# Gives you the scope in t0, while allowing you to optionally perform additional checks on the
822# scopes as they are traversed. scopeCheck() is called with two arguments: the register
823# holding the scope, and a register that can be used for scratch. Note that this does not
824# use t3, so you can hold stuff in t3 if need be.
825macro getScope(deBruijinIndexOperand, scopeCheck)
826 loadp ScopeChain[cfr], t0
827 loadis deBruijinIndexOperand, t2
828
829 btiz t2, .done
830
831 loadp CodeBlock[cfr], t1
832 bineq CodeBlock::m_codeType[t1], FunctionCode, .loop
833 btbz CodeBlock::m_needsFullScopeChain[t1], .loop
834
835 loadis CodeBlock::m_activationRegister[t1], t1
836
837 # Need to conditionally skip over one scope.
838 btpz [cfr, t1, 8], .noActivation
839 scopeCheck(t0, t1)
840 loadp ScopeChainNode::next[t0], t0
841.noActivation:
842 subi 1, t2
843
844 btiz t2, .done
845.loop:
846 scopeCheck(t0, t1)
847 loadp ScopeChainNode::next[t0], t0
848 subi 1, t2
849 btinz t2, .loop
850
851.done:
852end
853
854_llint_op_resolve_global_dynamic:
855 traceExecution()
856 loadp JITStackFrame::globalData[sp], t3
857 loadp JSGlobalData::activationStructure[t3], t3
858 getScope(
859 40[PB, PC, 8],
860 macro (scope, scratch)
861 loadp ScopeChainNode::object[scope], scratch
862 bpneq JSCell::m_structure[scratch], t3, .opResolveGlobalDynamicSuperSlow
863 end)
864 resolveGlobal(7, .opResolveGlobalDynamicSlow)
865 dispatch(7)
866
867.opResolveGlobalDynamicSuperSlow:
868 callSlowPath(_llint_slow_path_resolve_for_resolve_global_dynamic)
869 dispatch(7)
870
871.opResolveGlobalDynamicSlow:
872 callSlowPath(_llint_slow_path_resolve_global_dynamic)
873 dispatch(7)
874
875
876_llint_op_get_scoped_var:
877 traceExecution()
878 # Operands are as follows:
879 # 8[PB, PC, 8] Destination for the load
880 # 16[PB, PC, 8] Index of register in the scope
881 # 24[PB, PC, 8] De Bruijin index.
882 getScope(24[PB, PC, 8], macro (scope, scratch) end)
883 loadis 8[PB, PC, 8], t1
884 loadis 16[PB, PC, 8], t2
885 loadp ScopeChainNode::object[t0], t0
886 loadp JSVariableObject::m_registers[t0], t0
887 loadp [t0, t2, 8], t3
888 storep t3, [cfr, t1, 8]
889 loadp 32[PB, PC, 8], t1
890 valueProfile(t3, t1)
891 dispatch(5)
892
893
894_llint_op_put_scoped_var:
895 traceExecution()
896 getScope(16[PB, PC, 8], macro (scope, scratch) end)
897 loadis 24[PB, PC, 8], t1
898 loadConstantOrVariable(t1, t3)
899 loadis 8[PB, PC, 8], t1
900 writeBarrier(t3)
901 loadp ScopeChainNode::object[t0], t0
902 loadp JSVariableObject::m_registers[t0], t0
903 storep t3, [t0, t1, 8]
904 dispatch(4)
905
906
907_llint_op_get_global_var:
908 traceExecution()
909 loadis 16[PB, PC, 8], t1
910 loadis 8[PB, PC, 8], t3
911 loadp CodeBlock[cfr], t0
912 loadp CodeBlock::m_globalObject[t0], t0
913 loadp JSGlobalObject::m_registers[t0], t0
914 loadp [t0, t1, 8], t2
915 storep t2, [cfr, t3, 8]
916 loadp 24[PB, PC, 8], t3
917 valueProfile(t2, t3)
918 dispatch(4)
919
920
921_llint_op_put_global_var:
922 traceExecution()
923 loadis 16[PB, PC, 8], t1
924 loadp CodeBlock[cfr], t0
925 loadp CodeBlock::m_globalObject[t0], t0
926 loadp JSGlobalObject::m_registers[t0], t0
927 loadConstantOrVariable(t1, t2)
928 loadis 8[PB, PC, 8], t1
929 writeBarrier(t2)
930 storep t2, [t0, t1, 8]
931 dispatch(3)
932
933
934_llint_op_get_by_id:
935 traceExecution()
936 # We only do monomorphic get_by_id caching for now, and we do not modify the
937 # opcode. We do, however, allow for the cache to change anytime if fails, since
938 # ping-ponging is free. At best we get lucky and the get_by_id will continue
939 # to take fast path on the new cache. At worst we take slow path, which is what
940 # we would have been doing anyway.
941 loadis 16[PB, PC, 8], t0
942 loadp 32[PB, PC, 8], t1
943 loadConstantOrVariableCell(t0, t3, .opGetByIdSlow)
944 loadis 40[PB, PC, 8], t2
945 loadp JSObject::m_propertyStorage[t3], t0
946 bpneq JSCell::m_structure[t3], t1, .opGetByIdSlow
947 loadis 8[PB, PC, 8], t1
948 loadp [t0, t2], t3
949 storep t3, [cfr, t1, 8]
950 loadp 64[PB, PC, 8], t1
951 valueProfile(t3, t1)
952 dispatch(9)
953
954.opGetByIdSlow:
955 callSlowPath(_llint_slow_path_get_by_id)
956 dispatch(9)
957
958
959_llint_op_get_arguments_length:
960 traceExecution()
961 loadis 16[PB, PC, 8], t0
962 loadis 8[PB, PC, 8], t1
963 btpnz [cfr, t0, 8], .opGetArgumentsLengthSlow
964 loadi ArgumentCount + PayloadOffset[cfr], t2
965 subi 1, t2
966 orp tagTypeNumber, t2
967 storep t2, [cfr, t1, 8]
968 dispatch(4)
969
970.opGetArgumentsLengthSlow:
971 callSlowPath(_llint_slow_path_get_arguments_length)
972 dispatch(4)
973
974
975_llint_op_put_by_id:
976 traceExecution()
977 loadis 8[PB, PC, 8], t3
978 loadp 32[PB, PC, 8], t1
979 loadConstantOrVariableCell(t3, t0, .opPutByIdSlow)
980 loadis 24[PB, PC, 8], t2
981 loadp JSObject::m_propertyStorage[t0], t3
982 bpneq JSCell::m_structure[t0], t1, .opPutByIdSlow
983 loadis 40[PB, PC, 8], t1
984 loadConstantOrVariable(t2, t0)
985 writeBarrier(t0)
986 storep t0, [t3, t1]
987 dispatch(9)
988
989.opPutByIdSlow:
990 callSlowPath(_llint_slow_path_put_by_id)
991 dispatch(9)
992
993
994macro putByIdTransition(additionalChecks)
995 traceExecution()
996 loadis 8[PB, PC, 8], t3
997 loadp 32[PB, PC, 8], t1
998 loadConstantOrVariableCell(t3, t0, .opPutByIdSlow)
999 loadis 24[PB, PC, 8], t2
1000 bpneq JSCell::m_structure[t0], t1, .opPutByIdSlow
1001 additionalChecks(t1, t3, .opPutByIdSlow)
1002 loadis 40[PB, PC, 8], t1
1003 loadp JSObject::m_propertyStorage[t0], t3
1004 addp t1, t3
1005 loadConstantOrVariable(t2, t1)
1006 writeBarrier(t1)
1007 storep t1, [t3]
1008 loadp 48[PB, PC, 8], t1
1009 storep t1, JSCell::m_structure[t0]
1010 dispatch(9)
1011end
1012
1013_llint_op_put_by_id_transition_direct:
1014 putByIdTransition(macro (oldStructure, scratch, slow) end)
1015
1016
1017_llint_op_put_by_id_transition_normal:
1018 putByIdTransition(
1019 macro (oldStructure, scratch, slow)
1020 const protoCell = oldStructure # Reusing the oldStructure register for the proto
1021 loadp 56[PB, PC, 8], scratch
1022 assert(macro (ok) btpnz scratch, ok end)
1023 loadp StructureChain::m_vector[scratch], scratch
1024 assert(macro (ok) btpnz scratch, ok end)
1025 bpeq Structure::m_prototype[oldStructure], ValueNull, .done
1026 .loop:
1027 loadp Structure::m_prototype[oldStructure], protoCell
1028 loadp JSCell::m_structure[protoCell], oldStructure
1029 bpneq oldStructure, [scratch], slow
1030 addp 8, scratch
1031 bpneq Structure::m_prototype[oldStructure], ValueNull, .loop
1032 .done:
1033 end)
1034
1035
1036_llint_op_get_by_val:
1037 traceExecution()
1038 loadp CodeBlock[cfr], t1
1039 loadis 16[PB, PC, 8], t2
1040 loadis 24[PB, PC, 8], t3
1041 loadp CodeBlock::m_globalData[t1], t1
1042 loadConstantOrVariableCell(t2, t0, .opGetByValSlow)
1043 loadp JSGlobalData::jsArrayClassInfo[t1], t2
1044 loadConstantOrVariableInt32(t3, t1, .opGetByValSlow)
1045 sxi2p t1, t1
1046 bpneq [t0], t2, .opGetByValSlow
1047 loadp JSArray::m_storage[t0], t3
1048 biaeq t1, JSArray::m_vectorLength[t0], .opGetByValSlow
1049 loadis 8[PB, PC, 8], t0
1050 loadp ArrayStorage::m_vector[t3, t1, 8], t2
1051 btpz t2, .opGetByValSlow
1052 storep t2, [cfr, t0, 8]
1053 loadp 32[PB, PC, 8], t0
1054 valueProfile(t2, t0)
1055 dispatch(5)
1056
1057.opGetByValSlow:
1058 callSlowPath(_llint_slow_path_get_by_val)
1059 dispatch(5)
1060
1061
1062_llint_op_get_argument_by_val:
1063 traceExecution()
1064 loadis 16[PB, PC, 8], t0
1065 loadis 24[PB, PC, 8], t1
1066 btpnz [cfr, t0, 8], .opGetArgumentByValSlow
1067 loadConstantOrVariableInt32(t1, t2, .opGetArgumentByValSlow)
1068 addi 1, t2
1069 loadi ArgumentCount + PayloadOffset[cfr], t1
1070 biaeq t2, t1, .opGetArgumentByValSlow
1071 negi t2
1072 sxi2p t2, t2
1073 loadis 8[PB, PC, 8], t3
1074 loadp ThisArgumentOffset[cfr, t2, 8], t0
1075 storep t0, [cfr, t3, 8]
1076 dispatch(5)
1077
1078.opGetArgumentByValSlow:
1079 callSlowPath(_llint_slow_path_get_argument_by_val)
1080 dispatch(5)
1081
1082
1083_llint_op_get_by_pname:
1084 traceExecution()
1085 loadis 24[PB, PC, 8], t1
1086 loadConstantOrVariable(t1, t0)
1087 loadis 32[PB, PC, 8], t1
1088 assertNotConstant(t1)
1089 bpneq t0, [cfr, t1, 8], .opGetByPnameSlow
1090 loadis 16[PB, PC, 8], t2
1091 loadis 40[PB, PC, 8], t3
1092 loadConstantOrVariableCell(t2, t0, .opGetByPnameSlow)
1093 assertNotConstant(t3)
1094 loadp [cfr, t3, 8], t1
1095 loadp JSCell::m_structure[t0], t2
1096 bpneq t2, JSPropertyNameIterator::m_cachedStructure[t1], .opGetByPnameSlow
1097 loadis 48[PB, PC, 8], t3
1098 loadi PayloadOffset[cfr, t3, 8], t3
1099 subi 1, t3
1100 biaeq t3, JSPropertyNameIterator::m_numCacheableSlots[t1], .opGetByPnameSlow
1101 loadp JSObject::m_propertyStorage[t0], t0
1102 loadp [t0, t3, 8], t0
1103 loadis 8[PB, PC, 8], t1
1104 storep t0, [cfr, t1, 8]
1105 dispatch(7)
1106
1107.opGetByPnameSlow:
1108 callSlowPath(_llint_slow_path_get_by_pname)
1109 dispatch(7)
1110
1111
1112_llint_op_put_by_val:
1113 traceExecution()
1114 loadis 8[PB, PC, 8], t0
1115 loadConstantOrVariableCell(t0, t1, .opPutByValSlow)
1116 loadis 16[PB, PC, 8], t0
1117 loadConstantOrVariableInt32(t0, t2, .opPutByValSlow)
1118 sxi2p t2, t2
1119 loadp CodeBlock[cfr], t0
1120 loadp CodeBlock::m_globalData[t0], t0
1121 loadp JSGlobalData::jsArrayClassInfo[t0], t0
1122 bpneq [t1], t0, .opPutByValSlow
1123 biaeq t2, JSArray::m_vectorLength[t1], .opPutByValSlow
1124 loadp JSArray::m_storage[t1], t0
1125 btpz ArrayStorage::m_vector[t0, t2, 8], .opPutByValEmpty
1126.opPutByValStoreResult:
1127 loadis 24[PB, PC, 8], t3
1128 loadConstantOrVariable(t3, t1)
1129 writeBarrier(t1)
1130 storep t1, ArrayStorage::m_vector[t0, t2, 8]
1131 dispatch(4)
1132
1133.opPutByValEmpty:
1134 addi 1, ArrayStorage::m_numValuesInVector[t0]
1135 bib t2, ArrayStorage::m_length[t0], .opPutByValStoreResult
1136 addi 1, t2, t1
1137 storei t1, ArrayStorage::m_length[t0]
1138 jmp .opPutByValStoreResult
1139
1140.opPutByValSlow:
1141 callSlowPath(_llint_slow_path_put_by_val)
1142 dispatch(4)
1143
1144
1145_llint_op_loop:
1146 nop
1147_llint_op_jmp:
1148 traceExecution()
1149 dispatchInt(8[PB, PC, 8])
1150
1151
1152macro jumpTrueOrFalse(conditionOp, slow)
1153 loadis 8[PB, PC, 8], t1
1154 loadConstantOrVariable(t1, t0)
1155 xorp ValueFalse, t0
1156 btpnz t0, -1, .slow
1157 conditionOp(t0, .target)
1158 dispatch(3)
1159
1160.target:
1161 dispatchInt(16[PB, PC, 8])
1162
1163.slow:
1164 callSlowPath(slow)
1165 dispatch(0)
1166end
1167
1168
1169macro equalNull(cellHandler, immediateHandler)
1170 loadis 8[PB, PC, 8], t0
1171 assertNotConstant(t0)
1172 loadp [cfr, t0, 8], t0
1173 btpnz t0, tagMask, .immediate
1174 loadp JSCell::m_structure[t0], t2
1175 cellHandler(Structure::m_typeInfo + TypeInfo::m_flags[t2], .target)
1176 dispatch(3)
1177
1178.target:
1179 dispatch(16[PB, PC, 8])
1180
1181.immediate:
1182 andp ~TagBitUndefined, t0
1183 immediateHandler(t0, .target)
1184 dispatch(3)
1185end
1186
1187_llint_op_jeq_null:
1188 traceExecution()
1189 equalNull(
1190 macro (value, target) btbnz value, MasqueradesAsUndefined, target end,
1191 macro (value, target) bpeq value, ValueNull, target end)
1192
1193
1194_llint_op_jneq_null:
1195 traceExecution()
1196 equalNull(
1197 macro (value, target) btbz value, MasqueradesAsUndefined, target end,
1198 macro (value, target) bpneq value, ValueNull, target end)
1199
1200
1201_llint_op_jneq_ptr:
1202 traceExecution()
1203 loadis 8[PB, PC, 8], t0
1204 loadp 16[PB, PC, 8], t1
1205 bpneq t1, [cfr, t0, 8], .opJneqPtrTarget
1206 dispatch(4)
1207
1208.opJneqPtrTarget:
1209 dispatchInt(24[PB, PC, 8])
1210
1211
1212macro compare(integerCompare, doubleCompare, slowPath)
1213 loadis 8[PB, PC, 8], t2
1214 loadis 16[PB, PC, 8], t3
1215 loadConstantOrVariable(t2, t0)
1216 loadConstantOrVariable(t3, t1)
1217 bpb t0, tagTypeNumber, .op1NotInt
1218 bpb t1, tagTypeNumber, .op2NotInt
1219 integerCompare(t0, t1, .jumpTarget)
1220 dispatch(4)
1221
1222.op1NotInt:
1223 btpz t0, tagTypeNumber, .slow
1224 bpb t1, tagTypeNumber, .op1NotIntOp2NotInt
1225 ci2d t1, ft1
1226 jmp .op1NotIntReady
1227.op1NotIntOp2NotInt:
1228 btpz t1, tagTypeNumber, .slow
1229 addp tagTypeNumber, t1
1230 fp2d t1, ft1
1231.op1NotIntReady:
1232 addp tagTypeNumber, t0
1233 fp2d t0, ft0
1234 doubleCompare(ft0, ft1, .jumpTarget)
1235 dispatch(4)
1236
1237.op2NotInt:
1238 ci2d t0, ft0
1239 btpz t1, tagTypeNumber, .slow
1240 addp tagTypeNumber, t1
1241 fp2d t1, ft1
1242 doubleCompare(ft0, ft1, .jumpTarget)
1243 dispatch(4)
1244
1245.jumpTarget:
1246 dispatchInt(24[PB, PC, 8])
1247
1248.slow:
1249 callSlowPath(slowPath)
1250 dispatch(0)
1251end
1252
1253
1254_llint_op_switch_imm:
1255 traceExecution()
1256 loadis 24[PB, PC, 8], t2
1257 loadis 8[PB, PC, 8], t3
1258 loadConstantOrVariable(t2, t1)
1259 loadp CodeBlock[cfr], t2
1260 loadp CodeBlock::m_rareData[t2], t2
1261 muli sizeof SimpleJumpTable, t3 # FIXME: would be nice to peephole this!
1262 loadp CodeBlock::RareData::m_immediateSwitchJumpTables + VectorBufferOffset[t2], t2
1263 addp t3, t2
1264 bpb t1, tagTypeNumber, .opSwitchImmNotInt
1265 subi SimpleJumpTable::min[t2], t1
1266 biaeq t1, SimpleJumpTable::branchOffsets + VectorSizeOffset[t2], .opSwitchImmFallThrough
1267 loadp SimpleJumpTable::branchOffsets + VectorBufferOffset[t2], t3
1268 loadis [t3, t1, 4], t1
1269 btiz t1, .opSwitchImmFallThrough
1270 dispatch(t1)
1271
1272.opSwitchImmNotInt:
1273 btpnz t1, tagTypeNumber, .opSwitchImmSlow # Go slow if it's a double.
1274.opSwitchImmFallThrough:
1275 dispatchInt(16[PB, PC, 8])
1276
1277.opSwitchImmSlow:
1278 callSlowPath(_llint_slow_path_switch_imm)
1279 dispatch(0)
1280
1281
1282_llint_op_switch_char:
1283 traceExecution()
1284 loadis 24[PB, PC, 8], t2
1285 loadis 8[PB, PC, 8], t3
1286 loadConstantOrVariable(t2, t1)
1287 loadp CodeBlock[cfr], t2
1288 loadp CodeBlock::m_rareData[t2], t2
1289 muli sizeof SimpleJumpTable, t3
1290 loadp CodeBlock::RareData::m_characterSwitchJumpTables + VectorBufferOffset[t2], t2
1291 addp t3, t2
1292 btpnz t1, tagMask, .opSwitchCharFallThrough
1293 loadp JSCell::m_structure[t1], t0
1294 bbneq Structure::m_typeInfo + TypeInfo::m_type[t0], StringType, .opSwitchCharFallThrough
1295 bineq JSString::m_length[t1], 1, .opSwitchCharFallThrough
1296 loadp JSString::m_value[t1], t0
1297 btpz t0, .opSwitchOnRope
1298 loadp StringImpl::m_data8[t0], t1
1299 btinz StringImpl::m_hashAndFlags[t0], HashFlags8BitBuffer, .opSwitchChar8Bit
1300 loadh [t1], t0
1301 jmp .opSwitchCharReady
1302.opSwitchChar8Bit:
1303 loadb [t1], t0
1304.opSwitchCharReady:
1305 subi SimpleJumpTable::min[t2], t0
1306 biaeq t0, SimpleJumpTable::branchOffsets + VectorSizeOffset[t2], .opSwitchCharFallThrough
1307 loadp SimpleJumpTable::branchOffsets + VectorBufferOffset[t2], t2
1308 loadis [t2, t0, 4], t1
1309 btiz t1, .opSwitchCharFallThrough
1310 dispatch(t1)
1311
1312.opSwitchCharFallThrough:
1313 dispatchInt(16[PB, PC, 8])
1314
1315.opSwitchOnRope:
1316 callSlowPath(_llint_slow_path_switch_char)
1317 dispatch(0)
1318
1319
1320_llint_op_new_func:
1321 traceExecution()
1322 btiz 24[PB, PC, 8], .opNewFuncUnchecked
1323 loadis 8[PB, PC, 8], t1
1324 btpnz [cfr, t1, 8], .opNewFuncDone
1325.opNewFuncUnchecked:
1326 callSlowPath(_llint_slow_path_new_func)
1327.opNewFuncDone:
1328 dispatch(4)
1329
1330
1331macro doCall(slowPath)
1332 loadis 8[PB, PC, 8], t0
1333 loadp 32[PB, PC, 8], t1
1334 loadp LLIntCallLinkInfo::callee[t1], t2
1335 loadConstantOrVariable(t0, t3)
1336 bpneq t3, t2, .opCallSlow
1337 loadis 24[PB, PC, 8], t3
1338 addi 6, PC
1339 lshifti 3, t3
1340 addp cfr, t3
1341 loadp JSFunction::m_scopeChain[t2], t0
1342 storep t2, Callee[t3]
1343 storep t0, ScopeChain[t3]
1344 loadis 16 - 48[PB, PC, 8], t2
1345 storei PC, ArgumentCount + TagOffset[cfr]
1346 storep cfr, CallerFrame[t3]
1347 storei t2, ArgumentCount + PayloadOffset[t3]
1348 move t3, cfr
1349 call LLIntCallLinkInfo::machineCodeTarget[t1]
1350 dispatchAfterCall()
1351
1352.opCallSlow:
1353 slowPathForCall(6, slowPath)
1354end
1355
1356
1357_llint_op_tear_off_activation:
1358 traceExecution()
1359 loadis 8[PB, PC, 8], t0
1360 loadis 16[PB, PC, 8], t1
1361 btpnz [cfr, t0, 8], .opTearOffActivationCreated
1362 btpz [cfr, t1, 8], .opTearOffActivationNotCreated
1363.opTearOffActivationCreated:
1364 callSlowPath(_llint_slow_path_tear_off_activation)
1365.opTearOffActivationNotCreated:
1366 dispatch(3)
1367
1368
1369_llint_op_tear_off_arguments:
1370 traceExecution()
1371 loadis 8[PB, PC, 8], t0
1372 subi 1, t0 # Get the unmodifiedArgumentsRegister
1373 btpz [cfr, t0, 8], .opTearOffArgumentsNotCreated
1374 callSlowPath(_llint_slow_path_tear_off_arguments)
1375.opTearOffArgumentsNotCreated:
1376 dispatch(2)
1377
1378
1379_llint_op_ret:
1380 traceExecution()
1381 checkSwitchToJITForEpilogue()
1382 loadis 8[PB, PC, 8], t2
1383 loadConstantOrVariable(t2, t0)
1384 doReturn()
1385
1386
1387_llint_op_call_put_result:
1388 loadis 8[PB, PC, 8], t2
1389 loadp 16[PB, PC, 8], t3
1390 storep t0, [cfr, t2, 8]
1391 valueProfile(t0, t3)
1392 traceExecution()
1393 dispatch(3)
1394
1395
1396_llint_op_ret_object_or_this:
1397 traceExecution()
1398 checkSwitchToJITForEpilogue()
1399 loadis 8[PB, PC, 8], t2
1400 loadConstantOrVariable(t2, t0)
1401 btpnz t0, tagMask, .opRetObjectOrThisNotObject
1402 loadp JSCell::m_structure[t0], t2
1403 bbb Structure::m_typeInfo + TypeInfo::m_type[t2], ObjectType, .opRetObjectOrThisNotObject
1404 doReturn()
1405
1406.opRetObjectOrThisNotObject:
1407 loadis 16[PB, PC, 8], t2
1408 loadConstantOrVariable(t2, t0)
1409 doReturn()
1410
1411
1412_llint_op_to_primitive:
1413 traceExecution()
1414 loadis 16[PB, PC, 8], t2
1415 loadis 8[PB, PC, 8], t3
1416 loadConstantOrVariable(t2, t0)
1417 btpnz t0, tagMask, .opToPrimitiveIsImm
1418 loadp JSCell::m_structure[t0], t2
1419 bbneq Structure::m_typeInfo + TypeInfo::m_type[t2], StringType, .opToPrimitiveSlowCase
1420.opToPrimitiveIsImm:
1421 storep t0, [cfr, t3, 8]
1422 dispatch(3)
1423
1424.opToPrimitiveSlowCase:
1425 callSlowPath(_llint_slow_path_to_primitive)
1426 dispatch(3)
1427
1428
1429_llint_op_next_pname:
1430 traceExecution()
1431 loadis 24[PB, PC, 8], t1
1432 loadis 32[PB, PC, 8], t2
1433 assertNotConstant(t1)
1434 assertNotConstant(t2)
1435 loadi PayloadOffset[cfr, t1, 8], t0
1436 bieq t0, PayloadOffset[cfr, t2, 8], .opNextPnameEnd
1437 loadis 40[PB, PC, 8], t2
1438 assertNotConstant(t2)
1439 loadp [cfr, t2, 8], t2
1440 loadp JSPropertyNameIterator::m_jsStrings[t2], t3
1441 loadp [t3, t0, 8], t3
1442 addi 1, t0
1443 storei t0, PayloadOffset[cfr, t1, 8]
1444 loadis 8[PB, PC, 8], t1
1445 storep t3, [cfr, t1, 8]
1446 loadis 16[PB, PC, 8], t3
1447 assertNotConstant(t3)
1448 loadp [cfr, t3, 8], t3
1449 loadp JSCell::m_structure[t3], t1
1450 bpneq t1, JSPropertyNameIterator::m_cachedStructure[t2], .opNextPnameSlow
1451 loadp JSPropertyNameIterator::m_cachedPrototypeChain[t2], t0
1452 loadp StructureChain::m_vector[t0], t0
1453 btpz [t0], .opNextPnameTarget
1454.opNextPnameCheckPrototypeLoop:
1455 bpeq Structure::m_prototype[t1], ValueNull, .opNextPnameSlow
1456 loadp Structure::m_prototype[t1], t2
1457 loadp JSCell::m_structure[t2], t1
1458 bpneq t1, [t0], .opNextPnameSlow
1459 addp 8, t0
1460 btpnz [t0], .opNextPnameCheckPrototypeLoop
1461.opNextPnameTarget:
1462 dispatchInt(48[PB, PC, 8])
1463
1464.opNextPnameEnd:
1465 dispatch(7)
1466
1467.opNextPnameSlow:
1468 callSlowPath(_llint_slow_path_next_pname) # This either keeps the PC where it was (causing us to loop) or sets it to target.
1469 dispatch(0)
1470
1471
1472_llint_op_catch:
1473 # This is where we end up from the JIT's throw trampoline (because the
1474 # machine code return address will be set to _llint_op_catch), and from
1475 # the interpreter's throw trampoline (see _llint_throw_trampoline).
1476 # The JIT throwing protocol calls for the cfr to be in t0. The throwing
1477 # code must have known that we were throwing to the interpreter, and have
1478 # set JSGlobalData::targetInterpreterPCForThrow.
1479 move t0, cfr
1480 loadp CodeBlock[cfr], PB
1481 loadp CodeBlock::m_instructions[PB], PB
1482 loadp JITStackFrame::globalData[sp], t3
1483 loadp JSGlobalData::targetInterpreterPCForThrow[t3], PC
1484 subp PB, PC
1485 urshiftp 3, PC
1486 loadp JSGlobalData::exception[t3], t0
1487 storep 0, JSGlobalData::exception[t3]
1488 loadis 8[PB, PC, 8], t2
1489 storep t0, [cfr, t2, 8]
1490 traceExecution()
1491 dispatch(2)
1492
1493
1494_llint_op_end:
1495 traceExecution()
1496 checkSwitchToJITForEpilogue()
1497 loadis 8[PB, PC, 8], t0
1498 assertNotConstant(t0)
1499 loadp [cfr, t0, 8], t0
1500 doReturn()
1501
1502
1503_llint_throw_from_slow_path_trampoline:
1504 # When throwing from the interpreter (i.e. throwing from LLIntSlowPaths), so
1505 # the throw target is not necessarily interpreted code, we come to here.
1506 # This essentially emulates the JIT's throwing protocol.
1507 loadp JITStackFrame::globalData[sp], t1
1508 loadp JSGlobalData::callFrameForThrow[t1], t0
1509 jmp JSGlobalData::targetMachinePCForThrow[t1]
1510
1511
1512_llint_throw_during_call_trampoline:
1513 preserveReturnAddressAfterCall(t2)
1514 loadp JITStackFrame::globalData[sp], t1
1515 loadp JSGlobalData::callFrameForThrow[t1], t0
1516 jmp JSGlobalData::targetMachinePCForThrow[t1]
1517
1518
1519macro nativeCallTrampoline(executableOffsetToFunction)
1520 storep 0, CodeBlock[cfr]
1521 loadp JITStackFrame::globalData + 8[sp], t0
1522 storep cfr, JSGlobalData::topCallFrame[t0]
1523 loadp CallerFrame[cfr], t0
1524 loadp ScopeChain[t0], t1
1525 storep t1, ScopeChain[cfr]
1526 peek 0, t1
1527 storep t1, ReturnPC[cfr]
1528 move cfr, t5 # t5 = rdi
1529 subp 16 - 8, sp
1530 loadp Callee[cfr], t4 # t4 = rsi
1531 loadp JSFunction::m_executable[t4], t1
1532 move t0, cfr # Restore cfr to avoid loading from stack
1533 call executableOffsetToFunction[t1]
1534 addp 16 - 8, sp
1535 loadp JITStackFrame::globalData + 8[sp], t3
1536 btpnz JSGlobalData::exception[t3], .exception
1537 ret
1538.exception:
1539 preserveReturnAddressAfterCall(t1)
1540 loadi ArgumentCount + TagOffset[cfr], PC
1541 loadp CodeBlock[cfr], PB
1542 loadp CodeBlock::m_instructions[PB], PB
1543 loadp JITStackFrame::globalData[sp], t0
1544 storep cfr, JSGlobalData::topCallFrame[t0]
1545 callSlowPath(_llint_throw_from_native_call)
1546 jmp _llint_throw_from_slow_path_trampoline
1547end
1548