File: | jdk/src/hotspot/share/asm/register.hpp |
Warning: | line 70, column 7 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* | ||||
2 | * Copyright (c) 1997, 2021, 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 | * | ||||
23 | */ | ||||
24 | |||||
25 | #include "precompiled.hpp" | ||||
26 | #include "jvm.h" | ||||
27 | #include "asm/macroAssembler.hpp" | ||||
28 | #include "classfile/vmClasses.hpp" | ||||
29 | #include "compiler/disassembler.hpp" | ||||
30 | #include "classfile/javaClasses.inline.hpp" | ||||
31 | #include "interpreter/interpreter.hpp" | ||||
32 | #include "interpreter/interpreterRuntime.hpp" | ||||
33 | #include "logging/log.hpp" | ||||
34 | #include "logging/logStream.hpp" | ||||
35 | #include "memory/allocation.inline.hpp" | ||||
36 | #include "memory/resourceArea.hpp" | ||||
37 | #include "prims/jvmtiExport.hpp" | ||||
38 | #include "prims/methodHandles.hpp" | ||||
39 | #include "runtime/flags/flagSetting.hpp" | ||||
40 | #include "runtime/frame.inline.hpp" | ||||
41 | #include "runtime/stubRoutines.hpp" | ||||
42 | #include "utilities/formatBuffer.hpp" | ||||
43 | #include "utilities/preserveException.hpp" | ||||
44 | |||||
45 | #define __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 45, _masm)-> Disassembler::hook<MacroAssembler>(__FILE__"/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp", __LINE__45, _masm)-> | ||||
46 | |||||
47 | #ifdef PRODUCT | ||||
48 | #define BLOCK_COMMENT(str)Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 48, _masm)-> block_comment(str) /* nothing */ | ||||
49 | #define STOP(error)block_comment(error); Disassembler::hook<MacroAssembler> ("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 49, _masm)-> stop(error) stop(error) | ||||
50 | #else | ||||
51 | #define BLOCK_COMMENT(str)Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 51, _masm)-> block_comment(str) __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 51, _masm)-> block_comment(str) | ||||
52 | #define STOP(error)block_comment(error); Disassembler::hook<MacroAssembler> ("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 52, _masm)-> stop(error) block_comment(error); __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 52, _masm)-> stop(error) | ||||
53 | #endif | ||||
54 | |||||
55 | #define BIND(label)bind(label); Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 55, _masm)-> block_comment("label" ":") bind(label); BLOCK_COMMENT(#label ":")Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 55, _masm)-> block_comment(#label ":") | ||||
56 | |||||
57 | void MethodHandles::load_klass_from_Class(MacroAssembler* _masm, Register klass_reg) { | ||||
58 | if (VerifyMethodHandles) | ||||
59 | verify_klass(_masm, klass_reg, VM_CLASS_ID(java_lang_Class)vmClassID::java_lang_Class_knum, | ||||
60 | "MH argument is a Class"); | ||||
61 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 61, _masm)-> movptr(klass_reg, Address(klass_reg, java_lang_Class::klass_offset())); | ||||
62 | } | ||||
63 | |||||
64 | #ifdef ASSERT1 | ||||
65 | static int check_nonzero(const char* xname, int x) { | ||||
66 | assert(x != 0, "%s should be nonzero", xname)do { if (!(x != 0)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 66, "assert(" "x != 0" ") failed", "%s should be nonzero", xname ); ::breakpoint(); } } while (0); | ||||
67 | return x; | ||||
68 | } | ||||
69 | #define NONZERO(x)check_nonzero("x", x) check_nonzero(#x, x) | ||||
70 | #else //ASSERT | ||||
71 | #define NONZERO(x)check_nonzero("x", x) (x) | ||||
72 | #endif //ASSERT | ||||
73 | |||||
74 | #ifdef ASSERT1 | ||||
75 | void MethodHandles::verify_klass(MacroAssembler* _masm, | ||||
76 | Register obj, vmClassID klass_id, | ||||
77 | const char* error_message) { | ||||
78 | InstanceKlass** klass_addr = vmClasses::klass_addr_at(klass_id); | ||||
79 | Klass* klass = vmClasses::klass_at(klass_id); | ||||
80 | Register temp = rdi; | ||||
81 | Register temp2 = noreg; | ||||
82 | LP64_ONLY(temp2 = rscratch1)temp2 = rscratch1; // used by MacroAssembler::cmpptr and load_klass | ||||
83 | Label L_ok, L_bad; | ||||
84 | BLOCK_COMMENT("verify_klass {")Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 84, _masm)-> block_comment("verify_klass {"); | ||||
85 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 85, _masm)-> verify_oop(obj)_verify_oop_checked(obj, "broken oop " "obj", "/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 85); | ||||
86 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 86, _masm)-> testptr(obj, obj); | ||||
87 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 87, _masm)-> jcc(Assembler::zero, L_bad); | ||||
88 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 88, _masm)-> push(temp); if (temp2 != noreg) __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 88, _masm)-> push(temp2); | ||||
89 | #define UNPUSH{ if (temp2 != noreg) Disassembler::hook<MacroAssembler> ("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 89, _masm)-> pop(temp2); Disassembler::hook<MacroAssembler >("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 89, _masm)-> pop(temp); } { if (temp2 != noreg) __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 89, _masm)-> pop(temp2); __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 89, _masm)-> pop(temp); } | ||||
90 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 90, _masm)-> load_klass(temp, obj, temp2); | ||||
91 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 91, _masm)-> cmpptr(temp, ExternalAddress((address) klass_addr)); | ||||
92 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 92, _masm)-> jcc(Assembler::equal, L_ok); | ||||
93 | intptr_t super_check_offset = klass->super_check_offset(); | ||||
94 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 94, _masm)-> movptr(temp, Address(temp, super_check_offset)); | ||||
95 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 95, _masm)-> cmpptr(temp, ExternalAddress((address) klass_addr)); | ||||
96 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 96, _masm)-> jcc(Assembler::equal, L_ok); | ||||
97 | UNPUSH{ if (temp2 != noreg) Disassembler::hook<MacroAssembler> ("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 97, _masm)-> pop(temp2); Disassembler::hook<MacroAssembler >("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 97, _masm)-> pop(temp); }; | ||||
98 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 98, _masm)-> bind(L_bad); | ||||
99 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 99, _masm)-> STOP(error_message)block_comment(error_message); Disassembler::hook<MacroAssembler >("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 99, _masm)-> stop(error_message); | ||||
100 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 100, _masm)-> BIND(L_ok)bind(L_ok); Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 100, _masm)-> block_comment("L_ok" ":"); | ||||
101 | UNPUSH{ if (temp2 != noreg) Disassembler::hook<MacroAssembler> ("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 101, _masm)-> pop(temp2); Disassembler::hook<MacroAssembler >("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 101, _masm)-> pop(temp); }; | ||||
102 | BLOCK_COMMENT("} verify_klass")Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 102, _masm)-> block_comment("} verify_klass"); | ||||
103 | } | ||||
104 | |||||
105 | void MethodHandles::verify_ref_kind(MacroAssembler* _masm, int ref_kind, Register member_reg, Register temp) { | ||||
106 | Label L; | ||||
107 | BLOCK_COMMENT("verify_ref_kind {")Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 107, _masm)-> block_comment("verify_ref_kind {"); | ||||
108 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 108, _masm)-> movl(temp, Address(member_reg, NONZERO(java_lang_invoke_MemberName::flags_offset())check_nonzero("java_lang_invoke_MemberName::flags_offset()", java_lang_invoke_MemberName ::flags_offset()))); | ||||
109 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 109, _masm)-> shrl(temp, java_lang_invoke_MemberName::MN_REFERENCE_KIND_SHIFT); | ||||
110 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 110, _masm)-> andl(temp, java_lang_invoke_MemberName::MN_REFERENCE_KIND_MASK); | ||||
111 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 111, _masm)-> cmpl(temp, ref_kind); | ||||
112 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 112, _masm)-> jcc(Assembler::equal, L); | ||||
113 | { char* buf = NEW_C_HEAP_ARRAY(char, 100, mtInternal)(char*) (AllocateHeap((100) * sizeof(char), mtInternal)); | ||||
114 | jio_snprintf(buf, 100, "verify_ref_kind expected %x", ref_kind); | ||||
115 | if (ref_kind == JVM_REF_invokeVirtual || | ||||
116 | ref_kind == JVM_REF_invokeSpecial) | ||||
117 | // could do this for all ref_kinds, but would explode assembly code size | ||||
118 | trace_method_handle(_masm, buf); | ||||
119 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 119, _masm)-> STOP(buf)block_comment(buf); Disassembler::hook<MacroAssembler>( "/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 119, _masm)-> stop(buf); | ||||
120 | } | ||||
121 | BLOCK_COMMENT("} verify_ref_kind")Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 121, _masm)-> block_comment("} verify_ref_kind"); | ||||
122 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 122, _masm)-> bind(L); | ||||
123 | } | ||||
124 | |||||
125 | #endif //ASSERT | ||||
126 | |||||
127 | void MethodHandles::jump_from_method_handle(MacroAssembler* _masm, Register method, Register temp, | ||||
128 | bool for_compiler_entry) { | ||||
129 | assert(method == rbx, "interpreter calling convention")do { if (!(method == rbx)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 129, "assert(" "method == rbx" ") failed", "interpreter calling convention" ); ::breakpoint(); } } while (0); | ||||
130 | |||||
131 | Label L_no_such_method; | ||||
132 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 132, _masm)-> testptr(rbx, rbx); | ||||
133 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 133, _masm)-> jcc(Assembler::zero, L_no_such_method); | ||||
134 | |||||
135 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 135, _masm)-> verify_method_ptr(method)_verify_method_ptr(method, "broken method " "method", "/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 135); | ||||
136 | |||||
137 | if (!for_compiler_entry && JvmtiExport::can_post_interpreter_events()) { | ||||
138 | Label run_compiled_code; | ||||
139 | // JVMTI events, such as single-stepping, are implemented partly by avoiding running | ||||
140 | // compiled code in threads for which the event is enabled. Check here for | ||||
141 | // interp_only_mode if these events CAN be enabled. | ||||
142 | #ifdef _LP641 | ||||
143 | Register rthread = r15_thread; | ||||
144 | #else | ||||
145 | Register rthread = temp; | ||||
146 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 146, _masm)-> get_thread(rthread); | ||||
147 | #endif | ||||
148 | // interp_only is an int, on little endian it is sufficient to test the byte only | ||||
149 | // Is a cmpl faster? | ||||
150 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 150, _masm)-> cmpb(Address(rthread, JavaThread::interp_only_mode_offset()), 0); | ||||
151 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 151, _masm)-> jccb(Assembler::zero, run_compiled_code)jccb_0(Assembler::zero, run_compiled_code, "/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 151); | ||||
152 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 152, _masm)-> jmp(Address(method, Method::interpreter_entry_offset())); | ||||
153 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 153, _masm)-> BIND(run_compiled_code)bind(run_compiled_code); Disassembler::hook<MacroAssembler >("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 153, _masm)-> block_comment("run_compiled_code" ":"); | ||||
154 | } | ||||
155 | |||||
156 | const ByteSize entry_offset = for_compiler_entry ? Method::from_compiled_offset() : | ||||
157 | Method::from_interpreted_offset(); | ||||
158 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 158, _masm)-> jmp(Address(method, entry_offset)); | ||||
159 | |||||
160 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 160, _masm)-> bind(L_no_such_method); | ||||
161 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 161, _masm)-> jump(RuntimeAddress(StubRoutines::throw_AbstractMethodError_entry())); | ||||
162 | } | ||||
163 | |||||
164 | void MethodHandles::jump_to_lambda_form(MacroAssembler* _masm, | ||||
165 | Register recv, Register method_temp, | ||||
166 | Register temp2, | ||||
167 | bool for_compiler_entry) { | ||||
168 | BLOCK_COMMENT("jump_to_lambda_form {")Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 168, _masm)-> block_comment("jump_to_lambda_form {"); | ||||
169 | // This is the initial entry point of a lazy method handle. | ||||
170 | // After type checking, it picks up the invoker from the LambdaForm. | ||||
171 | assert_different_registers(recv, method_temp, temp2); | ||||
172 | assert(recv != noreg, "required register")do { if (!(recv != noreg)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 172, "assert(" "recv != noreg" ") failed", "required register" ); ::breakpoint(); } } while (0); | ||||
173 | assert(method_temp == rbx, "required register for loading method")do { if (!(method_temp == rbx)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 173, "assert(" "method_temp == rbx" ") failed", "required register for loading method" ); ::breakpoint(); } } while (0); | ||||
174 | |||||
175 | // Load the invoker, as MH -> MH.form -> LF.vmentry | ||||
176 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 176, _masm)-> verify_oop(recv)_verify_oop_checked(recv, "broken oop " "recv", "/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 176); | ||||
177 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 177, _masm)-> load_heap_oop(method_temp, Address(recv, NONZERO(java_lang_invoke_MethodHandle::form_offset())check_nonzero("java_lang_invoke_MethodHandle::form_offset()", java_lang_invoke_MethodHandle::form_offset())), temp2); | ||||
178 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 178, _masm)-> verify_oop(method_temp)_verify_oop_checked(method_temp, "broken oop " "method_temp", "/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 178); | ||||
179 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 179, _masm)-> load_heap_oop(method_temp, Address(method_temp, NONZERO(java_lang_invoke_LambdaForm::vmentry_offset())check_nonzero("java_lang_invoke_LambdaForm::vmentry_offset()" , java_lang_invoke_LambdaForm::vmentry_offset())), temp2); | ||||
180 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 180, _masm)-> verify_oop(method_temp)_verify_oop_checked(method_temp, "broken oop " "method_temp", "/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 180); | ||||
181 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 181, _masm)-> load_heap_oop(method_temp, Address(method_temp, NONZERO(java_lang_invoke_MemberName::method_offset())check_nonzero("java_lang_invoke_MemberName::method_offset()", java_lang_invoke_MemberName::method_offset())), temp2); | ||||
182 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 182, _masm)-> verify_oop(method_temp)_verify_oop_checked(method_temp, "broken oop " "method_temp", "/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 182); | ||||
183 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 183, _masm)-> access_load_at(T_ADDRESS, IN_HEAP, method_temp, | ||||
184 | Address(method_temp, NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset())check_nonzero("java_lang_invoke_ResolvedMethodName::vmtarget_offset()" , java_lang_invoke_ResolvedMethodName::vmtarget_offset())), | ||||
185 | noreg, noreg); | ||||
186 | |||||
187 | if (VerifyMethodHandles && !for_compiler_entry) { | ||||
188 | // make sure recv is already on stack | ||||
189 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 189, _masm)-> movptr(temp2, Address(method_temp, Method::const_offset())); | ||||
190 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 190, _masm)-> load_sized_value(temp2, | ||||
191 | Address(temp2, ConstMethod::size_of_parameters_offset()), | ||||
192 | sizeof(u2), /*is_signed*/ false); | ||||
193 | // assert(sizeof(u2) == sizeof(Method::_size_of_parameters), ""); | ||||
194 | Label L; | ||||
195 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 195, _masm)-> cmpoop(recv, __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 195, _masm)-> argument_address(temp2, -1)); | ||||
196 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 196, _masm)-> jcc(Assembler::equal, L); | ||||
197 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 197, _masm)-> movptr(rax, __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 197, _masm)-> argument_address(temp2, -1)); | ||||
198 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 198, _masm)-> STOP("receiver not on stack")block_comment("receiver not on stack"); Disassembler::hook< MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 198, _masm)-> stop("receiver not on stack"); | ||||
199 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 199, _masm)-> BIND(L)bind(L); Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 199, _masm)-> block_comment("L" ":"); | ||||
200 | } | ||||
201 | |||||
202 | jump_from_method_handle(_masm, method_temp, temp2, for_compiler_entry); | ||||
203 | BLOCK_COMMENT("} jump_to_lambda_form")Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 203, _masm)-> block_comment("} jump_to_lambda_form"); | ||||
204 | } | ||||
205 | |||||
206 | |||||
207 | // Code generation | ||||
208 | address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler* _masm, | ||||
209 | vmIntrinsics::ID iid) { | ||||
210 | const bool not_for_compiler_entry = false; // this is the interpreter entry | ||||
211 | assert(is_signature_polymorphic(iid), "expected invoke iid")do { if (!(is_signature_polymorphic(iid))) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 211, "assert(" "is_signature_polymorphic(iid)" ") failed", "expected invoke iid" ); ::breakpoint(); } } while (0); | ||||
| |||||
212 | if (iid == vmIntrinsics::_invokeGeneric || | ||||
213 | iid
| ||||
214 | // Perhaps surprisingly, the symbolic references visible to Java are not directly used. | ||||
215 | // They are linked to Java-generated adapters via MethodHandleNatives.linkMethod. | ||||
216 | // They all allow an appendix argument. | ||||
217 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 217, _masm)-> hlt(); // empty stubs make SG sick | ||||
218 | return NULL__null; | ||||
219 | } | ||||
220 | |||||
221 | // No need in interpreter entry for linkToNative for now. | ||||
222 | // Interpreter calls compiled entry through i2c. | ||||
223 | if (iid == vmIntrinsics::_linkToNative) { | ||||
224 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 224, _masm)-> hlt(); | ||||
225 | return NULL__null; | ||||
226 | } | ||||
227 | |||||
228 | // rsi/r13: sender SP (must preserve; see prepare_to_jump_from_interpreted) | ||||
229 | // rbx: Method* | ||||
230 | // rdx: argument locator (parameter slot count, added to rsp) | ||||
231 | // rcx: used as temp to hold mh or receiver | ||||
232 | // rax, rdi: garbage temps, blown away | ||||
233 | Register rdx_argp = rdx; // argument list ptr, live on error paths | ||||
234 | Register rax_temp = rax; | ||||
235 | Register rcx_mh = rcx; // MH receiver; dies quickly and is recycled | ||||
236 | Register rbx_method = rbx; // eventual target of this invocation | ||||
237 | |||||
238 | // here's where control starts out: | ||||
239 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 239, _masm)-> align(CodeEntryAlignment); | ||||
240 | address entry_point = __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 240, _masm)-> pc(); | ||||
241 | |||||
242 | if (VerifyMethodHandles) { | ||||
243 | assert(Method::intrinsic_id_size_in_bytes() == 2, "assuming Method::_intrinsic_id is u2")do { if (!(Method::intrinsic_id_size_in_bytes() == 2)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 243, "assert(" "Method::intrinsic_id_size_in_bytes() == 2" ") failed" , "assuming Method::_intrinsic_id is u2"); ::breakpoint(); } } while (0); | ||||
244 | |||||
245 | Label L; | ||||
246 | BLOCK_COMMENT("verify_intrinsic_id {")Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 246, _masm)-> block_comment("verify_intrinsic_id {"); | ||||
247 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 247, _masm)-> cmpw(Address(rbx_method, Method::intrinsic_id_offset_in_bytes()), (int) iid); | ||||
248 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 248, _masm)-> jcc(Assembler::equal, L); | ||||
249 | if (iid == vmIntrinsics::_linkToVirtual || | ||||
250 | iid == vmIntrinsics::_linkToSpecial) { | ||||
251 | // could do this for all kinds, but would explode assembly code size | ||||
252 | trace_method_handle(_masm, "bad Method*::intrinsic_id"); | ||||
253 | } | ||||
254 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 254, _masm)-> STOP("bad Method*::intrinsic_id")block_comment("bad Method*::intrinsic_id"); Disassembler::hook <MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 254, _masm)-> stop("bad Method*::intrinsic_id"); | ||||
255 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 255, _masm)-> bind(L); | ||||
256 | BLOCK_COMMENT("} verify_intrinsic_id")Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 256, _masm)-> block_comment("} verify_intrinsic_id"); | ||||
257 | } | ||||
258 | |||||
259 | // First task: Find out how big the argument list is. | ||||
260 | Address rdx_first_arg_addr; | ||||
261 | int ref_kind = signature_polymorphic_intrinsic_ref_kind(iid); | ||||
262 | assert(ref_kind != 0 || iid == vmIntrinsics::_invokeBasic, "must be _invokeBasic or a linkTo intrinsic")do { if (!(ref_kind != 0 || iid == vmIntrinsics::_invokeBasic )) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 262, "assert(" "ref_kind != 0 || iid == vmIntrinsics::_invokeBasic" ") failed", "must be _invokeBasic or a linkTo intrinsic"); :: breakpoint(); } } while (0); | ||||
263 | if (ref_kind
| ||||
264 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 264, _masm)-> movptr(rdx_argp, Address(rbx_method, Method::const_offset())); | ||||
265 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 265, _masm)-> load_sized_value(rdx_argp, | ||||
266 | Address(rdx_argp, ConstMethod::size_of_parameters_offset()), | ||||
267 | sizeof(u2), /*is_signed*/ false); | ||||
268 | // assert(sizeof(u2) == sizeof(Method::_size_of_parameters), ""); | ||||
269 | rdx_first_arg_addr = __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 269, _masm)-> argument_address(rdx_argp, -1); | ||||
270 | } else { | ||||
271 | DEBUG_ONLY(rdx_argp = noreg)rdx_argp = noreg; | ||||
272 | } | ||||
273 | |||||
274 | if (!is_signature_polymorphic_static(iid)) { | ||||
275 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 275, _masm)-> movptr(rcx_mh, rdx_first_arg_addr); | ||||
276 | DEBUG_ONLY(rdx_argp = noreg)rdx_argp = noreg; | ||||
277 | } | ||||
278 | |||||
279 | // rdx_first_arg_addr is live! | ||||
280 | |||||
281 | trace_method_handle_interpreter_entry(_masm, iid); | ||||
282 | |||||
283 | if (iid
| ||||
284 | generate_method_handle_dispatch(_masm, iid, rcx_mh, noreg, not_for_compiler_entry); | ||||
285 | |||||
286 | } else { | ||||
287 | // Adjust argument list by popping the trailing MemberName argument. | ||||
288 | Register rcx_recv = noreg; | ||||
289 | if (MethodHandles::ref_kind_has_receiver(ref_kind)) { | ||||
290 | // Load the receiver (not the MH; the actual MemberName's receiver) up from the interpreter stack. | ||||
291 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 291, _masm)-> movptr(rcx_recv = rcx, rdx_first_arg_addr); | ||||
292 | } | ||||
293 | DEBUG_ONLY(rdx_argp = noreg)rdx_argp = noreg; | ||||
294 | Register rbx_member = rbx_method; // MemberName ptr; incoming method ptr is dead now | ||||
295 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 295, _masm)-> pop(rax_temp); // return address | ||||
296 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 296, _masm)-> pop(rbx_member); // extract last argument | ||||
297 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 297, _masm)-> push(rax_temp); // re-push return address | ||||
298 | generate_method_handle_dispatch(_masm, iid, rcx_recv, rbx_member, not_for_compiler_entry); | ||||
299 | } | ||||
300 | |||||
301 | return entry_point; | ||||
302 | } | ||||
303 | |||||
304 | void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm, | ||||
305 | vmIntrinsics::ID iid, | ||||
306 | Register receiver_reg, | ||||
307 | Register member_reg, | ||||
308 | bool for_compiler_entry) { | ||||
309 | assert(is_signature_polymorphic(iid), "expected invoke iid")do { if (!(is_signature_polymorphic(iid))) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 309, "assert(" "is_signature_polymorphic(iid)" ") failed", "expected invoke iid" ); ::breakpoint(); } } while (0); | ||||
310 | Register rbx_method = rbx; // eventual target of this invocation | ||||
311 | // temps used in this code are not used in *either* compiled or interpreted calling sequences | ||||
312 | #ifdef _LP641 | ||||
313 | Register temp1 = rscratch1; | ||||
314 | Register temp2 = rscratch2; | ||||
315 | Register temp3 = rax; | ||||
316 | if (for_compiler_entry
| ||||
317 | assert(receiver_reg == (iid == vmIntrinsics::_linkToStatic ? noreg : j_rarg0), "only valid assignment")do { if (!(receiver_reg == (iid == vmIntrinsics::_linkToStatic ? noreg : j_rarg0))) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 317, "assert(" "receiver_reg == (iid == vmIntrinsics::_linkToStatic ? noreg : j_rarg0)" ") failed", "only valid assignment"); ::breakpoint(); } } while (0); | ||||
318 | assert_different_registers(temp1, j_rarg0, j_rarg1, j_rarg2, j_rarg3, j_rarg4, j_rarg5); | ||||
319 | assert_different_registers(temp2, j_rarg0, j_rarg1, j_rarg2, j_rarg3, j_rarg4, j_rarg5); | ||||
320 | assert_different_registers(temp3, j_rarg0, j_rarg1, j_rarg2, j_rarg3, j_rarg4, j_rarg5); | ||||
321 | } | ||||
322 | #else | ||||
323 | Register temp1 = (for_compiler_entry ? rsi : rdx); | ||||
324 | Register temp2 = rdi; | ||||
325 | Register temp3 = rax; | ||||
326 | if (for_compiler_entry) { | ||||
327 | assert(receiver_reg == (iid == vmIntrinsics::_linkToStatic ? noreg : rcx), "only valid assignment")do { if (!(receiver_reg == (iid == vmIntrinsics::_linkToStatic ? noreg : rcx))) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 327, "assert(" "receiver_reg == (iid == vmIntrinsics::_linkToStatic ? noreg : rcx)" ") failed", "only valid assignment"); ::breakpoint(); } } while (0); | ||||
328 | assert_different_registers(temp1, rcx, rdx); | ||||
329 | assert_different_registers(temp2, rcx, rdx); | ||||
330 | assert_different_registers(temp3, rcx, rdx); | ||||
331 | } | ||||
332 | #endif | ||||
333 | else { | ||||
334 | assert_different_registers(temp1, temp2, temp3, saved_last_sp_register()); // don't trash lastSP | ||||
335 | } | ||||
336 | assert_different_registers(temp1, temp2, temp3, receiver_reg); | ||||
337 | assert_different_registers(temp1, temp2, temp3, member_reg); | ||||
338 | |||||
339 | if (iid == vmIntrinsics::_invokeBasic || iid == vmIntrinsics::_linkToNative) { | ||||
340 | if (iid == vmIntrinsics::_linkToNative) { | ||||
341 | assert(for_compiler_entry, "only compiler entry is supported")do { if (!(for_compiler_entry)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 341, "assert(" "for_compiler_entry" ") failed", "only compiler entry is supported" ); ::breakpoint(); } } while (0); | ||||
342 | } | ||||
343 | // indirect through MH.form.vmentry.vmtarget | ||||
344 | jump_to_lambda_form(_masm, receiver_reg, rbx_method, temp1, for_compiler_entry); | ||||
345 | |||||
346 | } else { | ||||
347 | // The method is a member invoker used by direct method handles. | ||||
348 | if (VerifyMethodHandles) { | ||||
349 | // make sure the trailing argument really is a MemberName (caller responsibility) | ||||
350 | verify_klass(_masm, member_reg, VM_CLASS_ID(java_lang_invoke_MemberName)vmClassID::java_lang_invoke_MemberName_knum, | ||||
351 | "MemberName required for invokeVirtual etc."); | ||||
352 | } | ||||
353 | |||||
354 | Address member_clazz( member_reg, NONZERO(java_lang_invoke_MemberName::clazz_offset())check_nonzero("java_lang_invoke_MemberName::clazz_offset()", java_lang_invoke_MemberName ::clazz_offset())); | ||||
355 | Address member_vmindex( member_reg, NONZERO(java_lang_invoke_MemberName::vmindex_offset())check_nonzero("java_lang_invoke_MemberName::vmindex_offset()" , java_lang_invoke_MemberName::vmindex_offset())); | ||||
356 | Address member_vmtarget( member_reg, NONZERO(java_lang_invoke_MemberName::method_offset())check_nonzero("java_lang_invoke_MemberName::method_offset()", java_lang_invoke_MemberName::method_offset())); | ||||
357 | Address vmtarget_method( rbx_method, NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset())check_nonzero("java_lang_invoke_ResolvedMethodName::vmtarget_offset()" , java_lang_invoke_ResolvedMethodName::vmtarget_offset())); | ||||
358 | |||||
359 | Register temp1_recv_klass = temp1; | ||||
360 | if (iid != vmIntrinsics::_linkToStatic) { | ||||
361 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 361, _masm)-> verify_oop(receiver_reg)_verify_oop_checked(receiver_reg, "broken oop " "receiver_reg" , "/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 361); | ||||
362 | if (iid == vmIntrinsics::_linkToSpecial) { | ||||
363 | // Don't actually load the klass; just null-check the receiver. | ||||
364 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 364, _masm)-> null_check(receiver_reg); | ||||
365 | } else { | ||||
366 | // load receiver klass itself | ||||
367 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 367, _masm)-> null_check(receiver_reg, oopDesc::klass_offset_in_bytes()); | ||||
368 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 368, _masm)-> load_klass(temp1_recv_klass, receiver_reg, temp2); | ||||
369 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 369, _masm)-> verify_klass_ptr(temp1_recv_klass)_verify_klass_ptr(temp1_recv_klass, "broken klass " "temp1_recv_klass" , "/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 369); | ||||
370 | } | ||||
371 | BLOCK_COMMENT("check_receiver {")Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 371, _masm)-> block_comment("check_receiver {"); | ||||
372 | // The receiver for the MemberName must be in receiver_reg. | ||||
373 | // Check the receiver against the MemberName.clazz | ||||
374 | if (VerifyMethodHandles && iid == vmIntrinsics::_linkToSpecial) { | ||||
375 | // Did not load it above... | ||||
376 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 376, _masm)-> load_klass(temp1_recv_klass, receiver_reg, temp2); | ||||
377 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 377, _masm)-> verify_klass_ptr(temp1_recv_klass)_verify_klass_ptr(temp1_recv_klass, "broken klass " "temp1_recv_klass" , "/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 377); | ||||
378 | } | ||||
379 | if (VerifyMethodHandles && iid != vmIntrinsics::_linkToInterface) { | ||||
380 | Label L_ok; | ||||
381 | Register temp2_defc = temp2; | ||||
382 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 382, _masm)-> load_heap_oop(temp2_defc, member_clazz, temp3); | ||||
383 | load_klass_from_Class(_masm, temp2_defc); | ||||
384 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 384, _masm)-> verify_klass_ptr(temp2_defc)_verify_klass_ptr(temp2_defc, "broken klass " "temp2_defc", "/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 384); | ||||
385 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 385, _masm)-> check_klass_subtype(temp1_recv_klass, temp2_defc, temp3, L_ok); | ||||
386 | // If we get here, the type check failed! | ||||
387 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 387, _masm)-> STOP("receiver class disagrees with MemberName.clazz")block_comment("receiver class disagrees with MemberName.clazz" ); Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 387, _masm)-> stop("receiver class disagrees with MemberName.clazz" ); | ||||
388 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 388, _masm)-> bind(L_ok); | ||||
389 | } | ||||
390 | BLOCK_COMMENT("} check_receiver")Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 390, _masm)-> block_comment("} check_receiver"); | ||||
391 | } | ||||
392 | if (iid == vmIntrinsics::_linkToSpecial || | ||||
393 | iid == vmIntrinsics::_linkToStatic) { | ||||
394 | DEBUG_ONLY(temp1_recv_klass = noreg)temp1_recv_klass = noreg; // these guys didn't load the recv_klass | ||||
395 | } | ||||
396 | |||||
397 | // Live registers at this point: | ||||
398 | // member_reg - MemberName that was the trailing argument | ||||
399 | // temp1_recv_klass - klass of stacked receiver, if needed | ||||
400 | // rsi/r13 - interpreter linkage (if interpreted) | ||||
401 | // rcx, rdx, rsi, rdi, r8 - compiler arguments (if compiled) | ||||
402 | |||||
403 | Label L_incompatible_class_change_error; | ||||
404 | switch (iid) { | ||||
405 | case vmIntrinsics::_linkToSpecial: | ||||
406 | if (VerifyMethodHandles) { | ||||
407 | verify_ref_kind(_masm, JVM_REF_invokeSpecial, member_reg, temp3); | ||||
408 | } | ||||
409 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 409, _masm)-> load_heap_oop(rbx_method, member_vmtarget); | ||||
410 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 410, _masm)-> access_load_at(T_ADDRESS, IN_HEAP, rbx_method, vmtarget_method, noreg, noreg); | ||||
411 | break; | ||||
412 | |||||
413 | case vmIntrinsics::_linkToStatic: | ||||
414 | if (VerifyMethodHandles) { | ||||
415 | verify_ref_kind(_masm, JVM_REF_invokeStatic, member_reg, temp3); | ||||
416 | } | ||||
417 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 417, _masm)-> load_heap_oop(rbx_method, member_vmtarget); | ||||
418 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 418, _masm)-> access_load_at(T_ADDRESS, IN_HEAP, rbx_method, vmtarget_method, noreg, noreg); | ||||
419 | break; | ||||
420 | |||||
421 | case vmIntrinsics::_linkToVirtual: | ||||
422 | { | ||||
423 | // same as TemplateTable::invokevirtual, | ||||
424 | // minus the CP setup and profiling: | ||||
425 | |||||
426 | if (VerifyMethodHandles) { | ||||
427 | verify_ref_kind(_masm, JVM_REF_invokeVirtual, member_reg, temp3); | ||||
428 | } | ||||
429 | |||||
430 | // pick out the vtable index from the MemberName, and then we can discard it: | ||||
431 | Register temp2_index = temp2; | ||||
432 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 432, _masm)-> access_load_at(T_ADDRESS, IN_HEAP, temp2_index, member_vmindex, noreg, noreg); | ||||
433 | |||||
434 | if (VerifyMethodHandles) { | ||||
435 | Label L_index_ok; | ||||
436 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 436, _masm)-> cmpl(temp2_index, 0); | ||||
437 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 437, _masm)-> jcc(Assembler::greaterEqual, L_index_ok); | ||||
438 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 438, _masm)-> STOP("no virtual index")block_comment("no virtual index"); Disassembler::hook<MacroAssembler >("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 438, _masm)-> stop("no virtual index"); | ||||
439 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 439, _masm)-> BIND(L_index_ok)bind(L_index_ok); Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 439, _masm)-> block_comment("L_index_ok" ":"); | ||||
440 | } | ||||
441 | |||||
442 | // Note: The verifier invariants allow us to ignore MemberName.clazz and vmtarget | ||||
443 | // at this point. And VerifyMethodHandles has already checked clazz, if needed. | ||||
444 | |||||
445 | // get target Method* & entry point | ||||
446 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 446, _masm)-> lookup_virtual_method(temp1_recv_klass, temp2_index, rbx_method); | ||||
447 | break; | ||||
448 | } | ||||
449 | |||||
450 | case vmIntrinsics::_linkToInterface: | ||||
451 | { | ||||
452 | // same as TemplateTable::invokeinterface | ||||
453 | // (minus the CP setup and profiling, with different argument motion) | ||||
454 | if (VerifyMethodHandles) { | ||||
455 | verify_ref_kind(_masm, JVM_REF_invokeInterface, member_reg, temp3); | ||||
456 | } | ||||
457 | |||||
458 | Register temp3_intf = temp3; | ||||
459 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 459, _masm)-> load_heap_oop(temp3_intf, member_clazz); | ||||
460 | load_klass_from_Class(_masm, temp3_intf); | ||||
461 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 461, _masm)-> verify_klass_ptr(temp3_intf)_verify_klass_ptr(temp3_intf, "broken klass " "temp3_intf", "/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 461); | ||||
462 | |||||
463 | Register rbx_index = rbx_method; | ||||
464 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 464, _masm)-> access_load_at(T_ADDRESS, IN_HEAP, rbx_index, member_vmindex, noreg, noreg); | ||||
465 | if (VerifyMethodHandles) { | ||||
466 | Label L; | ||||
467 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 467, _masm)-> cmpl(rbx_index, 0); | ||||
468 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 468, _masm)-> jcc(Assembler::greaterEqual, L); | ||||
469 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 469, _masm)-> STOP("invalid vtable index for MH.invokeInterface")block_comment("invalid vtable index for MH.invokeInterface"); Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 469, _masm)-> stop("invalid vtable index for MH.invokeInterface" ); | ||||
470 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 470, _masm)-> bind(L); | ||||
471 | } | ||||
472 | |||||
473 | // given intf, index, and recv klass, dispatch to the implementation method | ||||
474 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 474, _masm)-> lookup_interface_method(temp1_recv_klass, temp3_intf, | ||||
475 | // note: next two args must be the same: | ||||
476 | rbx_index, rbx_method, | ||||
477 | temp2, | ||||
478 | L_incompatible_class_change_error); | ||||
479 | break; | ||||
480 | } | ||||
481 | |||||
482 | default: | ||||
483 | fatal("unexpected intrinsic %d: %s", vmIntrinsics::as_int(iid), vmIntrinsics::name_at(iid))do { (*g_assert_poison) = 'X';; report_fatal(INTERNAL_ERROR, "/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 483, "unexpected intrinsic %d: %s", vmIntrinsics::as_int(iid ), vmIntrinsics::name_at(iid)); ::breakpoint(); } while (0); | ||||
484 | break; | ||||
485 | } | ||||
486 | |||||
487 | // Live at this point: | ||||
488 | // rbx_method | ||||
489 | // rsi/r13 (if interpreted) | ||||
490 | |||||
491 | // After figuring out which concrete method to call, jump into it. | ||||
492 | // Note that this works in the interpreter with no data motion. | ||||
493 | // But the compiled version will require that rcx_recv be shifted out. | ||||
494 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 494, _masm)-> verify_method_ptr(rbx_method)_verify_method_ptr(rbx_method, "broken method " "rbx_method", "/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 494); | ||||
495 | jump_from_method_handle(_masm, rbx_method, temp1, for_compiler_entry); | ||||
496 | |||||
497 | if (iid == vmIntrinsics::_linkToInterface) { | ||||
498 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 498, _masm)-> bind(L_incompatible_class_change_error); | ||||
499 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 499, _masm)-> jump(RuntimeAddress(StubRoutines::throw_IncompatibleClassChangeError_entry())); | ||||
500 | } | ||||
501 | } | ||||
502 | } | ||||
503 | |||||
504 | #ifndef PRODUCT | ||||
505 | void trace_method_handle_stub(const char* adaptername, | ||||
506 | oopDesc* mh, | ||||
507 | intptr_t* saved_regs, | ||||
508 | intptr_t* entry_sp) { | ||||
509 | // called as a leaf from native code: do not block the JVM! | ||||
510 | bool has_mh = (strstr(adaptername, "/static") == NULL__null && | ||||
511 | strstr(adaptername, "linkTo") == NULL__null); // static linkers don't have MH | ||||
512 | const char* mh_reg_name = has_mh ? "rcx_mh" : "rcx"; | ||||
513 | log_info(methodhandles)(!(LogImpl<(LogTag::_methodhandles), (LogTag::__NO_TAG), ( LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag ::__NO_TAG)>::is_level(LogLevel::Info))) ? (void)0 : LogImpl <(LogTag::_methodhandles), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::write<LogLevel::Info>("MH %s %s=" PTR_FORMAT"0x%016" "l" "x" " sp=" PTR_FORMAT"0x%016" "l" "x", adaptername, mh_reg_name, p2i(mh), p2i(entry_sp)); | ||||
514 | |||||
515 | LogTarget(Trace, methodhandles)LogTargetImpl<LogLevel::Trace, (LogTag::_methodhandles), ( LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag ::__NO_TAG), (LogTag::__NO_TAG)> lt; | ||||
516 | if (lt.is_enabled()) { | ||||
517 | ResourceMark rm; | ||||
518 | LogStream ls(lt); | ||||
519 | ls.print_cr("Registers:"); | ||||
520 | const int saved_regs_count = RegisterImpl::number_of_registers; | ||||
521 | for (int i = 0; i < saved_regs_count; i++) { | ||||
522 | Register r = as_Register(i); | ||||
523 | // The registers are stored in reverse order on the stack (by pusha). | ||||
524 | #ifdef AMD641 | ||||
525 | assert(RegisterImpl::number_of_registers == 16, "sanity")do { if (!(RegisterImpl::number_of_registers == 16)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 525, "assert(" "RegisterImpl::number_of_registers == 16" ") failed" , "sanity"); ::breakpoint(); } } while (0); | ||||
526 | if (r == rsp) { | ||||
527 | // rsp is actually not stored by pusha(), compute the old rsp from saved_regs (rsp after pusha): saved_regs + 16 = old rsp | ||||
528 | ls.print("%3s=" PTR_FORMAT"0x%016" "l" "x", r->name(), (intptr_t)(&saved_regs[16])); | ||||
529 | } else { | ||||
530 | ls.print("%3s=" PTR_FORMAT"0x%016" "l" "x", r->name(), saved_regs[((saved_regs_count - 1) - i)]); | ||||
531 | } | ||||
532 | #else | ||||
533 | ls.print("%3s=" PTR_FORMAT"0x%016" "l" "x", r->name(), saved_regs[((saved_regs_count - 1) - i)]); | ||||
534 | #endif | ||||
535 | if ((i + 1) % 4 == 0) { | ||||
536 | ls.cr(); | ||||
537 | } else { | ||||
538 | ls.print(", "); | ||||
539 | } | ||||
540 | } | ||||
541 | ls.cr(); | ||||
542 | |||||
543 | // Note: We want to allow trace_method_handle from any call site. | ||||
544 | // While trace_method_handle creates a frame, it may be entered | ||||
545 | // without a PC on the stack top (e.g. not just after a call). | ||||
546 | // Walking that frame could lead to failures due to that invalid PC. | ||||
547 | // => carefully detect that frame when doing the stack walking | ||||
548 | |||||
549 | { | ||||
550 | // dumping last frame with frame::describe | ||||
551 | |||||
552 | JavaThread* p = JavaThread::active(); | ||||
553 | |||||
554 | // may not be needed by safer and unexpensive here | ||||
555 | PreserveExceptionMark pem(Thread::current()); | ||||
556 | FrameValues values; | ||||
557 | |||||
558 | frame cur_frame = os::current_frame(); | ||||
559 | |||||
560 | if (cur_frame.fp() != 0) { // not walkable | ||||
561 | |||||
562 | // Robust search of trace_calling_frame (independent of inlining). | ||||
563 | // Assumes saved_regs comes from a pusha in the trace_calling_frame. | ||||
564 | // | ||||
565 | // We have to start the search from cur_frame, because trace_calling_frame may be it. | ||||
566 | // It is guaranteed that trace_calling_frame is different from the top frame. | ||||
567 | // But os::current_frame() does NOT return the top frame: it returns the next frame under it (caller's frame). | ||||
568 | // (Due to inlining and tail call optimizations, caller's frame doesn't necessarily correspond to the immediate | ||||
569 | // caller in the source code.) | ||||
570 | assert(cur_frame.sp() < saved_regs, "registers not saved on stack ?")do { if (!(cur_frame.sp() < saved_regs)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 570, "assert(" "cur_frame.sp() < saved_regs" ") failed", "registers not saved on stack ?"); ::breakpoint(); } } while (0); | ||||
571 | frame trace_calling_frame = cur_frame; | ||||
572 | while (trace_calling_frame.fp() < saved_regs) { | ||||
573 | assert(trace_calling_frame.cb() == NULL, "not a C frame")do { if (!(trace_calling_frame.cb() == __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 573, "assert(" "trace_calling_frame.cb() == __null" ") failed" , "not a C frame"); ::breakpoint(); } } while (0); | ||||
574 | trace_calling_frame = os::get_sender_for_C_frame(&trace_calling_frame); | ||||
575 | } | ||||
576 | assert(trace_calling_frame.sp() < saved_regs, "wrong frame")do { if (!(trace_calling_frame.sp() < saved_regs)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 576, "assert(" "trace_calling_frame.sp() < saved_regs" ") failed" , "wrong frame"); ::breakpoint(); } } while (0); | ||||
577 | |||||
578 | // safely create a frame and call frame::describe | ||||
579 | intptr_t *dump_sp = trace_calling_frame.sender_sp(); | ||||
580 | intptr_t *dump_fp = trace_calling_frame.link(); | ||||
581 | |||||
582 | if (has_mh) { | ||||
583 | // The previous definition of walkable may have to be refined | ||||
584 | // if new call sites cause the next frame constructor to start | ||||
585 | // failing. Alternatively, frame constructors could be | ||||
586 | // modified to support the current or future non walkable | ||||
587 | // frames (but this is more intrusive and is not considered as | ||||
588 | // part of this RFE, which will instead use a simpler output). | ||||
589 | frame dump_frame = frame(dump_sp, dump_fp); | ||||
590 | dump_frame.describe(values, 1); | ||||
591 | } else { | ||||
592 | // Stack may not be walkable (invalid PC above FP): | ||||
593 | // Add descriptions without building a Java frame to avoid issues | ||||
594 | values.describe(-1, dump_fp, "fp for #1 <not parsed, cannot trust pc>"); | ||||
595 | values.describe(-1, dump_sp, "sp for #1"); | ||||
596 | } | ||||
597 | } | ||||
598 | values.describe(-1, entry_sp, "raw top of stack"); | ||||
599 | |||||
600 | ls.print_cr("Stack layout:"); | ||||
601 | values.print_on(p, &ls); | ||||
602 | } | ||||
603 | if (has_mh && oopDesc::is_oop(mh)) { | ||||
604 | mh->print_on(&ls); | ||||
605 | if (java_lang_invoke_MethodHandle::is_instance(mh)) { | ||||
606 | java_lang_invoke_MethodHandle::form(mh)->print_on(&ls); | ||||
607 | } | ||||
608 | } | ||||
609 | } | ||||
610 | } | ||||
611 | |||||
612 | // The stub wraps the arguments in a struct on the stack to avoid | ||||
613 | // dealing with the different calling conventions for passing 6 | ||||
614 | // arguments. | ||||
615 | struct MethodHandleStubArguments { | ||||
616 | const char* adaptername; | ||||
617 | oopDesc* mh; | ||||
618 | intptr_t* saved_regs; | ||||
619 | intptr_t* entry_sp; | ||||
620 | }; | ||||
621 | void trace_method_handle_stub_wrapper(MethodHandleStubArguments* args) { | ||||
622 | trace_method_handle_stub(args->adaptername, | ||||
623 | args->mh, | ||||
624 | args->saved_regs, | ||||
625 | args->entry_sp); | ||||
626 | } | ||||
627 | |||||
628 | void MethodHandles::trace_method_handle(MacroAssembler* _masm, const char* adaptername) { | ||||
629 | if (!log_is_enabled(Info, methodhandles)(LogImpl<(LogTag::_methodhandles), (LogTag::__NO_TAG), (LogTag ::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag:: __NO_TAG)>::is_level(LogLevel::Info))) return; | ||||
630 | BLOCK_COMMENT(err_msg("trace_method_handle %s {", adaptername))Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 630, _masm)-> block_comment(err_msg("trace_method_handle %s {" , adaptername)); | ||||
631 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 631, _masm)-> enter(); | ||||
632 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 632, _masm)-> andptr(rsp, -16); // align stack if needed for FPU state | ||||
633 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 633, _masm)-> pusha(); | ||||
634 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 634, _masm)-> mov(rbx, rsp); // for retreiving saved_regs | ||||
635 | // Note: saved_regs must be in the entered frame for the | ||||
636 | // robust stack walking implemented in trace_method_handle_stub. | ||||
637 | |||||
638 | // save FP result, valid at some call sites (adapter_opt_return_float, ...) | ||||
639 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 639, _masm)-> decrement(rsp, 2 * wordSize); | ||||
640 | #ifdef _LP641 | ||||
641 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 641, _masm)-> movdbl(Address(rsp, 0), xmm0); | ||||
642 | #else | ||||
643 | if (UseSSE >= 2) { | ||||
644 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 644, _masm)-> movdbl(Address(rsp, 0), xmm0); | ||||
645 | } else if (UseSSE == 1) { | ||||
646 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 646, _masm)-> movflt(Address(rsp, 0), xmm0); | ||||
647 | } else { | ||||
648 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 648, _masm)-> fst_d(Address(rsp, 0)); | ||||
649 | } | ||||
650 | #endif // LP64 | ||||
651 | |||||
652 | // Incoming state: | ||||
653 | // rcx: method handle | ||||
654 | // | ||||
655 | // To avoid calling convention issues, build a record on the stack | ||||
656 | // and pass the pointer to that instead. | ||||
657 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 657, _masm)-> push(rbp); // entry_sp (with extra align space) | ||||
658 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 658, _masm)-> push(rbx); // pusha saved_regs | ||||
659 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 659, _masm)-> push(rcx); // mh | ||||
660 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 660, _masm)-> push(rcx); // slot for adaptername | ||||
661 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 661, _masm)-> movptr(Address(rsp, 0), (intptr_t) adaptername); | ||||
662 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 662, _masm)-> super_call_VM_leaf(CAST_FROM_FN_PTR(address, trace_method_handle_stub_wrapper)((address)((address_word)(trace_method_handle_stub_wrapper))), rsp); | ||||
663 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 663, _masm)-> increment(rsp, sizeof(MethodHandleStubArguments)); | ||||
664 | |||||
665 | #ifdef _LP641 | ||||
666 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 666, _masm)-> movdbl(xmm0, Address(rsp, 0)); | ||||
667 | #else | ||||
668 | if (UseSSE >= 2) { | ||||
669 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 669, _masm)-> movdbl(xmm0, Address(rsp, 0)); | ||||
670 | } else if (UseSSE == 1) { | ||||
671 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 671, _masm)-> movflt(xmm0, Address(rsp, 0)); | ||||
672 | } else { | ||||
673 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 673, _masm)-> fld_d(Address(rsp, 0)); | ||||
674 | } | ||||
675 | #endif // LP64 | ||||
676 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 676, _masm)-> increment(rsp, 2 * wordSize); | ||||
677 | |||||
678 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 678, _masm)-> popa(); | ||||
679 | __Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 679, _masm)-> leave(); | ||||
680 | BLOCK_COMMENT("} trace_method_handle")Disassembler::hook<MacroAssembler>("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/methodHandles_x86.cpp" , 680, _masm)-> block_comment("} trace_method_handle"); | ||||
681 | } | ||||
682 | #endif //PRODUCT |
1 | /* | |||
2 | * Copyright (c) 2000, 2021, 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 | * | |||
23 | */ | |||
24 | ||||
25 | #ifndef SHARE_ASM_REGISTER_HPP | |||
26 | #define SHARE_ASM_REGISTER_HPP | |||
27 | ||||
28 | #include "utilities/debug.hpp" | |||
29 | #include "utilities/globalDefinitions.hpp" | |||
30 | #include "utilities/macros.hpp" | |||
31 | ||||
32 | // Use AbstractRegister as shortcut | |||
33 | class AbstractRegisterImpl; | |||
34 | typedef AbstractRegisterImpl* AbstractRegister; | |||
35 | ||||
36 | ||||
37 | // The super class for platform specific registers. Instead of using value objects, | |||
38 | // registers are implemented as pointers. Subclassing is used so all registers can | |||
39 | // use the debugging suport below. No virtual functions are used for efficiency. | |||
40 | // They are canonicalized; i.e., registers are equal if their pointers are equal, | |||
41 | // and vice versa. A concrete implementation may just map the register onto 'this'. | |||
42 | ||||
43 | class AbstractRegisterImpl { | |||
44 | protected: | |||
45 | int value() const { return (int)(intx)this; } | |||
46 | }; | |||
47 | ||||
48 | #define AS_REGISTER(type,name)((type)name_typeEnumValue) ((type)name##_##type##EnumValue) | |||
49 | ||||
50 | #define CONSTANT_REGISTER_DECLARATION(type, name, value)const type name = ((type)value); enum { name_typeEnumValue = ( value) } \ | |||
51 | const type name = ((type)value); \ | |||
52 | enum { name##_##type##EnumValue = (value) } | |||
53 | ||||
54 | #define REGISTER_DECLARATION(type, name, value)const type name = ((type)value) \ | |||
55 | const type name = ((type)value) | |||
56 | ||||
57 | #define REGISTER_DEFINITION(type, name) | |||
58 | ||||
59 | #include CPU_HEADER(register)"register_x86.hpp" | |||
60 | ||||
61 | // Debugging support | |||
62 | ||||
63 | template<typename R, typename... Rx> | |||
64 | inline void assert_different_registers(R first_register, Rx... more_registers) { | |||
65 | #ifdef ASSERT1 | |||
66 | const R regs[] = { first_register, more_registers... }; | |||
67 | // Verify there are no equal entries. | |||
68 | for (size_t i = 0; i < ARRAY_SIZE(regs)sizeof(array_size_impl(regs)) - 1; ++i) { | |||
69 | for (size_t j = i + 1; j < ARRAY_SIZE(regs)sizeof(array_size_impl(regs)); ++j) { | |||
70 | assert(regs[i] != regs[j], "Multiple uses of register: %s", regs[i]->name())do { if (!(regs[i] != regs[j])) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/asm/register.hpp" , 70, "assert(" "regs[i] != regs[j]" ") failed", "Multiple uses of register: %s" , regs[i]->name()); ::breakpoint(); } } while (0); | |||
| ||||
71 | } | |||
72 | } | |||
73 | #endif | |||
74 | } | |||
75 | ||||
76 | #endif // SHARE_ASM_REGISTER_HPP |