1 /*
2 * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
24
25
26 package org.graalvm.compiler.core.amd64;
27
28 import static jdk.vm.ci.code.ValueUtil.asRegister;
29 import static jdk.vm.ci.code.ValueUtil.isAllocatableValue;
30 import static jdk.vm.ci.code.ValueUtil.isRegister;
31 import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic.CMP;
32 import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize.DWORD;
33 import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize.PD;
34 import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize.PS;
35 import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize.QWORD;
36 import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
37 import static org.graalvm.compiler.lir.LIRValueUtil.asConstant;
38 import static org.graalvm.compiler.lir.LIRValueUtil.asConstantValue;
39 import static org.graalvm.compiler.lir.LIRValueUtil.asJavaConstant;
40 import static org.graalvm.compiler.lir.LIRValueUtil.isConstantValue;
41 import static org.graalvm.compiler.lir.LIRValueUtil.isIntConstant;
42 import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant;
43
44 import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic;
45 import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MIOp;
46 import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RMOp;
47 import org.graalvm.compiler.asm.amd64.AMD64Assembler.ConditionFlag;
48 import org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize;
49 import org.graalvm.compiler.asm.amd64.AMD64Assembler.SSEOp;
50 import org.graalvm.compiler.core.common.LIRKind;
51 import org.graalvm.compiler.core.common.NumUtil;
52 import org.graalvm.compiler.core.common.calc.Condition;
53 import org.graalvm.compiler.core.common.spi.ForeignCallLinkage;
54 import org.graalvm.compiler.core.common.spi.LIRKindTool;
55 import org.graalvm.compiler.debug.GraalError;
56 import org.graalvm.compiler.lir.ConstantValue;
57 import org.graalvm.compiler.lir.LIRFrameState;
58 import org.graalvm.compiler.lir.LIRInstruction;
59 import org.graalvm.compiler.lir.LIRValueUtil;
60 import org.graalvm.compiler.lir.LabelRef;
61 import org.graalvm.compiler.lir.StandardOp.JumpOp;
62 import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp;
63 import org.graalvm.compiler.lir.SwitchStrategy;
64 import org.graalvm.compiler.lir.Variable;
65 import org.graalvm.compiler.lir.amd64.AMD64AddressValue;
66 import org.graalvm.compiler.lir.amd64.AMD64ArithmeticLIRGeneratorTool;
67 import org.graalvm.compiler.lir.amd64.AMD64ArrayCompareToOp;
68 import org.graalvm.compiler.lir.amd64.AMD64ArrayEqualsOp;
69 import org.graalvm.compiler.lir.amd64.AMD64ArrayIndexOfOp;
70 import org.graalvm.compiler.lir.amd64.AMD64Binary;
71 import org.graalvm.compiler.lir.amd64.AMD64BinaryConsumer;
72 import org.graalvm.compiler.lir.amd64.AMD64ByteSwapOp;
73 import org.graalvm.compiler.lir.amd64.AMD64Call;
74 import org.graalvm.compiler.lir.amd64.AMD64ControlFlow;
75 import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.BranchOp;
76 import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.CondMoveOp;
77 import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.CondSetOp;
78 import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.FloatBranchOp;
79 import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.FloatCondMoveOp;
80 import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.FloatCondSetOp;
81 import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.ReturnOp;
82 import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.StrategySwitchOp;
83 import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.TableSwitchOp;
84 import org.graalvm.compiler.lir.amd64.AMD64LFenceOp;
85 import org.graalvm.compiler.lir.amd64.AMD64Move;
86 import org.graalvm.compiler.lir.amd64.AMD64Move.CompareAndSwapOp;
87 import org.graalvm.compiler.lir.amd64.AMD64Move.MembarOp;
88 import org.graalvm.compiler.lir.amd64.AMD64Move.StackLeaOp;
89 import org.graalvm.compiler.lir.amd64.AMD64PauseOp;
90 import org.graalvm.compiler.lir.amd64.AMD64StringLatin1InflateOp;
91 import org.graalvm.compiler.lir.amd64.AMD64StringUTF16CompressOp;
92 import org.graalvm.compiler.lir.amd64.AMD64ZapRegistersOp;
93 import org.graalvm.compiler.lir.amd64.AMD64ZapStackOp;
94 import org.graalvm.compiler.lir.gen.LIRGenerationResult;
95 import org.graalvm.compiler.lir.gen.LIRGenerator;
96 import org.graalvm.compiler.phases.util.Providers;
97
98 import jdk.vm.ci.amd64.AMD64;
99 import jdk.vm.ci.amd64.AMD64Kind;
100 import jdk.vm.ci.code.CallingConvention;
101 import jdk.vm.ci.code.Register;
102 import jdk.vm.ci.code.RegisterValue;
103 import jdk.vm.ci.code.StackSlot;
104 import jdk.vm.ci.meta.AllocatableValue;
105 import jdk.vm.ci.meta.JavaConstant;
106 import jdk.vm.ci.meta.JavaKind;
107 import jdk.vm.ci.meta.PlatformKind;
108 import jdk.vm.ci.meta.VMConstant;
109 import jdk.vm.ci.meta.Value;
110 import jdk.vm.ci.meta.ValueKind;
111
112 /**
113 * This class implements the AMD64 specific portion of the LIR generator.
114 */
115 public abstract class AMD64LIRGenerator extends LIRGenerator {
528 return result;
529 }
530
531 @Override
532 public Variable emitArrayCompareTo(JavaKind kind1, JavaKind kind2, Value array1, Value array2, Value length1, Value length2) {
533 LIRKind resultKind = LIRKind.value(AMD64Kind.DWORD);
534 RegisterValue raxRes = AMD64.rax.asValue(resultKind);
535 RegisterValue cnt1 = AMD64.rcx.asValue(length1.getValueKind());
536 RegisterValue cnt2 = AMD64.rdx.asValue(length2.getValueKind());
537 emitMove(cnt1, length1);
538 emitMove(cnt2, length2);
539 append(new AMD64ArrayCompareToOp(this, kind1, kind2, raxRes, array1, array2, cnt1, cnt2));
540 Variable result = newVariable(resultKind);
541 emitMove(result, raxRes);
542 return result;
543 }
544
545 @Override
546 public Variable emitArrayEquals(JavaKind kind, Value array1, Value array2, Value length, int constantLength, boolean directPointers) {
547 Variable result = newVariable(LIRKind.value(AMD64Kind.DWORD));
548 append(new AMD64ArrayEqualsOp(this, kind, result, array1, array2, asAllocatable(length), constantLength, directPointers, getMaxVectorSize()));
549 return result;
550 }
551
552 /**
553 * Return a conservative estimate of the page size for use by the String.indexOf intrinsic.
554 */
555 protected int getVMPageSize() {
556 return 4096;
557 }
558
559 /**
560 * Return the maximum size of vector registers used in SSE/AVX instructions.
561 */
562 protected int getMaxVectorSize() {
563 // default for "unlimited"
564 return -1;
565 }
566
567 @Override
568 public Variable emitArrayIndexOf(JavaKind kind, boolean findTwoConsecutive, Value arrayPointer, Value arrayLength, Value... searchValues) {
615 operand = resultOperandFor(kind, input.getValueKind());
616 emitMove(operand, input);
617 }
618 append(new ReturnOp(operand));
619 }
620
621 protected StrategySwitchOp createStrategySwitchOp(SwitchStrategy strategy, LabelRef[] keyTargets, LabelRef defaultTarget, Variable key, AllocatableValue temp) {
622 return new StrategySwitchOp(strategy, keyTargets, defaultTarget, key, temp);
623 }
624
625 @Override
626 public void emitStrategySwitch(SwitchStrategy strategy, Variable key, LabelRef[] keyTargets, LabelRef defaultTarget) {
627 // a temp is needed for loading object constants
628 boolean needsTemp = !LIRKind.isValue(key);
629 append(createStrategySwitchOp(strategy, keyTargets, defaultTarget, key, needsTemp ? newVariable(key.getValueKind()) : Value.ILLEGAL));
630 }
631
632 @Override
633 protected void emitTableSwitch(int lowKey, LabelRef defaultTarget, LabelRef[] targets, Value key) {
634 append(new TableSwitchOp(lowKey, defaultTarget, targets, key, newVariable(LIRKind.value(target().arch.getWordKind())), newVariable(key.getValueKind())));
635 }
636
637 @Override
638 public void emitPause() {
639 append(new AMD64PauseOp());
640 }
641
642 @Override
643 public SaveRegistersOp createZapRegisters(Register[] zappedRegisters, JavaConstant[] zapValues) {
644 return new AMD64ZapRegistersOp(zappedRegisters, zapValues);
645 }
646
647 @Override
648 public LIRInstruction createZapArgumentSpace(StackSlot[] zappedStack, JavaConstant[] zapValues) {
649 return new AMD64ZapStackOp(zappedStack, zapValues);
650 }
651
652 @Override
653 public void emitSpeculationFence() {
654 append(new AMD64LFenceOp());
|
1 /*
2 * Copyright (c) 2009, 2019, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
24
25
26 package org.graalvm.compiler.core.amd64;
27
28 import static jdk.vm.ci.code.ValueUtil.asRegister;
29 import static jdk.vm.ci.code.ValueUtil.isAllocatableValue;
30 import static jdk.vm.ci.code.ValueUtil.isRegister;
31 import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic.CMP;
32 import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize.DWORD;
33 import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize.PD;
34 import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize.PS;
35 import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize.QWORD;
36 import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
37 import static org.graalvm.compiler.lir.LIRValueUtil.asConstant;
38 import static org.graalvm.compiler.lir.LIRValueUtil.asConstantValue;
39 import static org.graalvm.compiler.lir.LIRValueUtil.asJavaConstant;
40 import static org.graalvm.compiler.lir.LIRValueUtil.isConstantValue;
41 import static org.graalvm.compiler.lir.LIRValueUtil.isIntConstant;
42 import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant;
43
44 import java.util.Optional;
45
46 import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic;
47 import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MIOp;
48 import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RMOp;
49 import org.graalvm.compiler.asm.amd64.AMD64Assembler.ConditionFlag;
50 import org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize;
51 import org.graalvm.compiler.asm.amd64.AMD64Assembler.SSEOp;
52 import org.graalvm.compiler.core.common.LIRKind;
53 import org.graalvm.compiler.core.common.NumUtil;
54 import org.graalvm.compiler.core.common.calc.Condition;
55 import org.graalvm.compiler.core.common.spi.ForeignCallLinkage;
56 import org.graalvm.compiler.core.common.spi.LIRKindTool;
57 import org.graalvm.compiler.debug.GraalError;
58 import org.graalvm.compiler.lir.ConstantValue;
59 import org.graalvm.compiler.lir.LIRFrameState;
60 import org.graalvm.compiler.lir.LIRInstruction;
61 import org.graalvm.compiler.lir.LIRValueUtil;
62 import org.graalvm.compiler.lir.LabelRef;
63 import org.graalvm.compiler.lir.StandardOp.JumpOp;
64 import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp;
65 import org.graalvm.compiler.lir.SwitchStrategy;
66 import org.graalvm.compiler.lir.Variable;
67 import org.graalvm.compiler.lir.amd64.AMD64AddressValue;
68 import org.graalvm.compiler.lir.amd64.AMD64ArithmeticLIRGeneratorTool;
69 import org.graalvm.compiler.lir.amd64.AMD64ArrayCompareToOp;
70 import org.graalvm.compiler.lir.amd64.AMD64ArrayEqualsOp;
71 import org.graalvm.compiler.lir.amd64.AMD64ArrayIndexOfOp;
72 import org.graalvm.compiler.lir.amd64.AMD64Binary;
73 import org.graalvm.compiler.lir.amd64.AMD64BinaryConsumer;
74 import org.graalvm.compiler.lir.amd64.AMD64ByteSwapOp;
75 import org.graalvm.compiler.lir.amd64.AMD64Call;
76 import org.graalvm.compiler.lir.amd64.AMD64ControlFlow;
77 import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.BranchOp;
78 import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.CondMoveOp;
79 import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.CondSetOp;
80 import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.FloatBranchOp;
81 import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.FloatCondMoveOp;
82 import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.FloatCondSetOp;
83 import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.ReturnOp;
84 import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.StrategySwitchOp;
85 import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.TableSwitchOp;
86 import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.HashTableSwitchOp;
87 import org.graalvm.compiler.lir.amd64.AMD64LFenceOp;
88 import org.graalvm.compiler.lir.amd64.AMD64Move;
89 import org.graalvm.compiler.lir.amd64.AMD64Move.CompareAndSwapOp;
90 import org.graalvm.compiler.lir.amd64.AMD64Move.MembarOp;
91 import org.graalvm.compiler.lir.amd64.AMD64Move.StackLeaOp;
92 import org.graalvm.compiler.lir.amd64.AMD64PauseOp;
93 import org.graalvm.compiler.lir.amd64.AMD64StringLatin1InflateOp;
94 import org.graalvm.compiler.lir.amd64.AMD64StringUTF16CompressOp;
95 import org.graalvm.compiler.lir.amd64.AMD64ZapRegistersOp;
96 import org.graalvm.compiler.lir.amd64.AMD64ZapStackOp;
97 import org.graalvm.compiler.lir.gen.LIRGenerationResult;
98 import org.graalvm.compiler.lir.gen.LIRGenerator;
99 import org.graalvm.compiler.lir.hashing.Hasher;
100 import org.graalvm.compiler.phases.util.Providers;
101
102 import jdk.vm.ci.amd64.AMD64;
103 import jdk.vm.ci.amd64.AMD64Kind;
104 import jdk.vm.ci.code.CallingConvention;
105 import jdk.vm.ci.code.Register;
106 import jdk.vm.ci.code.RegisterValue;
107 import jdk.vm.ci.code.StackSlot;
108 import jdk.vm.ci.meta.AllocatableValue;
109 import jdk.vm.ci.meta.JavaConstant;
110 import jdk.vm.ci.meta.JavaKind;
111 import jdk.vm.ci.meta.PlatformKind;
112 import jdk.vm.ci.meta.VMConstant;
113 import jdk.vm.ci.meta.Value;
114 import jdk.vm.ci.meta.ValueKind;
115
116 /**
117 * This class implements the AMD64 specific portion of the LIR generator.
118 */
119 public abstract class AMD64LIRGenerator extends LIRGenerator {
532 return result;
533 }
534
535 @Override
536 public Variable emitArrayCompareTo(JavaKind kind1, JavaKind kind2, Value array1, Value array2, Value length1, Value length2) {
537 LIRKind resultKind = LIRKind.value(AMD64Kind.DWORD);
538 RegisterValue raxRes = AMD64.rax.asValue(resultKind);
539 RegisterValue cnt1 = AMD64.rcx.asValue(length1.getValueKind());
540 RegisterValue cnt2 = AMD64.rdx.asValue(length2.getValueKind());
541 emitMove(cnt1, length1);
542 emitMove(cnt2, length2);
543 append(new AMD64ArrayCompareToOp(this, kind1, kind2, raxRes, array1, array2, cnt1, cnt2));
544 Variable result = newVariable(resultKind);
545 emitMove(result, raxRes);
546 return result;
547 }
548
549 @Override
550 public Variable emitArrayEquals(JavaKind kind, Value array1, Value array2, Value length, int constantLength, boolean directPointers) {
551 Variable result = newVariable(LIRKind.value(AMD64Kind.DWORD));
552 append(new AMD64ArrayEqualsOp(this, kind, kind, result, array1, array2, asAllocatable(length), constantLength, directPointers, getMaxVectorSize()));
553 return result;
554 }
555
556 @Override
557 public Variable emitArrayEquals(JavaKind kind1, JavaKind kind2, Value array1, Value array2, Value length, int constantLength, boolean directPointers) {
558 Variable result = newVariable(LIRKind.value(AMD64Kind.DWORD));
559 append(new AMD64ArrayEqualsOp(this, kind1, kind2, result, array1, array2, asAllocatable(length), constantLength, directPointers, getMaxVectorSize()));
560 return result;
561 }
562
563 /**
564 * Return a conservative estimate of the page size for use by the String.indexOf intrinsic.
565 */
566 protected int getVMPageSize() {
567 return 4096;
568 }
569
570 /**
571 * Return the maximum size of vector registers used in SSE/AVX instructions.
572 */
573 protected int getMaxVectorSize() {
574 // default for "unlimited"
575 return -1;
576 }
577
578 @Override
579 public Variable emitArrayIndexOf(JavaKind kind, boolean findTwoConsecutive, Value arrayPointer, Value arrayLength, Value... searchValues) {
626 operand = resultOperandFor(kind, input.getValueKind());
627 emitMove(operand, input);
628 }
629 append(new ReturnOp(operand));
630 }
631
632 protected StrategySwitchOp createStrategySwitchOp(SwitchStrategy strategy, LabelRef[] keyTargets, LabelRef defaultTarget, Variable key, AllocatableValue temp) {
633 return new StrategySwitchOp(strategy, keyTargets, defaultTarget, key, temp);
634 }
635
636 @Override
637 public void emitStrategySwitch(SwitchStrategy strategy, Variable key, LabelRef[] keyTargets, LabelRef defaultTarget) {
638 // a temp is needed for loading object constants
639 boolean needsTemp = !LIRKind.isValue(key);
640 append(createStrategySwitchOp(strategy, keyTargets, defaultTarget, key, needsTemp ? newVariable(key.getValueKind()) : Value.ILLEGAL));
641 }
642
643 @Override
644 protected void emitTableSwitch(int lowKey, LabelRef defaultTarget, LabelRef[] targets, Value key) {
645 append(new TableSwitchOp(lowKey, defaultTarget, targets, key, newVariable(LIRKind.value(target().arch.getWordKind())), newVariable(key.getValueKind())));
646 }
647
648 @Override
649 protected Optional<Hasher> hasherFor(JavaConstant[] keyConstants, double minDensity) {
650 return Hasher.forKeys(keyConstants, minDensity);
651 }
652
653 @Override
654 protected void emitHashTableSwitch(Hasher hasher, JavaConstant[] keys, LabelRef defaultTarget, LabelRef[] targets, Value value) {
655 Value index = hasher.hash(value, arithmeticLIRGen);
656 Variable scratch = newVariable(LIRKind.value(target().arch.getWordKind()));
657 Variable entryScratch = newVariable(LIRKind.value(target().arch.getWordKind()));
658 append(new HashTableSwitchOp(keys, defaultTarget, targets, value, index, scratch, entryScratch));
659 }
660
661 @Override
662 public void emitPause() {
663 append(new AMD64PauseOp());
664 }
665
666 @Override
667 public SaveRegistersOp createZapRegisters(Register[] zappedRegisters, JavaConstant[] zapValues) {
668 return new AMD64ZapRegistersOp(zappedRegisters, zapValues);
669 }
670
671 @Override
672 public LIRInstruction createZapArgumentSpace(StackSlot[] zappedStack, JavaConstant[] zapValues) {
673 return new AMD64ZapStackOp(zappedStack, zapValues);
674 }
675
676 @Override
677 public void emitSpeculationFence() {
678 append(new AMD64LFenceOp());
|