annotate src/cpu/sparc/vm/cppInterpreter_sparc.cpp @ 3249:e1162778c1c8

7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error Summary: A referent object that is only weakly reachable at the start of concurrent marking but is re-attached to the strongly reachable object graph during marking may not be marked as live. This can cause the reference object to be processed prematurely and leave dangling pointers to the referent object. Implement a read barrier for the java.lang.ref.Reference::referent field by intrinsifying the Reference.get() method, and intercepting accesses though JNI, reflection, and Unsafe, so that when a non-null referent object is read it is also logged in an SATB buffer. Reviewed-by: kvn, iveresov, never, tonyp, dholmes
author johnc
date Thu, 07 Apr 2011 09:53:20 -0700
parents 8033953d67ff
children 92add02409c9
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1 /*
2357
8033953d67ff 7012648: move JSR 292 to package java.lang.invoke and adjust names
jrose
parents: 1972
diff changeset
2 * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
a61af66fc99e Initial load
duke
parents:
diff changeset
4 *
a61af66fc99e Initial load
duke
parents:
diff changeset
5 * This code is free software; you can redistribute it and/or modify it
a61af66fc99e Initial load
duke
parents:
diff changeset
6 * under the terms of the GNU General Public License version 2 only, as
a61af66fc99e Initial load
duke
parents:
diff changeset
7 * published by the Free Software Foundation.
a61af66fc99e Initial load
duke
parents:
diff changeset
8 *
a61af66fc99e Initial load
duke
parents:
diff changeset
9 * This code is distributed in the hope that it will be useful, but WITHOUT
a61af66fc99e Initial load
duke
parents:
diff changeset
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
a61af66fc99e Initial load
duke
parents:
diff changeset
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
a61af66fc99e Initial load
duke
parents:
diff changeset
12 * version 2 for more details (a copy is included in the LICENSE file that
a61af66fc99e Initial load
duke
parents:
diff changeset
13 * accompanied this code).
a61af66fc99e Initial load
duke
parents:
diff changeset
14 *
a61af66fc99e Initial load
duke
parents:
diff changeset
15 * You should have received a copy of the GNU General Public License version
a61af66fc99e Initial load
duke
parents:
diff changeset
16 * 2 along with this work; if not, write to the Free Software Foundation,
a61af66fc99e Initial load
duke
parents:
diff changeset
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
a61af66fc99e Initial load
duke
parents:
diff changeset
18 *
1552
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 710
diff changeset
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 710
diff changeset
20 * or visit www.oracle.com if you need additional information or have any
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 710
diff changeset
21 * questions.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
22 *
a61af66fc99e Initial load
duke
parents:
diff changeset
23 */
a61af66fc99e Initial load
duke
parents:
diff changeset
24
1972
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
25 #include "precompiled.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
26 #include "asm/assembler.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
27 #include "interpreter/bytecodeHistogram.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
28 #include "interpreter/cppInterpreter.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
29 #include "interpreter/interpreter.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
30 #include "interpreter/interpreterGenerator.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
31 #include "interpreter/interpreterRuntime.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
32 #include "oops/arrayOop.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
33 #include "oops/methodDataOop.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
34 #include "oops/methodOop.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
35 #include "oops/oop.inline.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
36 #include "prims/jvmtiExport.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
37 #include "prims/jvmtiThreadState.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
38 #include "runtime/arguments.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
39 #include "runtime/deoptimization.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
40 #include "runtime/frame.inline.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
41 #include "runtime/interfaceSupport.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
42 #include "runtime/sharedRuntime.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
43 #include "runtime/stubRoutines.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
44 #include "runtime/synchronizer.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
45 #include "runtime/timer.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
46 #include "runtime/vframeArray.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
47 #include "utilities/debug.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
48 #ifdef SHARK
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
49 #include "shark/shark_globals.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
50 #endif
0
a61af66fc99e Initial load
duke
parents:
diff changeset
51
a61af66fc99e Initial load
duke
parents:
diff changeset
52 #ifdef CC_INTERP
a61af66fc99e Initial load
duke
parents:
diff changeset
53
a61af66fc99e Initial load
duke
parents:
diff changeset
54 // Routine exists to make tracebacks look decent in debugger
a61af66fc99e Initial load
duke
parents:
diff changeset
55 // while "shadow" interpreter frames are on stack. It is also
a61af66fc99e Initial load
duke
parents:
diff changeset
56 // used to distinguish interpreter frames.
a61af66fc99e Initial load
duke
parents:
diff changeset
57
a61af66fc99e Initial load
duke
parents:
diff changeset
58 extern "C" void RecursiveInterpreterActivation(interpreterState istate) {
a61af66fc99e Initial load
duke
parents:
diff changeset
59 ShouldNotReachHere();
a61af66fc99e Initial load
duke
parents:
diff changeset
60 }
a61af66fc99e Initial load
duke
parents:
diff changeset
61
a61af66fc99e Initial load
duke
parents:
diff changeset
62 bool CppInterpreter::contains(address pc) {
a61af66fc99e Initial load
duke
parents:
diff changeset
63 return ( _code->contains(pc) ||
a61af66fc99e Initial load
duke
parents:
diff changeset
64 ( pc == (CAST_FROM_FN_PTR(address, RecursiveInterpreterActivation) + frame::pc_return_offset)));
a61af66fc99e Initial load
duke
parents:
diff changeset
65 }
a61af66fc99e Initial load
duke
parents:
diff changeset
66
a61af66fc99e Initial load
duke
parents:
diff changeset
67 #define STATE(field_name) Lstate, in_bytes(byte_offset_of(BytecodeInterpreter, field_name))
a61af66fc99e Initial load
duke
parents:
diff changeset
68 #define __ _masm->
a61af66fc99e Initial load
duke
parents:
diff changeset
69
a61af66fc99e Initial load
duke
parents:
diff changeset
70 Label frame_manager_entry;
a61af66fc99e Initial load
duke
parents:
diff changeset
71 Label fast_accessor_slow_entry_path; // fast accessor methods need to be able to jmp to unsynchronized
a61af66fc99e Initial load
duke
parents:
diff changeset
72 // c++ interpreter entry point this holds that entry point label.
a61af66fc99e Initial load
duke
parents:
diff changeset
73
a61af66fc99e Initial load
duke
parents:
diff changeset
74 static address unctrap_frame_manager_entry = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
75
a61af66fc99e Initial load
duke
parents:
diff changeset
76 static address interpreter_return_address = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
77 static address deopt_frame_manager_return_atos = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
78 static address deopt_frame_manager_return_btos = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
79 static address deopt_frame_manager_return_itos = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
80 static address deopt_frame_manager_return_ltos = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
81 static address deopt_frame_manager_return_ftos = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
82 static address deopt_frame_manager_return_dtos = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
83 static address deopt_frame_manager_return_vtos = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
84
a61af66fc99e Initial load
duke
parents:
diff changeset
85 const Register prevState = G1_scratch;
a61af66fc99e Initial load
duke
parents:
diff changeset
86
a61af66fc99e Initial load
duke
parents:
diff changeset
87 void InterpreterGenerator::save_native_result(void) {
a61af66fc99e Initial load
duke
parents:
diff changeset
88 // result potentially in O0/O1: save it across calls
a61af66fc99e Initial load
duke
parents:
diff changeset
89 __ stf(FloatRegisterImpl::D, F0, STATE(_native_fresult));
a61af66fc99e Initial load
duke
parents:
diff changeset
90 #ifdef _LP64
a61af66fc99e Initial load
duke
parents:
diff changeset
91 __ stx(O0, STATE(_native_lresult));
a61af66fc99e Initial load
duke
parents:
diff changeset
92 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
93 __ std(O0, STATE(_native_lresult));
a61af66fc99e Initial load
duke
parents:
diff changeset
94 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
95 }
a61af66fc99e Initial load
duke
parents:
diff changeset
96
a61af66fc99e Initial load
duke
parents:
diff changeset
97 void InterpreterGenerator::restore_native_result(void) {
a61af66fc99e Initial load
duke
parents:
diff changeset
98
a61af66fc99e Initial load
duke
parents:
diff changeset
99 // Restore any method result value
a61af66fc99e Initial load
duke
parents:
diff changeset
100 __ ldf(FloatRegisterImpl::D, STATE(_native_fresult), F0);
a61af66fc99e Initial load
duke
parents:
diff changeset
101 #ifdef _LP64
a61af66fc99e Initial load
duke
parents:
diff changeset
102 __ ldx(STATE(_native_lresult), O0);
a61af66fc99e Initial load
duke
parents:
diff changeset
103 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
104 __ ldd(STATE(_native_lresult), O0);
a61af66fc99e Initial load
duke
parents:
diff changeset
105 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
106 }
a61af66fc99e Initial load
duke
parents:
diff changeset
107
a61af66fc99e Initial load
duke
parents:
diff changeset
108 // A result handler converts/unboxes a native call result into
a61af66fc99e Initial load
duke
parents:
diff changeset
109 // a java interpreter/compiler result. The current frame is an
a61af66fc99e Initial load
duke
parents:
diff changeset
110 // interpreter frame. The activation frame unwind code must be
a61af66fc99e Initial load
duke
parents:
diff changeset
111 // consistent with that of TemplateTable::_return(...). In the
a61af66fc99e Initial load
duke
parents:
diff changeset
112 // case of native methods, the caller's SP was not modified.
a61af66fc99e Initial load
duke
parents:
diff changeset
113 address CppInterpreterGenerator::generate_result_handler_for(BasicType type) {
a61af66fc99e Initial load
duke
parents:
diff changeset
114 address entry = __ pc();
a61af66fc99e Initial load
duke
parents:
diff changeset
115 Register Itos_i = Otos_i ->after_save();
a61af66fc99e Initial load
duke
parents:
diff changeset
116 Register Itos_l = Otos_l ->after_save();
a61af66fc99e Initial load
duke
parents:
diff changeset
117 Register Itos_l1 = Otos_l1->after_save();
a61af66fc99e Initial load
duke
parents:
diff changeset
118 Register Itos_l2 = Otos_l2->after_save();
a61af66fc99e Initial load
duke
parents:
diff changeset
119 switch (type) {
a61af66fc99e Initial load
duke
parents:
diff changeset
120 case T_BOOLEAN: __ subcc(G0, O0, G0); __ addc(G0, 0, Itos_i); break; // !0 => true; 0 => false
a61af66fc99e Initial load
duke
parents:
diff changeset
121 case T_CHAR : __ sll(O0, 16, O0); __ srl(O0, 16, Itos_i); break; // cannot use and3, 0xFFFF too big as immediate value!
a61af66fc99e Initial load
duke
parents:
diff changeset
122 case T_BYTE : __ sll(O0, 24, O0); __ sra(O0, 24, Itos_i); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
123 case T_SHORT : __ sll(O0, 16, O0); __ sra(O0, 16, Itos_i); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
124 case T_LONG :
a61af66fc99e Initial load
duke
parents:
diff changeset
125 #ifndef _LP64
a61af66fc99e Initial load
duke
parents:
diff changeset
126 __ mov(O1, Itos_l2); // move other half of long
a61af66fc99e Initial load
duke
parents:
diff changeset
127 #endif // ifdef or no ifdef, fall through to the T_INT case
a61af66fc99e Initial load
duke
parents:
diff changeset
128 case T_INT : __ mov(O0, Itos_i); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
129 case T_VOID : /* nothing to do */ break;
a61af66fc99e Initial load
duke
parents:
diff changeset
130 case T_FLOAT : assert(F0 == Ftos_f, "fix this code" ); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
131 case T_DOUBLE : assert(F0 == Ftos_d, "fix this code" ); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
132 case T_OBJECT :
a61af66fc99e Initial load
duke
parents:
diff changeset
133 __ ld_ptr(STATE(_oop_temp), Itos_i);
a61af66fc99e Initial load
duke
parents:
diff changeset
134 __ verify_oop(Itos_i);
a61af66fc99e Initial load
duke
parents:
diff changeset
135 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
136 default : ShouldNotReachHere();
a61af66fc99e Initial load
duke
parents:
diff changeset
137 }
a61af66fc99e Initial load
duke
parents:
diff changeset
138 __ ret(); // return from interpreter activation
a61af66fc99e Initial load
duke
parents:
diff changeset
139 __ delayed()->restore(I5_savedSP, G0, SP); // remove interpreter frame
a61af66fc99e Initial load
duke
parents:
diff changeset
140 NOT_PRODUCT(__ emit_long(0);) // marker for disassembly
a61af66fc99e Initial load
duke
parents:
diff changeset
141 return entry;
a61af66fc99e Initial load
duke
parents:
diff changeset
142 }
a61af66fc99e Initial load
duke
parents:
diff changeset
143
a61af66fc99e Initial load
duke
parents:
diff changeset
144 // tosca based result to c++ interpreter stack based result.
a61af66fc99e Initial load
duke
parents:
diff changeset
145 // Result goes to address in L1_scratch
a61af66fc99e Initial load
duke
parents:
diff changeset
146
a61af66fc99e Initial load
duke
parents:
diff changeset
147 address CppInterpreterGenerator::generate_tosca_to_stack_converter(BasicType type) {
a61af66fc99e Initial load
duke
parents:
diff changeset
148 // A result is in the native abi result register from a native method call.
a61af66fc99e Initial load
duke
parents:
diff changeset
149 // We need to return this result to the interpreter by pushing the result on the interpreter's
a61af66fc99e Initial load
duke
parents:
diff changeset
150 // stack. This is relatively simple the destination is in L1_scratch
a61af66fc99e Initial load
duke
parents:
diff changeset
151 // i.e. L1_scratch is the first free element on the stack. If we "push" a return value we must
a61af66fc99e Initial load
duke
parents:
diff changeset
152 // adjust L1_scratch
a61af66fc99e Initial load
duke
parents:
diff changeset
153 address entry = __ pc();
a61af66fc99e Initial load
duke
parents:
diff changeset
154 switch (type) {
a61af66fc99e Initial load
duke
parents:
diff changeset
155 case T_BOOLEAN:
a61af66fc99e Initial load
duke
parents:
diff changeset
156 // !0 => true; 0 => false
a61af66fc99e Initial load
duke
parents:
diff changeset
157 __ subcc(G0, O0, G0);
a61af66fc99e Initial load
duke
parents:
diff changeset
158 __ addc(G0, 0, O0);
a61af66fc99e Initial load
duke
parents:
diff changeset
159 __ st(O0, L1_scratch, 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
160 __ sub(L1_scratch, wordSize, L1_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
161 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
162
a61af66fc99e Initial load
duke
parents:
diff changeset
163 // cannot use and3, 0xFFFF too big as immediate value!
a61af66fc99e Initial load
duke
parents:
diff changeset
164 case T_CHAR :
a61af66fc99e Initial load
duke
parents:
diff changeset
165 __ sll(O0, 16, O0);
a61af66fc99e Initial load
duke
parents:
diff changeset
166 __ srl(O0, 16, O0);
a61af66fc99e Initial load
duke
parents:
diff changeset
167 __ st(O0, L1_scratch, 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
168 __ sub(L1_scratch, wordSize, L1_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
169 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
170
a61af66fc99e Initial load
duke
parents:
diff changeset
171 case T_BYTE :
a61af66fc99e Initial load
duke
parents:
diff changeset
172 __ sll(O0, 24, O0);
a61af66fc99e Initial load
duke
parents:
diff changeset
173 __ sra(O0, 24, O0);
a61af66fc99e Initial load
duke
parents:
diff changeset
174 __ st(O0, L1_scratch, 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
175 __ sub(L1_scratch, wordSize, L1_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
176 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
177
a61af66fc99e Initial load
duke
parents:
diff changeset
178 case T_SHORT :
a61af66fc99e Initial load
duke
parents:
diff changeset
179 __ sll(O0, 16, O0);
a61af66fc99e Initial load
duke
parents:
diff changeset
180 __ sra(O0, 16, O0);
a61af66fc99e Initial load
duke
parents:
diff changeset
181 __ st(O0, L1_scratch, 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
182 __ sub(L1_scratch, wordSize, L1_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
183 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
184 case T_LONG :
a61af66fc99e Initial load
duke
parents:
diff changeset
185 #ifndef _LP64
123
9e5a7340635e 6688137: c++ interpreter fails on 64bit sparc
sgoldman
parents: 0
diff changeset
186 #if defined(COMPILER2)
0
a61af66fc99e Initial load
duke
parents:
diff changeset
187 // All return values are where we want them, except for Longs. C2 returns
a61af66fc99e Initial load
duke
parents:
diff changeset
188 // longs in G1 in the 32-bit build whereas the interpreter wants them in O0/O1.
a61af66fc99e Initial load
duke
parents:
diff changeset
189 // Since the interpreter will return longs in G1 and O0/O1 in the 32bit
a61af66fc99e Initial load
duke
parents:
diff changeset
190 // build even if we are returning from interpreted we just do a little
a61af66fc99e Initial load
duke
parents:
diff changeset
191 // stupid shuffing.
a61af66fc99e Initial load
duke
parents:
diff changeset
192 // Note: I tried to make c2 return longs in O0/O1 and G1 so we wouldn't have to
a61af66fc99e Initial load
duke
parents:
diff changeset
193 // do this here. Unfortunately if we did a rethrow we'd see an machepilog node
a61af66fc99e Initial load
duke
parents:
diff changeset
194 // first which would move g1 -> O0/O1 and destroy the exception we were throwing.
a61af66fc99e Initial load
duke
parents:
diff changeset
195 __ stx(G1, L1_scratch, -wordSize);
a61af66fc99e Initial load
duke
parents:
diff changeset
196 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
197 // native result is in O0, O1
a61af66fc99e Initial load
duke
parents:
diff changeset
198 __ st(O1, L1_scratch, 0); // Low order
a61af66fc99e Initial load
duke
parents:
diff changeset
199 __ st(O0, L1_scratch, -wordSize); // High order
123
9e5a7340635e 6688137: c++ interpreter fails on 64bit sparc
sgoldman
parents: 0
diff changeset
200 #endif /* COMPILER2 */
0
a61af66fc99e Initial load
duke
parents:
diff changeset
201 #else
123
9e5a7340635e 6688137: c++ interpreter fails on 64bit sparc
sgoldman
parents: 0
diff changeset
202 __ stx(O0, L1_scratch, -wordSize);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
203 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
204 __ sub(L1_scratch, 2*wordSize, L1_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
205 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
206
a61af66fc99e Initial load
duke
parents:
diff changeset
207 case T_INT :
a61af66fc99e Initial load
duke
parents:
diff changeset
208 __ st(O0, L1_scratch, 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
209 __ sub(L1_scratch, wordSize, L1_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
210 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
211
a61af66fc99e Initial load
duke
parents:
diff changeset
212 case T_VOID : /* nothing to do */
a61af66fc99e Initial load
duke
parents:
diff changeset
213 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
214
a61af66fc99e Initial load
duke
parents:
diff changeset
215 case T_FLOAT :
a61af66fc99e Initial load
duke
parents:
diff changeset
216 __ stf(FloatRegisterImpl::S, F0, L1_scratch, 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
217 __ sub(L1_scratch, wordSize, L1_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
218 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
219
a61af66fc99e Initial load
duke
parents:
diff changeset
220 case T_DOUBLE :
a61af66fc99e Initial load
duke
parents:
diff changeset
221 // Every stack slot is aligned on 64 bit, However is this
a61af66fc99e Initial load
duke
parents:
diff changeset
222 // the correct stack slot on 64bit?? QQQ
a61af66fc99e Initial load
duke
parents:
diff changeset
223 __ stf(FloatRegisterImpl::D, F0, L1_scratch, -wordSize);
a61af66fc99e Initial load
duke
parents:
diff changeset
224 __ sub(L1_scratch, 2*wordSize, L1_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
225 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
226 case T_OBJECT :
a61af66fc99e Initial load
duke
parents:
diff changeset
227 __ verify_oop(O0);
a61af66fc99e Initial load
duke
parents:
diff changeset
228 __ st_ptr(O0, L1_scratch, 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
229 __ sub(L1_scratch, wordSize, L1_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
230 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
231 default : ShouldNotReachHere();
a61af66fc99e Initial load
duke
parents:
diff changeset
232 }
a61af66fc99e Initial load
duke
parents:
diff changeset
233 __ retl(); // return from interpreter activation
a61af66fc99e Initial load
duke
parents:
diff changeset
234 __ delayed()->nop(); // schedule this better
a61af66fc99e Initial load
duke
parents:
diff changeset
235 NOT_PRODUCT(__ emit_long(0);) // marker for disassembly
a61af66fc99e Initial load
duke
parents:
diff changeset
236 return entry;
a61af66fc99e Initial load
duke
parents:
diff changeset
237 }
a61af66fc99e Initial load
duke
parents:
diff changeset
238
a61af66fc99e Initial load
duke
parents:
diff changeset
239 address CppInterpreterGenerator::generate_stack_to_stack_converter(BasicType type) {
a61af66fc99e Initial load
duke
parents:
diff changeset
240 // A result is in the java expression stack of the interpreted method that has just
a61af66fc99e Initial load
duke
parents:
diff changeset
241 // returned. Place this result on the java expression stack of the caller.
a61af66fc99e Initial load
duke
parents:
diff changeset
242 //
a61af66fc99e Initial load
duke
parents:
diff changeset
243 // The current interpreter activation in Lstate is for the method just returning its
a61af66fc99e Initial load
duke
parents:
diff changeset
244 // result. So we know that the result of this method is on the top of the current
a61af66fc99e Initial load
duke
parents:
diff changeset
245 // execution stack (which is pre-pushed) and will be return to the top of the caller
a61af66fc99e Initial load
duke
parents:
diff changeset
246 // stack. The top of the callers stack is the bottom of the locals of the current
a61af66fc99e Initial load
duke
parents:
diff changeset
247 // activation.
a61af66fc99e Initial load
duke
parents:
diff changeset
248 // Because of the way activation are managed by the frame manager the value of esp is
a61af66fc99e Initial load
duke
parents:
diff changeset
249 // below both the stack top of the current activation and naturally the stack top
a61af66fc99e Initial load
duke
parents:
diff changeset
250 // of the calling activation. This enable this routine to leave the return address
a61af66fc99e Initial load
duke
parents:
diff changeset
251 // to the frame manager on the stack and do a vanilla return.
a61af66fc99e Initial load
duke
parents:
diff changeset
252 //
a61af66fc99e Initial load
duke
parents:
diff changeset
253 // On entry: O0 - points to source (callee stack top)
a61af66fc99e Initial load
duke
parents:
diff changeset
254 // O1 - points to destination (caller stack top [i.e. free location])
a61af66fc99e Initial load
duke
parents:
diff changeset
255 // destroys O2, O3
a61af66fc99e Initial load
duke
parents:
diff changeset
256 //
a61af66fc99e Initial load
duke
parents:
diff changeset
257
a61af66fc99e Initial load
duke
parents:
diff changeset
258 address entry = __ pc();
a61af66fc99e Initial load
duke
parents:
diff changeset
259 switch (type) {
a61af66fc99e Initial load
duke
parents:
diff changeset
260 case T_VOID: break;
a61af66fc99e Initial load
duke
parents:
diff changeset
261 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
262 case T_FLOAT :
a61af66fc99e Initial load
duke
parents:
diff changeset
263 case T_BOOLEAN:
a61af66fc99e Initial load
duke
parents:
diff changeset
264 case T_CHAR :
a61af66fc99e Initial load
duke
parents:
diff changeset
265 case T_BYTE :
a61af66fc99e Initial load
duke
parents:
diff changeset
266 case T_SHORT :
a61af66fc99e Initial load
duke
parents:
diff changeset
267 case T_INT :
a61af66fc99e Initial load
duke
parents:
diff changeset
268 // 1 word result
a61af66fc99e Initial load
duke
parents:
diff changeset
269 __ ld(O0, 0, O2);
a61af66fc99e Initial load
duke
parents:
diff changeset
270 __ st(O2, O1, 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
271 __ sub(O1, wordSize, O1);
a61af66fc99e Initial load
duke
parents:
diff changeset
272 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
273 case T_DOUBLE :
a61af66fc99e Initial load
duke
parents:
diff changeset
274 case T_LONG :
a61af66fc99e Initial load
duke
parents:
diff changeset
275 // return top two words on current expression stack to caller's expression stack
a61af66fc99e Initial load
duke
parents:
diff changeset
276 // The caller's expression stack is adjacent to the current frame manager's intepretState
a61af66fc99e Initial load
duke
parents:
diff changeset
277 // except we allocated one extra word for this intepretState so we won't overwrite it
a61af66fc99e Initial load
duke
parents:
diff changeset
278 // when we return a two word result.
a61af66fc99e Initial load
duke
parents:
diff changeset
279 #ifdef _LP64
a61af66fc99e Initial load
duke
parents:
diff changeset
280 __ ld_ptr(O0, 0, O2);
a61af66fc99e Initial load
duke
parents:
diff changeset
281 __ st_ptr(O2, O1, -wordSize);
a61af66fc99e Initial load
duke
parents:
diff changeset
282 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
283 __ ld(O0, 0, O2);
a61af66fc99e Initial load
duke
parents:
diff changeset
284 __ ld(O0, wordSize, O3);
a61af66fc99e Initial load
duke
parents:
diff changeset
285 __ st(O3, O1, 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
286 __ st(O2, O1, -wordSize);
a61af66fc99e Initial load
duke
parents:
diff changeset
287 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
288 __ sub(O1, 2*wordSize, O1);
a61af66fc99e Initial load
duke
parents:
diff changeset
289 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
290 case T_OBJECT :
a61af66fc99e Initial load
duke
parents:
diff changeset
291 __ ld_ptr(O0, 0, O2);
a61af66fc99e Initial load
duke
parents:
diff changeset
292 __ verify_oop(O2); // verify it
a61af66fc99e Initial load
duke
parents:
diff changeset
293 __ st_ptr(O2, O1, 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
294 __ sub(O1, wordSize, O1);
a61af66fc99e Initial load
duke
parents:
diff changeset
295 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
296 default : ShouldNotReachHere();
a61af66fc99e Initial load
duke
parents:
diff changeset
297 }
a61af66fc99e Initial load
duke
parents:
diff changeset
298 __ retl();
a61af66fc99e Initial load
duke
parents:
diff changeset
299 __ delayed()->nop(); // QQ schedule this better
a61af66fc99e Initial load
duke
parents:
diff changeset
300 return entry;
a61af66fc99e Initial load
duke
parents:
diff changeset
301 }
a61af66fc99e Initial load
duke
parents:
diff changeset
302
a61af66fc99e Initial load
duke
parents:
diff changeset
303 address CppInterpreterGenerator::generate_stack_to_native_abi_converter(BasicType type) {
a61af66fc99e Initial load
duke
parents:
diff changeset
304 // A result is in the java expression stack of the interpreted method that has just
a61af66fc99e Initial load
duke
parents:
diff changeset
305 // returned. Place this result in the native abi that the caller expects.
a61af66fc99e Initial load
duke
parents:
diff changeset
306 // We are in a new frame registers we set must be in caller (i.e. callstub) frame.
a61af66fc99e Initial load
duke
parents:
diff changeset
307 //
a61af66fc99e Initial load
duke
parents:
diff changeset
308 // Similar to generate_stack_to_stack_converter above. Called at a similar time from the
a61af66fc99e Initial load
duke
parents:
diff changeset
309 // frame manager execept in this situation the caller is native code (c1/c2/call_stub)
a61af66fc99e Initial load
duke
parents:
diff changeset
310 // and so rather than return result onto caller's java expression stack we return the
a61af66fc99e Initial load
duke
parents:
diff changeset
311 // result in the expected location based on the native abi.
a61af66fc99e Initial load
duke
parents:
diff changeset
312 // On entry: O0 - source (stack top)
a61af66fc99e Initial load
duke
parents:
diff changeset
313 // On exit result in expected output register
a61af66fc99e Initial load
duke
parents:
diff changeset
314 // QQQ schedule this better
a61af66fc99e Initial load
duke
parents:
diff changeset
315
a61af66fc99e Initial load
duke
parents:
diff changeset
316 address entry = __ pc();
a61af66fc99e Initial load
duke
parents:
diff changeset
317 switch (type) {
a61af66fc99e Initial load
duke
parents:
diff changeset
318 case T_VOID: break;
a61af66fc99e Initial load
duke
parents:
diff changeset
319 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
320 case T_FLOAT :
a61af66fc99e Initial load
duke
parents:
diff changeset
321 __ ldf(FloatRegisterImpl::S, O0, 0, F0);
a61af66fc99e Initial load
duke
parents:
diff changeset
322 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
323 case T_BOOLEAN:
a61af66fc99e Initial load
duke
parents:
diff changeset
324 case T_CHAR :
a61af66fc99e Initial load
duke
parents:
diff changeset
325 case T_BYTE :
a61af66fc99e Initial load
duke
parents:
diff changeset
326 case T_SHORT :
a61af66fc99e Initial load
duke
parents:
diff changeset
327 case T_INT :
a61af66fc99e Initial load
duke
parents:
diff changeset
328 // 1 word result
a61af66fc99e Initial load
duke
parents:
diff changeset
329 __ ld(O0, 0, O0->after_save());
a61af66fc99e Initial load
duke
parents:
diff changeset
330 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
331 case T_DOUBLE :
a61af66fc99e Initial load
duke
parents:
diff changeset
332 __ ldf(FloatRegisterImpl::D, O0, 0, F0);
a61af66fc99e Initial load
duke
parents:
diff changeset
333 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
334 case T_LONG :
a61af66fc99e Initial load
duke
parents:
diff changeset
335 // return top two words on current expression stack to caller's expression stack
a61af66fc99e Initial load
duke
parents:
diff changeset
336 // The caller's expression stack is adjacent to the current frame manager's interpretState
a61af66fc99e Initial load
duke
parents:
diff changeset
337 // except we allocated one extra word for this intepretState so we won't overwrite it
a61af66fc99e Initial load
duke
parents:
diff changeset
338 // when we return a two word result.
a61af66fc99e Initial load
duke
parents:
diff changeset
339 #ifdef _LP64
a61af66fc99e Initial load
duke
parents:
diff changeset
340 __ ld_ptr(O0, 0, O0->after_save());
a61af66fc99e Initial load
duke
parents:
diff changeset
341 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
342 __ ld(O0, wordSize, O1->after_save());
a61af66fc99e Initial load
duke
parents:
diff changeset
343 __ ld(O0, 0, O0->after_save());
a61af66fc99e Initial load
duke
parents:
diff changeset
344 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
345 #if defined(COMPILER2) && !defined(_LP64)
a61af66fc99e Initial load
duke
parents:
diff changeset
346 // C2 expects long results in G1 we can't tell if we're returning to interpreted
a61af66fc99e Initial load
duke
parents:
diff changeset
347 // or compiled so just be safe use G1 and O0/O1
a61af66fc99e Initial load
duke
parents:
diff changeset
348
a61af66fc99e Initial load
duke
parents:
diff changeset
349 // Shift bits into high (msb) of G1
a61af66fc99e Initial load
duke
parents:
diff changeset
350 __ sllx(Otos_l1->after_save(), 32, G1);
a61af66fc99e Initial load
duke
parents:
diff changeset
351 // Zero extend low bits
a61af66fc99e Initial load
duke
parents:
diff changeset
352 __ srl (Otos_l2->after_save(), 0, Otos_l2->after_save());
a61af66fc99e Initial load
duke
parents:
diff changeset
353 __ or3 (Otos_l2->after_save(), G1, G1);
a61af66fc99e Initial load
duke
parents:
diff changeset
354 #endif /* COMPILER2 */
a61af66fc99e Initial load
duke
parents:
diff changeset
355 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
356 case T_OBJECT :
a61af66fc99e Initial load
duke
parents:
diff changeset
357 __ ld_ptr(O0, 0, O0->after_save());
a61af66fc99e Initial load
duke
parents:
diff changeset
358 __ verify_oop(O0->after_save()); // verify it
a61af66fc99e Initial load
duke
parents:
diff changeset
359 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
360 default : ShouldNotReachHere();
a61af66fc99e Initial load
duke
parents:
diff changeset
361 }
a61af66fc99e Initial load
duke
parents:
diff changeset
362 __ retl();
a61af66fc99e Initial load
duke
parents:
diff changeset
363 __ delayed()->nop();
a61af66fc99e Initial load
duke
parents:
diff changeset
364 return entry;
a61af66fc99e Initial load
duke
parents:
diff changeset
365 }
a61af66fc99e Initial load
duke
parents:
diff changeset
366
a61af66fc99e Initial load
duke
parents:
diff changeset
367 address CppInterpreter::return_entry(TosState state, int length) {
a61af66fc99e Initial load
duke
parents:
diff changeset
368 // make it look good in the debugger
a61af66fc99e Initial load
duke
parents:
diff changeset
369 return CAST_FROM_FN_PTR(address, RecursiveInterpreterActivation) + frame::pc_return_offset;
a61af66fc99e Initial load
duke
parents:
diff changeset
370 }
a61af66fc99e Initial load
duke
parents:
diff changeset
371
a61af66fc99e Initial load
duke
parents:
diff changeset
372 address CppInterpreter::deopt_entry(TosState state, int length) {
a61af66fc99e Initial load
duke
parents:
diff changeset
373 address ret = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
374 if (length != 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
375 switch (state) {
a61af66fc99e Initial load
duke
parents:
diff changeset
376 case atos: ret = deopt_frame_manager_return_atos; break;
a61af66fc99e Initial load
duke
parents:
diff changeset
377 case btos: ret = deopt_frame_manager_return_btos; break;
a61af66fc99e Initial load
duke
parents:
diff changeset
378 case ctos:
a61af66fc99e Initial load
duke
parents:
diff changeset
379 case stos:
a61af66fc99e Initial load
duke
parents:
diff changeset
380 case itos: ret = deopt_frame_manager_return_itos; break;
a61af66fc99e Initial load
duke
parents:
diff changeset
381 case ltos: ret = deopt_frame_manager_return_ltos; break;
a61af66fc99e Initial load
duke
parents:
diff changeset
382 case ftos: ret = deopt_frame_manager_return_ftos; break;
a61af66fc99e Initial load
duke
parents:
diff changeset
383 case dtos: ret = deopt_frame_manager_return_dtos; break;
a61af66fc99e Initial load
duke
parents:
diff changeset
384 case vtos: ret = deopt_frame_manager_return_vtos; break;
a61af66fc99e Initial load
duke
parents:
diff changeset
385 }
a61af66fc99e Initial load
duke
parents:
diff changeset
386 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
387 ret = unctrap_frame_manager_entry; // re-execute the bytecode ( e.g. uncommon trap)
a61af66fc99e Initial load
duke
parents:
diff changeset
388 }
a61af66fc99e Initial load
duke
parents:
diff changeset
389 assert(ret != NULL, "Not initialized");
a61af66fc99e Initial load
duke
parents:
diff changeset
390 return ret;
a61af66fc99e Initial load
duke
parents:
diff changeset
391 }
a61af66fc99e Initial load
duke
parents:
diff changeset
392
a61af66fc99e Initial load
duke
parents:
diff changeset
393 //
a61af66fc99e Initial load
duke
parents:
diff changeset
394 // Helpers for commoning out cases in the various type of method entries.
a61af66fc99e Initial load
duke
parents:
diff changeset
395 //
a61af66fc99e Initial load
duke
parents:
diff changeset
396
a61af66fc99e Initial load
duke
parents:
diff changeset
397 // increment invocation count & check for overflow
a61af66fc99e Initial load
duke
parents:
diff changeset
398 //
a61af66fc99e Initial load
duke
parents:
diff changeset
399 // Note: checking for negative value instead of overflow
a61af66fc99e Initial load
duke
parents:
diff changeset
400 // so we have a 'sticky' overflow test
a61af66fc99e Initial load
duke
parents:
diff changeset
401 //
a61af66fc99e Initial load
duke
parents:
diff changeset
402 // Lmethod: method
a61af66fc99e Initial load
duke
parents:
diff changeset
403 // ??: invocation counter
a61af66fc99e Initial load
duke
parents:
diff changeset
404 //
a61af66fc99e Initial load
duke
parents:
diff changeset
405 void InterpreterGenerator::generate_counter_incr(Label* overflow, Label* profile_method, Label* profile_method_continue) {
a61af66fc99e Initial load
duke
parents:
diff changeset
406 // Update standard invocation counters
a61af66fc99e Initial load
duke
parents:
diff changeset
407 __ increment_invocation_counter(O0, G3_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
408 if (ProfileInterpreter) { // %%% Merge this into methodDataOop
a61af66fc99e Initial load
duke
parents:
diff changeset
409 __ ld_ptr(STATE(_method), G3_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
410 Address interpreter_invocation_counter(G3_scratch, 0, in_bytes(methodOopDesc::interpreter_invocation_counter_offset()));
a61af66fc99e Initial load
duke
parents:
diff changeset
411 __ ld(interpreter_invocation_counter, G3_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
412 __ inc(G3_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
413 __ st(G3_scratch, interpreter_invocation_counter);
a61af66fc99e Initial load
duke
parents:
diff changeset
414 }
a61af66fc99e Initial load
duke
parents:
diff changeset
415
a61af66fc99e Initial load
duke
parents:
diff changeset
416 Address invocation_limit(G3_scratch, (address)&InvocationCounter::InterpreterInvocationLimit);
a61af66fc99e Initial load
duke
parents:
diff changeset
417 __ sethi(invocation_limit);
a61af66fc99e Initial load
duke
parents:
diff changeset
418 __ ld(invocation_limit, G3_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
419 __ cmp(O0, G3_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
420 __ br(Assembler::greaterEqualUnsigned, false, Assembler::pn, *overflow);
a61af66fc99e Initial load
duke
parents:
diff changeset
421 __ delayed()->nop();
a61af66fc99e Initial load
duke
parents:
diff changeset
422
a61af66fc99e Initial load
duke
parents:
diff changeset
423 }
a61af66fc99e Initial load
duke
parents:
diff changeset
424
a61af66fc99e Initial load
duke
parents:
diff changeset
425 address InterpreterGenerator::generate_empty_entry(void) {
a61af66fc99e Initial load
duke
parents:
diff changeset
426
a61af66fc99e Initial load
duke
parents:
diff changeset
427 // A method that does nothing but return...
a61af66fc99e Initial load
duke
parents:
diff changeset
428
a61af66fc99e Initial load
duke
parents:
diff changeset
429 address entry = __ pc();
a61af66fc99e Initial load
duke
parents:
diff changeset
430 Label slow_path;
a61af66fc99e Initial load
duke
parents:
diff changeset
431
a61af66fc99e Initial load
duke
parents:
diff changeset
432 __ verify_oop(G5_method);
a61af66fc99e Initial load
duke
parents:
diff changeset
433
a61af66fc99e Initial load
duke
parents:
diff changeset
434 // do nothing for empty methods (do not even increment invocation counter)
a61af66fc99e Initial load
duke
parents:
diff changeset
435 if ( UseFastEmptyMethods) {
a61af66fc99e Initial load
duke
parents:
diff changeset
436 // If we need a safepoint check, generate full interpreter entry.
a61af66fc99e Initial load
duke
parents:
diff changeset
437 Address sync_state(G3_scratch, SafepointSynchronize::address_of_state());
a61af66fc99e Initial load
duke
parents:
diff changeset
438 __ load_contents(sync_state, G3_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
439 __ cmp(G3_scratch, SafepointSynchronize::_not_synchronized);
a61af66fc99e Initial load
duke
parents:
diff changeset
440 __ br(Assembler::notEqual, false, Assembler::pn, frame_manager_entry);
a61af66fc99e Initial load
duke
parents:
diff changeset
441 __ delayed()->nop();
a61af66fc99e Initial load
duke
parents:
diff changeset
442
a61af66fc99e Initial load
duke
parents:
diff changeset
443 // Code: _return
a61af66fc99e Initial load
duke
parents:
diff changeset
444 __ retl();
a61af66fc99e Initial load
duke
parents:
diff changeset
445 __ delayed()->mov(O5_savedSP, SP);
a61af66fc99e Initial load
duke
parents:
diff changeset
446 return entry;
a61af66fc99e Initial load
duke
parents:
diff changeset
447 }
a61af66fc99e Initial load
duke
parents:
diff changeset
448 return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
449 }
a61af66fc99e Initial load
duke
parents:
diff changeset
450
a61af66fc99e Initial load
duke
parents:
diff changeset
451 // Call an accessor method (assuming it is resolved, otherwise drop into
a61af66fc99e Initial load
duke
parents:
diff changeset
452 // vanilla (slow path) entry
a61af66fc99e Initial load
duke
parents:
diff changeset
453
a61af66fc99e Initial load
duke
parents:
diff changeset
454 // Generates code to elide accessor methods
a61af66fc99e Initial load
duke
parents:
diff changeset
455 // Uses G3_scratch and G1_scratch as scratch
a61af66fc99e Initial load
duke
parents:
diff changeset
456 address InterpreterGenerator::generate_accessor_entry(void) {
a61af66fc99e Initial load
duke
parents:
diff changeset
457
a61af66fc99e Initial load
duke
parents:
diff changeset
458 // Code: _aload_0, _(i|a)getfield, _(i|a)return or any rewrites thereof;
a61af66fc99e Initial load
duke
parents:
diff changeset
459 // parameter size = 1
a61af66fc99e Initial load
duke
parents:
diff changeset
460 // Note: We can only use this code if the getfield has been resolved
a61af66fc99e Initial load
duke
parents:
diff changeset
461 // and if we don't have a null-pointer exception => check for
a61af66fc99e Initial load
duke
parents:
diff changeset
462 // these conditions first and use slow path if necessary.
a61af66fc99e Initial load
duke
parents:
diff changeset
463 address entry = __ pc();
a61af66fc99e Initial load
duke
parents:
diff changeset
464 Label slow_path;
a61af66fc99e Initial load
duke
parents:
diff changeset
465
a61af66fc99e Initial load
duke
parents:
diff changeset
466 if ( UseFastAccessorMethods) {
a61af66fc99e Initial load
duke
parents:
diff changeset
467 // Check if we need to reach a safepoint and generate full interpreter
a61af66fc99e Initial load
duke
parents:
diff changeset
468 // frame if so.
a61af66fc99e Initial load
duke
parents:
diff changeset
469 Address sync_state(G3_scratch, SafepointSynchronize::address_of_state());
a61af66fc99e Initial load
duke
parents:
diff changeset
470 __ load_contents(sync_state, G3_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
471 __ cmp(G3_scratch, SafepointSynchronize::_not_synchronized);
a61af66fc99e Initial load
duke
parents:
diff changeset
472 __ br(Assembler::notEqual, false, Assembler::pn, slow_path);
a61af66fc99e Initial load
duke
parents:
diff changeset
473 __ delayed()->nop();
a61af66fc99e Initial load
duke
parents:
diff changeset
474
a61af66fc99e Initial load
duke
parents:
diff changeset
475 // Check if local 0 != NULL
a61af66fc99e Initial load
duke
parents:
diff changeset
476 __ ld_ptr(Gargs, G0, Otos_i ); // get local 0
a61af66fc99e Initial load
duke
parents:
diff changeset
477 __ tst(Otos_i); // check if local 0 == NULL and go the slow path
a61af66fc99e Initial load
duke
parents:
diff changeset
478 __ brx(Assembler::zero, false, Assembler::pn, slow_path);
a61af66fc99e Initial load
duke
parents:
diff changeset
479 __ delayed()->nop();
a61af66fc99e Initial load
duke
parents:
diff changeset
480
a61af66fc99e Initial load
duke
parents:
diff changeset
481
a61af66fc99e Initial load
duke
parents:
diff changeset
482 // read first instruction word and extract bytecode @ 1 and index @ 2
a61af66fc99e Initial load
duke
parents:
diff changeset
483 // get first 4 bytes of the bytecodes (big endian!)
a61af66fc99e Initial load
duke
parents:
diff changeset
484 __ ld_ptr(Address(G5_method, 0, in_bytes(methodOopDesc::const_offset())), G1_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
485 __ ld(Address(G1_scratch, 0, in_bytes(constMethodOopDesc::codes_offset())), G1_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
486
a61af66fc99e Initial load
duke
parents:
diff changeset
487 // move index @ 2 far left then to the right most two bytes.
a61af66fc99e Initial load
duke
parents:
diff changeset
488 __ sll(G1_scratch, 2*BitsPerByte, G1_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
489 __ srl(G1_scratch, 2*BitsPerByte - exact_log2(in_words(
a61af66fc99e Initial load
duke
parents:
diff changeset
490 ConstantPoolCacheEntry::size()) * BytesPerWord), G1_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
491
a61af66fc99e Initial load
duke
parents:
diff changeset
492 // get constant pool cache
a61af66fc99e Initial load
duke
parents:
diff changeset
493 __ ld_ptr(G5_method, in_bytes(methodOopDesc::constants_offset()), G3_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
494 __ ld_ptr(G3_scratch, constantPoolOopDesc::cache_offset_in_bytes(), G3_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
495
a61af66fc99e Initial load
duke
parents:
diff changeset
496 // get specific constant pool cache entry
a61af66fc99e Initial load
duke
parents:
diff changeset
497 __ add(G3_scratch, G1_scratch, G3_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
498
a61af66fc99e Initial load
duke
parents:
diff changeset
499 // Check the constant Pool cache entry to see if it has been resolved.
a61af66fc99e Initial load
duke
parents:
diff changeset
500 // If not, need the slow path.
a61af66fc99e Initial load
duke
parents:
diff changeset
501 ByteSize cp_base_offset = constantPoolCacheOopDesc::base_offset();
a61af66fc99e Initial load
duke
parents:
diff changeset
502 __ ld_ptr(G3_scratch, in_bytes(cp_base_offset + ConstantPoolCacheEntry::indices_offset()), G1_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
503 __ srl(G1_scratch, 2*BitsPerByte, G1_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
504 __ and3(G1_scratch, 0xFF, G1_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
505 __ cmp(G1_scratch, Bytecodes::_getfield);
a61af66fc99e Initial load
duke
parents:
diff changeset
506 __ br(Assembler::notEqual, false, Assembler::pn, slow_path);
a61af66fc99e Initial load
duke
parents:
diff changeset
507 __ delayed()->nop();
a61af66fc99e Initial load
duke
parents:
diff changeset
508
a61af66fc99e Initial load
duke
parents:
diff changeset
509 // Get the type and return field offset from the constant pool cache
a61af66fc99e Initial load
duke
parents:
diff changeset
510 __ ld_ptr(G3_scratch, in_bytes(cp_base_offset + ConstantPoolCacheEntry::flags_offset()), G1_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
511 __ ld_ptr(G3_scratch, in_bytes(cp_base_offset + ConstantPoolCacheEntry::f2_offset()), G3_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
512
a61af66fc99e Initial load
duke
parents:
diff changeset
513 Label xreturn_path;
a61af66fc99e Initial load
duke
parents:
diff changeset
514 // Need to differentiate between igetfield, agetfield, bgetfield etc.
a61af66fc99e Initial load
duke
parents:
diff changeset
515 // because they are different sizes.
a61af66fc99e Initial load
duke
parents:
diff changeset
516 // Get the type from the constant pool cache
a61af66fc99e Initial load
duke
parents:
diff changeset
517 __ srl(G1_scratch, ConstantPoolCacheEntry::tosBits, G1_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
518 // Make sure we don't need to mask G1_scratch for tosBits after the above shift
a61af66fc99e Initial load
duke
parents:
diff changeset
519 ConstantPoolCacheEntry::verify_tosBits();
a61af66fc99e Initial load
duke
parents:
diff changeset
520 __ cmp(G1_scratch, atos );
a61af66fc99e Initial load
duke
parents:
diff changeset
521 __ br(Assembler::equal, true, Assembler::pt, xreturn_path);
a61af66fc99e Initial load
duke
parents:
diff changeset
522 __ delayed()->ld_ptr(Otos_i, G3_scratch, Otos_i);
a61af66fc99e Initial load
duke
parents:
diff changeset
523 __ cmp(G1_scratch, itos);
a61af66fc99e Initial load
duke
parents:
diff changeset
524 __ br(Assembler::equal, true, Assembler::pt, xreturn_path);
a61af66fc99e Initial load
duke
parents:
diff changeset
525 __ delayed()->ld(Otos_i, G3_scratch, Otos_i);
a61af66fc99e Initial load
duke
parents:
diff changeset
526 __ cmp(G1_scratch, stos);
a61af66fc99e Initial load
duke
parents:
diff changeset
527 __ br(Assembler::equal, true, Assembler::pt, xreturn_path);
a61af66fc99e Initial load
duke
parents:
diff changeset
528 __ delayed()->ldsh(Otos_i, G3_scratch, Otos_i);
a61af66fc99e Initial load
duke
parents:
diff changeset
529 __ cmp(G1_scratch, ctos);
a61af66fc99e Initial load
duke
parents:
diff changeset
530 __ br(Assembler::equal, true, Assembler::pt, xreturn_path);
a61af66fc99e Initial load
duke
parents:
diff changeset
531 __ delayed()->lduh(Otos_i, G3_scratch, Otos_i);
a61af66fc99e Initial load
duke
parents:
diff changeset
532 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
533 __ cmp(G1_scratch, btos);
a61af66fc99e Initial load
duke
parents:
diff changeset
534 __ br(Assembler::equal, true, Assembler::pt, xreturn_path);
a61af66fc99e Initial load
duke
parents:
diff changeset
535 __ delayed()->ldsb(Otos_i, G3_scratch, Otos_i);
a61af66fc99e Initial load
duke
parents:
diff changeset
536 __ should_not_reach_here();
a61af66fc99e Initial load
duke
parents:
diff changeset
537 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
538 __ ldsb(Otos_i, G3_scratch, Otos_i);
a61af66fc99e Initial load
duke
parents:
diff changeset
539 __ bind(xreturn_path);
a61af66fc99e Initial load
duke
parents:
diff changeset
540
a61af66fc99e Initial load
duke
parents:
diff changeset
541 // _ireturn/_areturn
a61af66fc99e Initial load
duke
parents:
diff changeset
542 __ retl(); // return from leaf routine
a61af66fc99e Initial load
duke
parents:
diff changeset
543 __ delayed()->mov(O5_savedSP, SP);
a61af66fc99e Initial load
duke
parents:
diff changeset
544
a61af66fc99e Initial load
duke
parents:
diff changeset
545 // Generate regular method entry
a61af66fc99e Initial load
duke
parents:
diff changeset
546 __ bind(slow_path);
a61af66fc99e Initial load
duke
parents:
diff changeset
547 __ ba(false, fast_accessor_slow_entry_path);
a61af66fc99e Initial load
duke
parents:
diff changeset
548 __ delayed()->nop();
a61af66fc99e Initial load
duke
parents:
diff changeset
549 return entry;
a61af66fc99e Initial load
duke
parents:
diff changeset
550 }
a61af66fc99e Initial load
duke
parents:
diff changeset
551 return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
552 }
a61af66fc99e Initial load
duke
parents:
diff changeset
553
3249
e1162778c1c8 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 2357
diff changeset
554 address InterpreterGenerator::generate_Reference_get_entry(void) {
e1162778c1c8 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 2357
diff changeset
555 #ifndef SERIALGC
e1162778c1c8 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 2357
diff changeset
556 if (UseG1GC) {
e1162778c1c8 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 2357
diff changeset
557 // We need to generate have a routine that generates code to:
e1162778c1c8 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 2357
diff changeset
558 // * load the value in the referent field
e1162778c1c8 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 2357
diff changeset
559 // * passes that value to the pre-barrier.
e1162778c1c8 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 2357
diff changeset
560 //
e1162778c1c8 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 2357
diff changeset
561 // In the case of G1 this will record the value of the
e1162778c1c8 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 2357
diff changeset
562 // referent in an SATB buffer if marking is active.
e1162778c1c8 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 2357
diff changeset
563 // This will cause concurrent marking to mark the referent
e1162778c1c8 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 2357
diff changeset
564 // field as live.
e1162778c1c8 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 2357
diff changeset
565 Unimplemented();
e1162778c1c8 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 2357
diff changeset
566 }
e1162778c1c8 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 2357
diff changeset
567 #endif // SERIALGC
e1162778c1c8 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 2357
diff changeset
568
e1162778c1c8 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 2357
diff changeset
569 // If G1 is not enabled then attempt to go through the accessor entry point
e1162778c1c8 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 2357
diff changeset
570 // Reference.get is an accessor
e1162778c1c8 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 2357
diff changeset
571 return generate_accessor_entry();
e1162778c1c8 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 2357
diff changeset
572 }
e1162778c1c8 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 2357
diff changeset
573
0
a61af66fc99e Initial load
duke
parents:
diff changeset
574 //
a61af66fc99e Initial load
duke
parents:
diff changeset
575 // Interpreter stub for calling a native method. (C++ interpreter)
a61af66fc99e Initial load
duke
parents:
diff changeset
576 // This sets up a somewhat different looking stack for calling the native method
a61af66fc99e Initial load
duke
parents:
diff changeset
577 // than the typical interpreter frame setup.
a61af66fc99e Initial load
duke
parents:
diff changeset
578 //
a61af66fc99e Initial load
duke
parents:
diff changeset
579
a61af66fc99e Initial load
duke
parents:
diff changeset
580 address InterpreterGenerator::generate_native_entry(bool synchronized) {
a61af66fc99e Initial load
duke
parents:
diff changeset
581 address entry = __ pc();
a61af66fc99e Initial load
duke
parents:
diff changeset
582
a61af66fc99e Initial load
duke
parents:
diff changeset
583 // the following temporary registers are used during frame creation
a61af66fc99e Initial load
duke
parents:
diff changeset
584 const Register Gtmp1 = G3_scratch ;
a61af66fc99e Initial load
duke
parents:
diff changeset
585 const Register Gtmp2 = G1_scratch;
a61af66fc99e Initial load
duke
parents:
diff changeset
586 const Address size_of_parameters(G5_method, 0, in_bytes(methodOopDesc::size_of_parameters_offset()));
a61af66fc99e Initial load
duke
parents:
diff changeset
587
a61af66fc99e Initial load
duke
parents:
diff changeset
588 bool inc_counter = UseCompiler || CountCompiledCalls;
a61af66fc99e Initial load
duke
parents:
diff changeset
589
a61af66fc99e Initial load
duke
parents:
diff changeset
590 // make sure registers are different!
a61af66fc99e Initial load
duke
parents:
diff changeset
591 assert_different_registers(G2_thread, G5_method, Gargs, Gtmp1, Gtmp2);
a61af66fc99e Initial load
duke
parents:
diff changeset
592
a61af66fc99e Initial load
duke
parents:
diff changeset
593 const Address access_flags (G5_method, 0, in_bytes(methodOopDesc::access_flags_offset()));
a61af66fc99e Initial load
duke
parents:
diff changeset
594
a61af66fc99e Initial load
duke
parents:
diff changeset
595 Label Lentry;
a61af66fc99e Initial load
duke
parents:
diff changeset
596 __ bind(Lentry);
a61af66fc99e Initial load
duke
parents:
diff changeset
597
a61af66fc99e Initial load
duke
parents:
diff changeset
598 __ verify_oop(G5_method);
a61af66fc99e Initial load
duke
parents:
diff changeset
599
a61af66fc99e Initial load
duke
parents:
diff changeset
600 const Register Glocals_size = G3;
a61af66fc99e Initial load
duke
parents:
diff changeset
601 assert_different_registers(Glocals_size, G4_scratch, Gframe_size);
a61af66fc99e Initial load
duke
parents:
diff changeset
602
a61af66fc99e Initial load
duke
parents:
diff changeset
603 // make sure method is native & not abstract
a61af66fc99e Initial load
duke
parents:
diff changeset
604 // rethink these assertions - they can be simplified and shared (gri 2/25/2000)
a61af66fc99e Initial load
duke
parents:
diff changeset
605 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
606 __ ld(access_flags, Gtmp1);
a61af66fc99e Initial load
duke
parents:
diff changeset
607 {
a61af66fc99e Initial load
duke
parents:
diff changeset
608 Label L;
a61af66fc99e Initial load
duke
parents:
diff changeset
609 __ btst(JVM_ACC_NATIVE, Gtmp1);
a61af66fc99e Initial load
duke
parents:
diff changeset
610 __ br(Assembler::notZero, false, Assembler::pt, L);
a61af66fc99e Initial load
duke
parents:
diff changeset
611 __ delayed()->nop();
a61af66fc99e Initial load
duke
parents:
diff changeset
612 __ stop("tried to execute non-native method as native");
a61af66fc99e Initial load
duke
parents:
diff changeset
613 __ bind(L);
a61af66fc99e Initial load
duke
parents:
diff changeset
614 }
a61af66fc99e Initial load
duke
parents:
diff changeset
615 { Label L;
a61af66fc99e Initial load
duke
parents:
diff changeset
616 __ btst(JVM_ACC_ABSTRACT, Gtmp1);
a61af66fc99e Initial load
duke
parents:
diff changeset
617 __ br(Assembler::zero, false, Assembler::pt, L);
a61af66fc99e Initial load
duke
parents:
diff changeset
618 __ delayed()->nop();
a61af66fc99e Initial load
duke
parents:
diff changeset
619 __ stop("tried to execute abstract method as non-abstract");
a61af66fc99e Initial load
duke
parents:
diff changeset
620 __ bind(L);
a61af66fc99e Initial load
duke
parents:
diff changeset
621 }
a61af66fc99e Initial load
duke
parents:
diff changeset
622 #endif // ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
623
a61af66fc99e Initial load
duke
parents:
diff changeset
624 __ lduh(size_of_parameters, Gtmp1);
a61af66fc99e Initial load
duke
parents:
diff changeset
625 __ sll(Gtmp1, LogBytesPerWord, Gtmp2); // parameter size in bytes
a61af66fc99e Initial load
duke
parents:
diff changeset
626 __ add(Gargs, Gtmp2, Gargs); // points to first local + BytesPerWord
a61af66fc99e Initial load
duke
parents:
diff changeset
627 // NEW
a61af66fc99e Initial load
duke
parents:
diff changeset
628 __ add(Gargs, -wordSize, Gargs); // points to first local[0]
a61af66fc99e Initial load
duke
parents:
diff changeset
629 // generate the code to allocate the interpreter stack frame
a61af66fc99e Initial load
duke
parents:
diff changeset
630 // NEW FRAME ALLOCATED HERE
a61af66fc99e Initial load
duke
parents:
diff changeset
631 // save callers original sp
a61af66fc99e Initial load
duke
parents:
diff changeset
632 // __ mov(SP, I5_savedSP->after_restore());
a61af66fc99e Initial load
duke
parents:
diff changeset
633
a61af66fc99e Initial load
duke
parents:
diff changeset
634 generate_compute_interpreter_state(Lstate, G0, true);
a61af66fc99e Initial load
duke
parents:
diff changeset
635
a61af66fc99e Initial load
duke
parents:
diff changeset
636 // At this point Lstate points to new interpreter state
a61af66fc99e Initial load
duke
parents:
diff changeset
637 //
a61af66fc99e Initial load
duke
parents:
diff changeset
638
a61af66fc99e Initial load
duke
parents:
diff changeset
639 const Address do_not_unlock_if_synchronized(G2_thread, 0,
a61af66fc99e Initial load
duke
parents:
diff changeset
640 in_bytes(JavaThread::do_not_unlock_if_synchronized_offset()));
a61af66fc99e Initial load
duke
parents:
diff changeset
641 // Since at this point in the method invocation the exception handler
a61af66fc99e Initial load
duke
parents:
diff changeset
642 // would try to exit the monitor of synchronized methods which hasn't
a61af66fc99e Initial load
duke
parents:
diff changeset
643 // been entered yet, we set the thread local variable
a61af66fc99e Initial load
duke
parents:
diff changeset
644 // _do_not_unlock_if_synchronized to true. If any exception was thrown by
a61af66fc99e Initial load
duke
parents:
diff changeset
645 // runtime, exception handling i.e. unlock_if_synchronized_method will
a61af66fc99e Initial load
duke
parents:
diff changeset
646 // check this thread local flag.
a61af66fc99e Initial load
duke
parents:
diff changeset
647 // This flag has two effects, one is to force an unwind in the topmost
a61af66fc99e Initial load
duke
parents:
diff changeset
648 // interpreter frame and not perform an unlock while doing so.
a61af66fc99e Initial load
duke
parents:
diff changeset
649
a61af66fc99e Initial load
duke
parents:
diff changeset
650 __ movbool(true, G3_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
651 __ stbool(G3_scratch, do_not_unlock_if_synchronized);
a61af66fc99e Initial load
duke
parents:
diff changeset
652
a61af66fc99e Initial load
duke
parents:
diff changeset
653
a61af66fc99e Initial load
duke
parents:
diff changeset
654 // increment invocation counter and check for overflow
a61af66fc99e Initial load
duke
parents:
diff changeset
655 //
a61af66fc99e Initial load
duke
parents:
diff changeset
656 // Note: checking for negative value instead of overflow
a61af66fc99e Initial load
duke
parents:
diff changeset
657 // so we have a 'sticky' overflow test (may be of
a61af66fc99e Initial load
duke
parents:
diff changeset
658 // importance as soon as we have true MT/MP)
a61af66fc99e Initial load
duke
parents:
diff changeset
659 Label invocation_counter_overflow;
a61af66fc99e Initial load
duke
parents:
diff changeset
660 if (inc_counter) {
a61af66fc99e Initial load
duke
parents:
diff changeset
661 generate_counter_incr(&invocation_counter_overflow, NULL, NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
662 }
a61af66fc99e Initial load
duke
parents:
diff changeset
663 Label Lcontinue;
a61af66fc99e Initial load
duke
parents:
diff changeset
664 __ bind(Lcontinue);
a61af66fc99e Initial load
duke
parents:
diff changeset
665
a61af66fc99e Initial load
duke
parents:
diff changeset
666 bang_stack_shadow_pages(true);
a61af66fc99e Initial load
duke
parents:
diff changeset
667 // reset the _do_not_unlock_if_synchronized flag
a61af66fc99e Initial load
duke
parents:
diff changeset
668 __ stbool(G0, do_not_unlock_if_synchronized);
a61af66fc99e Initial load
duke
parents:
diff changeset
669
a61af66fc99e Initial load
duke
parents:
diff changeset
670 // check for synchronized methods
a61af66fc99e Initial load
duke
parents:
diff changeset
671 // Must happen AFTER invocation_counter check, so method is not locked
a61af66fc99e Initial load
duke
parents:
diff changeset
672 // if counter overflows.
a61af66fc99e Initial load
duke
parents:
diff changeset
673
a61af66fc99e Initial load
duke
parents:
diff changeset
674 if (synchronized) {
a61af66fc99e Initial load
duke
parents:
diff changeset
675 lock_method();
a61af66fc99e Initial load
duke
parents:
diff changeset
676 // Don't see how G2_thread is preserved here...
a61af66fc99e Initial load
duke
parents:
diff changeset
677 // __ verify_thread(); QQQ destroys L0,L1 can't use
a61af66fc99e Initial load
duke
parents:
diff changeset
678 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
679 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
680 { Label ok;
a61af66fc99e Initial load
duke
parents:
diff changeset
681 __ ld_ptr(STATE(_method), G5_method);
a61af66fc99e Initial load
duke
parents:
diff changeset
682 __ ld(access_flags, O0);
a61af66fc99e Initial load
duke
parents:
diff changeset
683 __ btst(JVM_ACC_SYNCHRONIZED, O0);
a61af66fc99e Initial load
duke
parents:
diff changeset
684 __ br( Assembler::zero, false, Assembler::pt, ok);
a61af66fc99e Initial load
duke
parents:
diff changeset
685 __ delayed()->nop();
a61af66fc99e Initial load
duke
parents:
diff changeset
686 __ stop("method needs synchronization");
a61af66fc99e Initial load
duke
parents:
diff changeset
687 __ bind(ok);
a61af66fc99e Initial load
duke
parents:
diff changeset
688 }
a61af66fc99e Initial load
duke
parents:
diff changeset
689 #endif // ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
690 }
a61af66fc99e Initial load
duke
parents:
diff changeset
691
a61af66fc99e Initial load
duke
parents:
diff changeset
692 // start execution
a61af66fc99e Initial load
duke
parents:
diff changeset
693
a61af66fc99e Initial load
duke
parents:
diff changeset
694 // __ verify_thread(); kills L1,L2 can't use at the moment
a61af66fc99e Initial load
duke
parents:
diff changeset
695
a61af66fc99e Initial load
duke
parents:
diff changeset
696 // jvmti/jvmpi support
a61af66fc99e Initial load
duke
parents:
diff changeset
697 __ notify_method_entry();
a61af66fc99e Initial load
duke
parents:
diff changeset
698
a61af66fc99e Initial load
duke
parents:
diff changeset
699 // native call
a61af66fc99e Initial load
duke
parents:
diff changeset
700
a61af66fc99e Initial load
duke
parents:
diff changeset
701 // (note that O0 is never an oop--at most it is a handle)
a61af66fc99e Initial load
duke
parents:
diff changeset
702 // It is important not to smash any handles created by this call,
a61af66fc99e Initial load
duke
parents:
diff changeset
703 // until any oop handle in O0 is dereferenced.
a61af66fc99e Initial load
duke
parents:
diff changeset
704
a61af66fc99e Initial load
duke
parents:
diff changeset
705 // (note that the space for outgoing params is preallocated)
a61af66fc99e Initial load
duke
parents:
diff changeset
706
a61af66fc99e Initial load
duke
parents:
diff changeset
707 // get signature handler
a61af66fc99e Initial load
duke
parents:
diff changeset
708
a61af66fc99e Initial load
duke
parents:
diff changeset
709 Label pending_exception_present;
a61af66fc99e Initial load
duke
parents:
diff changeset
710
a61af66fc99e Initial load
duke
parents:
diff changeset
711 { Label L;
a61af66fc99e Initial load
duke
parents:
diff changeset
712 __ ld_ptr(STATE(_method), G5_method);
a61af66fc99e Initial load
duke
parents:
diff changeset
713 __ ld_ptr(Address(G5_method, 0, in_bytes(methodOopDesc::signature_handler_offset())), G3_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
714 __ tst(G3_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
715 __ brx(Assembler::notZero, false, Assembler::pt, L);
a61af66fc99e Initial load
duke
parents:
diff changeset
716 __ delayed()->nop();
a61af66fc99e Initial load
duke
parents:
diff changeset
717 __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::prepare_native_call), G5_method, false);
a61af66fc99e Initial load
duke
parents:
diff changeset
718 __ ld_ptr(STATE(_method), G5_method);
a61af66fc99e Initial load
duke
parents:
diff changeset
719
a61af66fc99e Initial load
duke
parents:
diff changeset
720 Address exception_addr(G2_thread, 0, in_bytes(Thread::pending_exception_offset()));
a61af66fc99e Initial load
duke
parents:
diff changeset
721 __ ld_ptr(exception_addr, G3_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
722 __ br_notnull(G3_scratch, false, Assembler::pn, pending_exception_present);
a61af66fc99e Initial load
duke
parents:
diff changeset
723 __ delayed()->nop();
a61af66fc99e Initial load
duke
parents:
diff changeset
724 __ ld_ptr(Address(G5_method, 0, in_bytes(methodOopDesc::signature_handler_offset())), G3_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
725 __ bind(L);
a61af66fc99e Initial load
duke
parents:
diff changeset
726 }
a61af66fc99e Initial load
duke
parents:
diff changeset
727
a61af66fc99e Initial load
duke
parents:
diff changeset
728 // Push a new frame so that the args will really be stored in
a61af66fc99e Initial load
duke
parents:
diff changeset
729 // Copy a few locals across so the new frame has the variables
a61af66fc99e Initial load
duke
parents:
diff changeset
730 // we need but these values will be dead at the jni call and
a61af66fc99e Initial load
duke
parents:
diff changeset
731 // therefore not gc volatile like the values in the current
a61af66fc99e Initial load
duke
parents:
diff changeset
732 // frame (Lstate in particular)
a61af66fc99e Initial load
duke
parents:
diff changeset
733
a61af66fc99e Initial load
duke
parents:
diff changeset
734 // Flush the state pointer to the register save area
a61af66fc99e Initial load
duke
parents:
diff changeset
735 // Which is the only register we need for a stack walk.
a61af66fc99e Initial load
duke
parents:
diff changeset
736 __ st_ptr(Lstate, SP, (Lstate->sp_offset_in_saved_window() * wordSize) + STACK_BIAS);
a61af66fc99e Initial load
duke
parents:
diff changeset
737
a61af66fc99e Initial load
duke
parents:
diff changeset
738 __ mov(Lstate, O1); // Need to pass the state pointer across the frame
a61af66fc99e Initial load
duke
parents:
diff changeset
739
a61af66fc99e Initial load
duke
parents:
diff changeset
740 // Calculate current frame size
a61af66fc99e Initial load
duke
parents:
diff changeset
741 __ sub(SP, FP, O3); // Calculate negative of current frame size
a61af66fc99e Initial load
duke
parents:
diff changeset
742 __ save(SP, O3, SP); // Allocate an identical sized frame
a61af66fc99e Initial load
duke
parents:
diff changeset
743
a61af66fc99e Initial load
duke
parents:
diff changeset
744 __ mov(I1, Lstate); // In the "natural" register.
a61af66fc99e Initial load
duke
parents:
diff changeset
745
a61af66fc99e Initial load
duke
parents:
diff changeset
746 // Note I7 has leftover trash. Slow signature handler will fill it in
a61af66fc99e Initial load
duke
parents:
diff changeset
747 // should we get there. Normal jni call will set reasonable last_Java_pc
a61af66fc99e Initial load
duke
parents:
diff changeset
748 // below (and fix I7 so the stack trace doesn't have a meaningless frame
a61af66fc99e Initial load
duke
parents:
diff changeset
749 // in it).
a61af66fc99e Initial load
duke
parents:
diff changeset
750
a61af66fc99e Initial load
duke
parents:
diff changeset
751
a61af66fc99e Initial load
duke
parents:
diff changeset
752 // call signature handler
a61af66fc99e Initial load
duke
parents:
diff changeset
753 __ ld_ptr(STATE(_method), Lmethod);
a61af66fc99e Initial load
duke
parents:
diff changeset
754 __ ld_ptr(STATE(_locals), Llocals);
a61af66fc99e Initial load
duke
parents:
diff changeset
755
a61af66fc99e Initial load
duke
parents:
diff changeset
756 __ callr(G3_scratch, 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
757 __ delayed()->nop();
a61af66fc99e Initial load
duke
parents:
diff changeset
758 __ ld_ptr(STATE(_thread), G2_thread); // restore thread (shouldn't be needed)
a61af66fc99e Initial load
duke
parents:
diff changeset
759
a61af66fc99e Initial load
duke
parents:
diff changeset
760 { Label not_static;
a61af66fc99e Initial load
duke
parents:
diff changeset
761
a61af66fc99e Initial load
duke
parents:
diff changeset
762 __ ld_ptr(STATE(_method), G5_method);
a61af66fc99e Initial load
duke
parents:
diff changeset
763 __ ld(access_flags, O0);
a61af66fc99e Initial load
duke
parents:
diff changeset
764 __ btst(JVM_ACC_STATIC, O0);
a61af66fc99e Initial load
duke
parents:
diff changeset
765 __ br( Assembler::zero, false, Assembler::pt, not_static);
a61af66fc99e Initial load
duke
parents:
diff changeset
766 __ delayed()->
a61af66fc99e Initial load
duke
parents:
diff changeset
767 // get native function entry point(O0 is a good temp until the very end)
a61af66fc99e Initial load
duke
parents:
diff changeset
768 ld_ptr(Address(G5_method, 0, in_bytes(methodOopDesc::native_function_offset())), O0);
a61af66fc99e Initial load
duke
parents:
diff changeset
769 // for static methods insert the mirror argument
a61af66fc99e Initial load
duke
parents:
diff changeset
770 const int mirror_offset = klassOopDesc::klass_part_offset_in_bytes() + Klass::java_mirror_offset_in_bytes();
a61af66fc99e Initial load
duke
parents:
diff changeset
771
a61af66fc99e Initial load
duke
parents:
diff changeset
772 __ ld_ptr(Address(G5_method, 0, in_bytes(methodOopDesc:: constants_offset())), O1);
a61af66fc99e Initial load
duke
parents:
diff changeset
773 __ ld_ptr(Address(O1, 0, constantPoolOopDesc::pool_holder_offset_in_bytes()), O1);
a61af66fc99e Initial load
duke
parents:
diff changeset
774 __ ld_ptr(O1, mirror_offset, O1);
a61af66fc99e Initial load
duke
parents:
diff changeset
775 // where the mirror handle body is allocated:
a61af66fc99e Initial load
duke
parents:
diff changeset
776 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
777 if (!PrintSignatureHandlers) // do not dirty the output with this
a61af66fc99e Initial load
duke
parents:
diff changeset
778 { Label L;
a61af66fc99e Initial load
duke
parents:
diff changeset
779 __ tst(O1);
a61af66fc99e Initial load
duke
parents:
diff changeset
780 __ brx(Assembler::notZero, false, Assembler::pt, L);
a61af66fc99e Initial load
duke
parents:
diff changeset
781 __ delayed()->nop();
a61af66fc99e Initial load
duke
parents:
diff changeset
782 __ stop("mirror is missing");
a61af66fc99e Initial load
duke
parents:
diff changeset
783 __ bind(L);
a61af66fc99e Initial load
duke
parents:
diff changeset
784 }
a61af66fc99e Initial load
duke
parents:
diff changeset
785 #endif // ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
786 __ st_ptr(O1, STATE(_oop_temp));
a61af66fc99e Initial load
duke
parents:
diff changeset
787 __ add(STATE(_oop_temp), O1); // this is really an LEA not an add
a61af66fc99e Initial load
duke
parents:
diff changeset
788 __ bind(not_static);
a61af66fc99e Initial load
duke
parents:
diff changeset
789 }
a61af66fc99e Initial load
duke
parents:
diff changeset
790
a61af66fc99e Initial load
duke
parents:
diff changeset
791 // At this point, arguments have been copied off of stack into
a61af66fc99e Initial load
duke
parents:
diff changeset
792 // their JNI positions, which are O1..O5 and SP[68..].
a61af66fc99e Initial load
duke
parents:
diff changeset
793 // Oops are boxed in-place on the stack, with handles copied to arguments.
a61af66fc99e Initial load
duke
parents:
diff changeset
794 // The result handler is in Lscratch. O0 will shortly hold the JNIEnv*.
a61af66fc99e Initial load
duke
parents:
diff changeset
795
a61af66fc99e Initial load
duke
parents:
diff changeset
796 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
797 { Label L;
a61af66fc99e Initial load
duke
parents:
diff changeset
798 __ tst(O0);
a61af66fc99e Initial load
duke
parents:
diff changeset
799 __ brx(Assembler::notZero, false, Assembler::pt, L);
a61af66fc99e Initial load
duke
parents:
diff changeset
800 __ delayed()->nop();
a61af66fc99e Initial load
duke
parents:
diff changeset
801 __ stop("native entry point is missing");
a61af66fc99e Initial load
duke
parents:
diff changeset
802 __ bind(L);
a61af66fc99e Initial load
duke
parents:
diff changeset
803 }
a61af66fc99e Initial load
duke
parents:
diff changeset
804 #endif // ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
805
a61af66fc99e Initial load
duke
parents:
diff changeset
806 //
a61af66fc99e Initial load
duke
parents:
diff changeset
807 // setup the java frame anchor
a61af66fc99e Initial load
duke
parents:
diff changeset
808 //
a61af66fc99e Initial load
duke
parents:
diff changeset
809 // The scavenge function only needs to know that the PC of this frame is
a61af66fc99e Initial load
duke
parents:
diff changeset
810 // in the interpreter method entry code, it doesn't need to know the exact
a61af66fc99e Initial load
duke
parents:
diff changeset
811 // PC and hence we can use O7 which points to the return address from the
a61af66fc99e Initial load
duke
parents:
diff changeset
812 // previous call in the code stream (signature handler function)
a61af66fc99e Initial load
duke
parents:
diff changeset
813 //
a61af66fc99e Initial load
duke
parents:
diff changeset
814 // The other trick is we set last_Java_sp to FP instead of the usual SP because
a61af66fc99e Initial load
duke
parents:
diff changeset
815 // we have pushed the extra frame in order to protect the volatile register(s)
a61af66fc99e Initial load
duke
parents:
diff changeset
816 // in that frame when we return from the jni call
a61af66fc99e Initial load
duke
parents:
diff changeset
817 //
a61af66fc99e Initial load
duke
parents:
diff changeset
818
a61af66fc99e Initial load
duke
parents:
diff changeset
819
a61af66fc99e Initial load
duke
parents:
diff changeset
820 __ set_last_Java_frame(FP, O7);
a61af66fc99e Initial load
duke
parents:
diff changeset
821 __ mov(O7, I7); // make dummy interpreter frame look like one above,
a61af66fc99e Initial load
duke
parents:
diff changeset
822 // not meaningless information that'll confuse me.
a61af66fc99e Initial load
duke
parents:
diff changeset
823
a61af66fc99e Initial load
duke
parents:
diff changeset
824 // flush the windows now. We don't care about the current (protection) frame
a61af66fc99e Initial load
duke
parents:
diff changeset
825 // only the outer frames
a61af66fc99e Initial load
duke
parents:
diff changeset
826
a61af66fc99e Initial load
duke
parents:
diff changeset
827 __ flush_windows();
a61af66fc99e Initial load
duke
parents:
diff changeset
828
a61af66fc99e Initial load
duke
parents:
diff changeset
829 // mark windows as flushed
a61af66fc99e Initial load
duke
parents:
diff changeset
830 Address flags(G2_thread,
a61af66fc99e Initial load
duke
parents:
diff changeset
831 0,
a61af66fc99e Initial load
duke
parents:
diff changeset
832 in_bytes(JavaThread::frame_anchor_offset()) + in_bytes(JavaFrameAnchor::flags_offset()));
a61af66fc99e Initial load
duke
parents:
diff changeset
833 __ set(JavaFrameAnchor::flushed, G3_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
834 __ st(G3_scratch, flags);
a61af66fc99e Initial load
duke
parents:
diff changeset
835
a61af66fc99e Initial load
duke
parents:
diff changeset
836 // Transition from _thread_in_Java to _thread_in_native. We are already safepoint ready.
a61af66fc99e Initial load
duke
parents:
diff changeset
837
a61af66fc99e Initial load
duke
parents:
diff changeset
838 Address thread_state(G2_thread, 0, in_bytes(JavaThread::thread_state_offset()));
a61af66fc99e Initial load
duke
parents:
diff changeset
839 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
840 { Label L;
a61af66fc99e Initial load
duke
parents:
diff changeset
841 __ ld(thread_state, G3_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
842 __ cmp(G3_scratch, _thread_in_Java);
a61af66fc99e Initial load
duke
parents:
diff changeset
843 __ br(Assembler::equal, false, Assembler::pt, L);
a61af66fc99e Initial load
duke
parents:
diff changeset
844 __ delayed()->nop();
a61af66fc99e Initial load
duke
parents:
diff changeset
845 __ stop("Wrong thread state in native stub");
a61af66fc99e Initial load
duke
parents:
diff changeset
846 __ bind(L);
a61af66fc99e Initial load
duke
parents:
diff changeset
847 }
a61af66fc99e Initial load
duke
parents:
diff changeset
848 #endif // ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
849 __ set(_thread_in_native, G3_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
850 __ st(G3_scratch, thread_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
851
a61af66fc99e Initial load
duke
parents:
diff changeset
852 // Call the jni method, using the delay slot to set the JNIEnv* argument.
a61af66fc99e Initial load
duke
parents:
diff changeset
853 __ callr(O0, 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
854 __ delayed()->
a61af66fc99e Initial load
duke
parents:
diff changeset
855 add(G2_thread, in_bytes(JavaThread::jni_environment_offset()), O0);
a61af66fc99e Initial load
duke
parents:
diff changeset
856 __ ld_ptr(STATE(_thread), G2_thread); // restore thread
a61af66fc99e Initial load
duke
parents:
diff changeset
857
a61af66fc99e Initial load
duke
parents:
diff changeset
858 // must we block?
a61af66fc99e Initial load
duke
parents:
diff changeset
859
a61af66fc99e Initial load
duke
parents:
diff changeset
860 // Block, if necessary, before resuming in _thread_in_Java state.
a61af66fc99e Initial load
duke
parents:
diff changeset
861 // In order for GC to work, don't clear the last_Java_sp until after blocking.
a61af66fc99e Initial load
duke
parents:
diff changeset
862 { Label no_block;
a61af66fc99e Initial load
duke
parents:
diff changeset
863 Address sync_state(G3_scratch, SafepointSynchronize::address_of_state());
a61af66fc99e Initial load
duke
parents:
diff changeset
864
a61af66fc99e Initial load
duke
parents:
diff changeset
865 // Switch thread to "native transition" state before reading the synchronization state.
a61af66fc99e Initial load
duke
parents:
diff changeset
866 // This additional state is necessary because reading and testing the synchronization
a61af66fc99e Initial load
duke
parents:
diff changeset
867 // state is not atomic w.r.t. GC, as this scenario demonstrates:
a61af66fc99e Initial load
duke
parents:
diff changeset
868 // Java thread A, in _thread_in_native state, loads _not_synchronized and is preempted.
a61af66fc99e Initial load
duke
parents:
diff changeset
869 // VM thread changes sync state to synchronizing and suspends threads for GC.
a61af66fc99e Initial load
duke
parents:
diff changeset
870 // Thread A is resumed to finish this native method, but doesn't block here since it
a61af66fc99e Initial load
duke
parents:
diff changeset
871 // didn't see any synchronization is progress, and escapes.
a61af66fc99e Initial load
duke
parents:
diff changeset
872 __ set(_thread_in_native_trans, G3_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
873 __ st(G3_scratch, thread_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
874 if(os::is_MP()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
875 // Write serialization page so VM thread can do a pseudo remote membar.
a61af66fc99e Initial load
duke
parents:
diff changeset
876 // We use the current thread pointer to calculate a thread specific
a61af66fc99e Initial load
duke
parents:
diff changeset
877 // offset to write to within the page. This minimizes bus traffic
a61af66fc99e Initial load
duke
parents:
diff changeset
878 // due to cache line collision.
a61af66fc99e Initial load
duke
parents:
diff changeset
879 __ serialize_memory(G2_thread, G1_scratch, G3_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
880 }
a61af66fc99e Initial load
duke
parents:
diff changeset
881 __ load_contents(sync_state, G3_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
882 __ cmp(G3_scratch, SafepointSynchronize::_not_synchronized);
a61af66fc99e Initial load
duke
parents:
diff changeset
883
a61af66fc99e Initial load
duke
parents:
diff changeset
884
a61af66fc99e Initial load
duke
parents:
diff changeset
885 Label L;
a61af66fc99e Initial load
duke
parents:
diff changeset
886 Address suspend_state(G2_thread, 0, in_bytes(JavaThread::suspend_flags_offset()));
a61af66fc99e Initial load
duke
parents:
diff changeset
887 __ br(Assembler::notEqual, false, Assembler::pn, L);
a61af66fc99e Initial load
duke
parents:
diff changeset
888 __ delayed()->
a61af66fc99e Initial load
duke
parents:
diff changeset
889 ld(suspend_state, G3_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
890 __ cmp(G3_scratch, 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
891 __ br(Assembler::equal, false, Assembler::pt, no_block);
a61af66fc99e Initial load
duke
parents:
diff changeset
892 __ delayed()->nop();
a61af66fc99e Initial load
duke
parents:
diff changeset
893 __ bind(L);
a61af66fc99e Initial load
duke
parents:
diff changeset
894
a61af66fc99e Initial load
duke
parents:
diff changeset
895 // Block. Save any potential method result value before the operation and
a61af66fc99e Initial load
duke
parents:
diff changeset
896 // use a leaf call to leave the last_Java_frame setup undisturbed.
a61af66fc99e Initial load
duke
parents:
diff changeset
897 save_native_result();
a61af66fc99e Initial load
duke
parents:
diff changeset
898 __ call_VM_leaf(noreg,
a61af66fc99e Initial load
duke
parents:
diff changeset
899 CAST_FROM_FN_PTR(address, JavaThread::check_safepoint_and_suspend_for_native_trans),
a61af66fc99e Initial load
duke
parents:
diff changeset
900 G2_thread);
a61af66fc99e Initial load
duke
parents:
diff changeset
901 __ ld_ptr(STATE(_thread), G2_thread); // restore thread
a61af66fc99e Initial load
duke
parents:
diff changeset
902 // Restore any method result value
a61af66fc99e Initial load
duke
parents:
diff changeset
903 restore_native_result();
a61af66fc99e Initial load
duke
parents:
diff changeset
904 __ bind(no_block);
a61af66fc99e Initial load
duke
parents:
diff changeset
905 }
a61af66fc99e Initial load
duke
parents:
diff changeset
906
a61af66fc99e Initial load
duke
parents:
diff changeset
907 // Clear the frame anchor now
a61af66fc99e Initial load
duke
parents:
diff changeset
908
a61af66fc99e Initial load
duke
parents:
diff changeset
909 __ reset_last_Java_frame();
a61af66fc99e Initial load
duke
parents:
diff changeset
910
a61af66fc99e Initial load
duke
parents:
diff changeset
911 // Move the result handler address
a61af66fc99e Initial load
duke
parents:
diff changeset
912 __ mov(Lscratch, G3_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
913 // return possible result to the outer frame
a61af66fc99e Initial load
duke
parents:
diff changeset
914 #ifndef __LP64
a61af66fc99e Initial load
duke
parents:
diff changeset
915 __ mov(O0, I0);
a61af66fc99e Initial load
duke
parents:
diff changeset
916 __ restore(O1, G0, O1);
a61af66fc99e Initial load
duke
parents:
diff changeset
917 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
918 __ restore(O0, G0, O0);
a61af66fc99e Initial load
duke
parents:
diff changeset
919 #endif /* __LP64 */
a61af66fc99e Initial load
duke
parents:
diff changeset
920
a61af66fc99e Initial load
duke
parents:
diff changeset
921 // Move result handler to expected register
a61af66fc99e Initial load
duke
parents:
diff changeset
922 __ mov(G3_scratch, Lscratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
923
a61af66fc99e Initial load
duke
parents:
diff changeset
924
a61af66fc99e Initial load
duke
parents:
diff changeset
925 // thread state is thread_in_native_trans. Any safepoint blocking has
a61af66fc99e Initial load
duke
parents:
diff changeset
926 // happened in the trampoline we are ready to switch to thread_in_Java.
a61af66fc99e Initial load
duke
parents:
diff changeset
927
a61af66fc99e Initial load
duke
parents:
diff changeset
928 __ set(_thread_in_Java, G3_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
929 __ st(G3_scratch, thread_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
930
a61af66fc99e Initial load
duke
parents:
diff changeset
931 // If we have an oop result store it where it will be safe for any further gc
a61af66fc99e Initial load
duke
parents:
diff changeset
932 // until we return now that we've released the handle it might be protected by
a61af66fc99e Initial load
duke
parents:
diff changeset
933
a61af66fc99e Initial load
duke
parents:
diff changeset
934 {
a61af66fc99e Initial load
duke
parents:
diff changeset
935 Label no_oop, store_result;
a61af66fc99e Initial load
duke
parents:
diff changeset
936
a61af66fc99e Initial load
duke
parents:
diff changeset
937 __ set((intptr_t)AbstractInterpreter::result_handler(T_OBJECT), G3_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
938 __ cmp(G3_scratch, Lscratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
939 __ brx(Assembler::notEqual, false, Assembler::pt, no_oop);
a61af66fc99e Initial load
duke
parents:
diff changeset
940 __ delayed()->nop();
a61af66fc99e Initial load
duke
parents:
diff changeset
941 __ addcc(G0, O0, O0);
a61af66fc99e Initial load
duke
parents:
diff changeset
942 __ brx(Assembler::notZero, true, Assembler::pt, store_result); // if result is not NULL:
a61af66fc99e Initial load
duke
parents:
diff changeset
943 __ delayed()->ld_ptr(O0, 0, O0); // unbox it
a61af66fc99e Initial load
duke
parents:
diff changeset
944 __ mov(G0, O0);
a61af66fc99e Initial load
duke
parents:
diff changeset
945
a61af66fc99e Initial load
duke
parents:
diff changeset
946 __ bind(store_result);
a61af66fc99e Initial load
duke
parents:
diff changeset
947 // Store it where gc will look for it and result handler expects it.
a61af66fc99e Initial load
duke
parents:
diff changeset
948 __ st_ptr(O0, STATE(_oop_temp));
a61af66fc99e Initial load
duke
parents:
diff changeset
949
a61af66fc99e Initial load
duke
parents:
diff changeset
950 __ bind(no_oop);
a61af66fc99e Initial load
duke
parents:
diff changeset
951
a61af66fc99e Initial load
duke
parents:
diff changeset
952 }
a61af66fc99e Initial load
duke
parents:
diff changeset
953
a61af66fc99e Initial load
duke
parents:
diff changeset
954 // reset handle block
a61af66fc99e Initial load
duke
parents:
diff changeset
955 __ ld_ptr(G2_thread, in_bytes(JavaThread::active_handles_offset()), G3_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
956 __ st_ptr(G0, G3_scratch, JNIHandleBlock::top_offset_in_bytes());
a61af66fc99e Initial load
duke
parents:
diff changeset
957
a61af66fc99e Initial load
duke
parents:
diff changeset
958
a61af66fc99e Initial load
duke
parents:
diff changeset
959 // handle exceptions (exception handling will handle unlocking!)
a61af66fc99e Initial load
duke
parents:
diff changeset
960 { Label L;
a61af66fc99e Initial load
duke
parents:
diff changeset
961 Address exception_addr (G2_thread, 0, in_bytes(Thread::pending_exception_offset()));
a61af66fc99e Initial load
duke
parents:
diff changeset
962
a61af66fc99e Initial load
duke
parents:
diff changeset
963 __ ld_ptr(exception_addr, Gtemp);
a61af66fc99e Initial load
duke
parents:
diff changeset
964 __ tst(Gtemp);
a61af66fc99e Initial load
duke
parents:
diff changeset
965 __ brx(Assembler::equal, false, Assembler::pt, L);
a61af66fc99e Initial load
duke
parents:
diff changeset
966 __ delayed()->nop();
a61af66fc99e Initial load
duke
parents:
diff changeset
967 __ bind(pending_exception_present);
a61af66fc99e Initial load
duke
parents:
diff changeset
968 // With c++ interpreter we just leave it pending caller will do the correct thing. However...
a61af66fc99e Initial load
duke
parents:
diff changeset
969 // Like x86 we ignore the result of the native call and leave the method locked. This
a61af66fc99e Initial load
duke
parents:
diff changeset
970 // seems wrong to leave things locked.
a61af66fc99e Initial load
duke
parents:
diff changeset
971
a61af66fc99e Initial load
duke
parents:
diff changeset
972 __ br(Assembler::always, false, Assembler::pt, StubRoutines::forward_exception_entry(), relocInfo::runtime_call_type);
a61af66fc99e Initial load
duke
parents:
diff changeset
973 __ delayed()->restore(I5_savedSP, G0, SP); // remove interpreter frame
a61af66fc99e Initial load
duke
parents:
diff changeset
974
a61af66fc99e Initial load
duke
parents:
diff changeset
975 __ bind(L);
a61af66fc99e Initial load
duke
parents:
diff changeset
976 }
a61af66fc99e Initial load
duke
parents:
diff changeset
977
a61af66fc99e Initial load
duke
parents:
diff changeset
978 // jvmdi/jvmpi support (preserves thread register)
a61af66fc99e Initial load
duke
parents:
diff changeset
979 __ notify_method_exit(true, ilgl, InterpreterMacroAssembler::NotifyJVMTI);
a61af66fc99e Initial load
duke
parents:
diff changeset
980
a61af66fc99e Initial load
duke
parents:
diff changeset
981 if (synchronized) {
a61af66fc99e Initial load
duke
parents:
diff changeset
982 // save and restore any potential method result value around the unlocking operation
a61af66fc99e Initial load
duke
parents:
diff changeset
983 save_native_result();
a61af66fc99e Initial load
duke
parents:
diff changeset
984
a61af66fc99e Initial load
duke
parents:
diff changeset
985 const int entry_size = frame::interpreter_frame_monitor_size() * wordSize;
a61af66fc99e Initial load
duke
parents:
diff changeset
986 // Get the initial monitor we allocated
a61af66fc99e Initial load
duke
parents:
diff changeset
987 __ sub(Lstate, entry_size, O1); // initial monitor
a61af66fc99e Initial load
duke
parents:
diff changeset
988 __ unlock_object(O1);
a61af66fc99e Initial load
duke
parents:
diff changeset
989 restore_native_result();
a61af66fc99e Initial load
duke
parents:
diff changeset
990 }
a61af66fc99e Initial load
duke
parents:
diff changeset
991
a61af66fc99e Initial load
duke
parents:
diff changeset
992 #if defined(COMPILER2) && !defined(_LP64)
a61af66fc99e Initial load
duke
parents:
diff changeset
993
a61af66fc99e Initial load
duke
parents:
diff changeset
994 // C2 expects long results in G1 we can't tell if we're returning to interpreted
a61af66fc99e Initial load
duke
parents:
diff changeset
995 // or compiled so just be safe.
a61af66fc99e Initial load
duke
parents:
diff changeset
996
a61af66fc99e Initial load
duke
parents:
diff changeset
997 __ sllx(O0, 32, G1); // Shift bits into high G1
a61af66fc99e Initial load
duke
parents:
diff changeset
998 __ srl (O1, 0, O1); // Zero extend O1
a61af66fc99e Initial load
duke
parents:
diff changeset
999 __ or3 (O1, G1, G1); // OR 64 bits into G1
a61af66fc99e Initial load
duke
parents:
diff changeset
1000
a61af66fc99e Initial load
duke
parents:
diff changeset
1001 #endif /* COMPILER2 && !_LP64 */
a61af66fc99e Initial load
duke
parents:
diff changeset
1002
a61af66fc99e Initial load
duke
parents:
diff changeset
1003 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
1004 {
a61af66fc99e Initial load
duke
parents:
diff changeset
1005 Label ok;
a61af66fc99e Initial load
duke
parents:
diff changeset
1006 __ cmp(I5_savedSP, FP);
a61af66fc99e Initial load
duke
parents:
diff changeset
1007 __ brx(Assembler::greaterEqualUnsigned, false, Assembler::pt, ok);
a61af66fc99e Initial load
duke
parents:
diff changeset
1008 __ delayed()->nop();
a61af66fc99e Initial load
duke
parents:
diff changeset
1009 __ stop("bad I5_savedSP value");
a61af66fc99e Initial load
duke
parents:
diff changeset
1010 __ should_not_reach_here();
a61af66fc99e Initial load
duke
parents:
diff changeset
1011 __ bind(ok);
a61af66fc99e Initial load
duke
parents:
diff changeset
1012 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1013 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
1014 // Calls result handler which POPS FRAME
a61af66fc99e Initial load
duke
parents:
diff changeset
1015 if (TraceJumps) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1016 // Move target to register that is recordable
a61af66fc99e Initial load
duke
parents:
diff changeset
1017 __ mov(Lscratch, G3_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
1018 __ JMP(G3_scratch, 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1019 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1020 __ jmp(Lscratch, 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1021 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1022 __ delayed()->nop();
a61af66fc99e Initial load
duke
parents:
diff changeset
1023
a61af66fc99e Initial load
duke
parents:
diff changeset
1024 if (inc_counter) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1025 // handle invocation counter overflow
a61af66fc99e Initial load
duke
parents:
diff changeset
1026 __ bind(invocation_counter_overflow);
a61af66fc99e Initial load
duke
parents:
diff changeset
1027 generate_counter_overflow(Lcontinue);
a61af66fc99e Initial load
duke
parents:
diff changeset
1028 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1029
a61af66fc99e Initial load
duke
parents:
diff changeset
1030
a61af66fc99e Initial load
duke
parents:
diff changeset
1031 return entry;
a61af66fc99e Initial load
duke
parents:
diff changeset
1032 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1033
a61af66fc99e Initial load
duke
parents:
diff changeset
1034 void CppInterpreterGenerator::generate_compute_interpreter_state(const Register state,
a61af66fc99e Initial load
duke
parents:
diff changeset
1035 const Register prev_state,
a61af66fc99e Initial load
duke
parents:
diff changeset
1036 bool native) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1037
a61af66fc99e Initial load
duke
parents:
diff changeset
1038 // On entry
a61af66fc99e Initial load
duke
parents:
diff changeset
1039 // G5_method - caller's method
a61af66fc99e Initial load
duke
parents:
diff changeset
1040 // Gargs - points to initial parameters (i.e. locals[0])
a61af66fc99e Initial load
duke
parents:
diff changeset
1041 // G2_thread - valid? (C1 only??)
a61af66fc99e Initial load
duke
parents:
diff changeset
1042 // "prev_state" - contains any previous frame manager state which we must save a link
a61af66fc99e Initial load
duke
parents:
diff changeset
1043 //
a61af66fc99e Initial load
duke
parents:
diff changeset
1044 // On return
a61af66fc99e Initial load
duke
parents:
diff changeset
1045 // "state" is a pointer to the newly allocated state object. We must allocate and initialize
a61af66fc99e Initial load
duke
parents:
diff changeset
1046 // a new interpretState object and the method expression stack.
a61af66fc99e Initial load
duke
parents:
diff changeset
1047
a61af66fc99e Initial load
duke
parents:
diff changeset
1048 assert_different_registers(state, prev_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
1049 assert_different_registers(prev_state, G3_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
1050 const Register Gtmp = G3_scratch;
a61af66fc99e Initial load
duke
parents:
diff changeset
1051 const Address constants (G5_method, 0, in_bytes(methodOopDesc::constants_offset()));
a61af66fc99e Initial load
duke
parents:
diff changeset
1052 const Address access_flags (G5_method, 0, in_bytes(methodOopDesc::access_flags_offset()));
a61af66fc99e Initial load
duke
parents:
diff changeset
1053 const Address size_of_parameters(G5_method, 0, in_bytes(methodOopDesc::size_of_parameters_offset()));
a61af66fc99e Initial load
duke
parents:
diff changeset
1054 const Address max_stack (G5_method, 0, in_bytes(methodOopDesc::max_stack_offset()));
a61af66fc99e Initial load
duke
parents:
diff changeset
1055 const Address size_of_locals (G5_method, 0, in_bytes(methodOopDesc::size_of_locals_offset()));
a61af66fc99e Initial load
duke
parents:
diff changeset
1056
a61af66fc99e Initial load
duke
parents:
diff changeset
1057 // slop factor is two extra slots on the expression stack so that
a61af66fc99e Initial load
duke
parents:
diff changeset
1058 // we always have room to store a result when returning from a call without parameters
a61af66fc99e Initial load
duke
parents:
diff changeset
1059 // that returns a result.
a61af66fc99e Initial load
duke
parents:
diff changeset
1060
a61af66fc99e Initial load
duke
parents:
diff changeset
1061 const int slop_factor = 2*wordSize;
a61af66fc99e Initial load
duke
parents:
diff changeset
1062
a61af66fc99e Initial load
duke
parents:
diff changeset
1063 const int fixed_size = ((sizeof(BytecodeInterpreter) + slop_factor) >> LogBytesPerWord) + // what is the slop factor?
710
e5b0439ef4ae 6655638: dynamic languages need method handles
jrose
parents: 196
diff changeset
1064 //6815692//methodOopDesc::extra_stack_words() + // extra push slots for MH adapters
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1065 frame::memory_parameter_word_sp_offset + // register save area + param window
a61af66fc99e Initial load
duke
parents:
diff changeset
1066 (native ? frame::interpreter_frame_extra_outgoing_argument_words : 0); // JNI, class
a61af66fc99e Initial load
duke
parents:
diff changeset
1067
a61af66fc99e Initial load
duke
parents:
diff changeset
1068 // XXX G5_method valid
a61af66fc99e Initial load
duke
parents:
diff changeset
1069
a61af66fc99e Initial load
duke
parents:
diff changeset
1070 // Now compute new frame size
a61af66fc99e Initial load
duke
parents:
diff changeset
1071
a61af66fc99e Initial load
duke
parents:
diff changeset
1072 if (native) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1073 __ lduh( size_of_parameters, Gtmp );
a61af66fc99e Initial load
duke
parents:
diff changeset
1074 __ calc_mem_param_words(Gtmp, Gtmp); // space for native call parameters passed on the stack in words
a61af66fc99e Initial load
duke
parents:
diff changeset
1075 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1076 __ lduh(max_stack, Gtmp); // Full size expression stack
a61af66fc99e Initial load
duke
parents:
diff changeset
1077 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1078 __ add(Gtmp, fixed_size, Gtmp); // plus the fixed portion
a61af66fc99e Initial load
duke
parents:
diff changeset
1079
a61af66fc99e Initial load
duke
parents:
diff changeset
1080 __ neg(Gtmp); // negative space for stack/parameters in words
a61af66fc99e Initial load
duke
parents:
diff changeset
1081 __ and3(Gtmp, -WordsPerLong, Gtmp); // make multiple of 2 (SP must be 2-word aligned)
a61af66fc99e Initial load
duke
parents:
diff changeset
1082 __ sll(Gtmp, LogBytesPerWord, Gtmp); // negative space for frame in bytes
a61af66fc99e Initial load
duke
parents:
diff changeset
1083
a61af66fc99e Initial load
duke
parents:
diff changeset
1084 // Need to do stack size check here before we fault on large frames
a61af66fc99e Initial load
duke
parents:
diff changeset
1085
a61af66fc99e Initial load
duke
parents:
diff changeset
1086 Label stack_ok;
a61af66fc99e Initial load
duke
parents:
diff changeset
1087
a61af66fc99e Initial load
duke
parents:
diff changeset
1088 const int max_pages = StackShadowPages > (StackRedPages+StackYellowPages) ? StackShadowPages :
a61af66fc99e Initial load
duke
parents:
diff changeset
1089 (StackRedPages+StackYellowPages);
a61af66fc99e Initial load
duke
parents:
diff changeset
1090
a61af66fc99e Initial load
duke
parents:
diff changeset
1091
a61af66fc99e Initial load
duke
parents:
diff changeset
1092 __ ld_ptr(G2_thread, in_bytes(Thread::stack_base_offset()), O0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1093 __ ld_ptr(G2_thread, in_bytes(Thread::stack_size_offset()), O1);
a61af66fc99e Initial load
duke
parents:
diff changeset
1094 // compute stack bottom
a61af66fc99e Initial load
duke
parents:
diff changeset
1095 __ sub(O0, O1, O0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1096
a61af66fc99e Initial load
duke
parents:
diff changeset
1097 // Avoid touching the guard pages
a61af66fc99e Initial load
duke
parents:
diff changeset
1098 // Also a fudge for frame size of BytecodeInterpreter::run
a61af66fc99e Initial load
duke
parents:
diff changeset
1099 // It varies from 1k->4k depending on build type
a61af66fc99e Initial load
duke
parents:
diff changeset
1100 const int fudge = 6 * K;
a61af66fc99e Initial load
duke
parents:
diff changeset
1101
a61af66fc99e Initial load
duke
parents:
diff changeset
1102 __ set(fudge + (max_pages * os::vm_page_size()), O1);
a61af66fc99e Initial load
duke
parents:
diff changeset
1103
a61af66fc99e Initial load
duke
parents:
diff changeset
1104 __ add(O0, O1, O0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1105 __ sub(O0, Gtmp, O0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1106 __ cmp(SP, O0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1107 __ brx(Assembler::greaterUnsigned, false, Assembler::pt, stack_ok);
a61af66fc99e Initial load
duke
parents:
diff changeset
1108 __ delayed()->nop();
a61af66fc99e Initial load
duke
parents:
diff changeset
1109
a61af66fc99e Initial load
duke
parents:
diff changeset
1110 // throw exception return address becomes throwing pc
a61af66fc99e Initial load
duke
parents:
diff changeset
1111
a61af66fc99e Initial load
duke
parents:
diff changeset
1112 __ call_VM(Oexception, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_StackOverflowError));
a61af66fc99e Initial load
duke
parents:
diff changeset
1113 __ stop("never reached");
a61af66fc99e Initial load
duke
parents:
diff changeset
1114
a61af66fc99e Initial load
duke
parents:
diff changeset
1115 __ bind(stack_ok);
a61af66fc99e Initial load
duke
parents:
diff changeset
1116
a61af66fc99e Initial load
duke
parents:
diff changeset
1117 __ save(SP, Gtmp, SP); // setup new frame and register window
a61af66fc99e Initial load
duke
parents:
diff changeset
1118
a61af66fc99e Initial load
duke
parents:
diff changeset
1119 // New window I7 call_stub or previous activation
a61af66fc99e Initial load
duke
parents:
diff changeset
1120 // O6 - register save area, BytecodeInterpreter just below it, args/locals just above that
a61af66fc99e Initial load
duke
parents:
diff changeset
1121 //
a61af66fc99e Initial load
duke
parents:
diff changeset
1122 __ sub(FP, sizeof(BytecodeInterpreter), state); // Point to new Interpreter state
a61af66fc99e Initial load
duke
parents:
diff changeset
1123 __ add(state, STACK_BIAS, state ); // Account for 64bit bias
a61af66fc99e Initial load
duke
parents:
diff changeset
1124
a61af66fc99e Initial load
duke
parents:
diff changeset
1125 #define XXX_STATE(field_name) state, in_bytes(byte_offset_of(BytecodeInterpreter, field_name))
a61af66fc99e Initial load
duke
parents:
diff changeset
1126
a61af66fc99e Initial load
duke
parents:
diff changeset
1127 // Initialize a new Interpreter state
a61af66fc99e Initial load
duke
parents:
diff changeset
1128 // orig_sp - caller's original sp
a61af66fc99e Initial load
duke
parents:
diff changeset
1129 // G2_thread - thread
a61af66fc99e Initial load
duke
parents:
diff changeset
1130 // Gargs - &locals[0] (unbiased?)
a61af66fc99e Initial load
duke
parents:
diff changeset
1131 // G5_method - method
a61af66fc99e Initial load
duke
parents:
diff changeset
1132 // SP (biased) - accounts for full size java stack, BytecodeInterpreter object, register save area, and register parameter save window
a61af66fc99e Initial load
duke
parents:
diff changeset
1133
a61af66fc99e Initial load
duke
parents:
diff changeset
1134
a61af66fc99e Initial load
duke
parents:
diff changeset
1135 __ set(0xdead0004, O1);
a61af66fc99e Initial load
duke
parents:
diff changeset
1136
a61af66fc99e Initial load
duke
parents:
diff changeset
1137
a61af66fc99e Initial load
duke
parents:
diff changeset
1138 __ st_ptr(Gargs, XXX_STATE(_locals));
a61af66fc99e Initial load
duke
parents:
diff changeset
1139 __ st_ptr(G0, XXX_STATE(_oop_temp));
a61af66fc99e Initial load
duke
parents:
diff changeset
1140
a61af66fc99e Initial load
duke
parents:
diff changeset
1141 __ st_ptr(state, XXX_STATE(_self_link)); // point to self
a61af66fc99e Initial load
duke
parents:
diff changeset
1142 __ st_ptr(prev_state->after_save(), XXX_STATE(_prev_link)); // Chain interpreter states
a61af66fc99e Initial load
duke
parents:
diff changeset
1143 __ st_ptr(G2_thread, XXX_STATE(_thread)); // Store javathread
a61af66fc99e Initial load
duke
parents:
diff changeset
1144
a61af66fc99e Initial load
duke
parents:
diff changeset
1145 if (native) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1146 __ st_ptr(G0, XXX_STATE(_bcp));
a61af66fc99e Initial load
duke
parents:
diff changeset
1147 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1148 __ ld_ptr(G5_method, in_bytes(methodOopDesc::const_offset()), O2); // get constMethodOop
a61af66fc99e Initial load
duke
parents:
diff changeset
1149 __ add(O2, in_bytes(constMethodOopDesc::codes_offset()), O2); // get bcp
a61af66fc99e Initial load
duke
parents:
diff changeset
1150 __ st_ptr(O2, XXX_STATE(_bcp));
a61af66fc99e Initial load
duke
parents:
diff changeset
1151 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1152
a61af66fc99e Initial load
duke
parents:
diff changeset
1153 __ st_ptr(G0, XXX_STATE(_mdx));
a61af66fc99e Initial load
duke
parents:
diff changeset
1154 __ st_ptr(G5_method, XXX_STATE(_method));
a61af66fc99e Initial load
duke
parents:
diff changeset
1155
a61af66fc99e Initial load
duke
parents:
diff changeset
1156 __ set((int) BytecodeInterpreter::method_entry, O1);
a61af66fc99e Initial load
duke
parents:
diff changeset
1157 __ st(O1, XXX_STATE(_msg));
a61af66fc99e Initial load
duke
parents:
diff changeset
1158
a61af66fc99e Initial load
duke
parents:
diff changeset
1159 __ ld_ptr(constants, O3);
a61af66fc99e Initial load
duke
parents:
diff changeset
1160 __ ld_ptr(O3, constantPoolOopDesc::cache_offset_in_bytes(), O2);
a61af66fc99e Initial load
duke
parents:
diff changeset
1161 __ st_ptr(O2, XXX_STATE(_constants));
a61af66fc99e Initial load
duke
parents:
diff changeset
1162
a61af66fc99e Initial load
duke
parents:
diff changeset
1163 __ st_ptr(G0, XXX_STATE(_result._to_call._callee));
a61af66fc99e Initial load
duke
parents:
diff changeset
1164
a61af66fc99e Initial load
duke
parents:
diff changeset
1165 // Monitor base is just start of BytecodeInterpreter object;
a61af66fc99e Initial load
duke
parents:
diff changeset
1166 __ mov(state, O2);
a61af66fc99e Initial load
duke
parents:
diff changeset
1167 __ st_ptr(O2, XXX_STATE(_monitor_base));
a61af66fc99e Initial load
duke
parents:
diff changeset
1168
a61af66fc99e Initial load
duke
parents:
diff changeset
1169 // Do we need a monitor for synchonized method?
a61af66fc99e Initial load
duke
parents:
diff changeset
1170 {
a61af66fc99e Initial load
duke
parents:
diff changeset
1171 __ ld(access_flags, O1);
a61af66fc99e Initial load
duke
parents:
diff changeset
1172 Label done;
a61af66fc99e Initial load
duke
parents:
diff changeset
1173 Label got_obj;
a61af66fc99e Initial load
duke
parents:
diff changeset
1174 __ btst(JVM_ACC_SYNCHRONIZED, O1);
a61af66fc99e Initial load
duke
parents:
diff changeset
1175 __ br( Assembler::zero, false, Assembler::pt, done);
a61af66fc99e Initial load
duke
parents:
diff changeset
1176
a61af66fc99e Initial load
duke
parents:
diff changeset
1177 const int mirror_offset = klassOopDesc::klass_part_offset_in_bytes() + Klass::java_mirror_offset_in_bytes();
a61af66fc99e Initial load
duke
parents:
diff changeset
1178 __ delayed()->btst(JVM_ACC_STATIC, O1);
a61af66fc99e Initial load
duke
parents:
diff changeset
1179 __ ld_ptr(XXX_STATE(_locals), O1);
a61af66fc99e Initial load
duke
parents:
diff changeset
1180 __ br( Assembler::zero, true, Assembler::pt, got_obj);
a61af66fc99e Initial load
duke
parents:
diff changeset
1181 __ delayed()->ld_ptr(O1, 0, O1); // get receiver for not-static case
a61af66fc99e Initial load
duke
parents:
diff changeset
1182 __ ld_ptr(constants, O1);
a61af66fc99e Initial load
duke
parents:
diff changeset
1183 __ ld_ptr( O1, constantPoolOopDesc::pool_holder_offset_in_bytes(), O1);
a61af66fc99e Initial load
duke
parents:
diff changeset
1184 // lock the mirror, not the klassOop
a61af66fc99e Initial load
duke
parents:
diff changeset
1185 __ ld_ptr( O1, mirror_offset, O1);
a61af66fc99e Initial load
duke
parents:
diff changeset
1186
a61af66fc99e Initial load
duke
parents:
diff changeset
1187 __ bind(got_obj);
a61af66fc99e Initial load
duke
parents:
diff changeset
1188
a61af66fc99e Initial load
duke
parents:
diff changeset
1189 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
1190 __ tst(O1);
a61af66fc99e Initial load
duke
parents:
diff changeset
1191 __ breakpoint_trap(Assembler::zero);
a61af66fc99e Initial load
duke
parents:
diff changeset
1192 #endif // ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
1193
a61af66fc99e Initial load
duke
parents:
diff changeset
1194 const int entry_size = frame::interpreter_frame_monitor_size() * wordSize;
a61af66fc99e Initial load
duke
parents:
diff changeset
1195 __ sub(SP, entry_size, SP); // account for initial monitor
a61af66fc99e Initial load
duke
parents:
diff changeset
1196 __ sub(O2, entry_size, O2); // initial monitor
a61af66fc99e Initial load
duke
parents:
diff changeset
1197 __ st_ptr(O1, O2, BasicObjectLock::obj_offset_in_bytes()); // and allocate it for interpreter use
a61af66fc99e Initial load
duke
parents:
diff changeset
1198 __ bind(done);
a61af66fc99e Initial load
duke
parents:
diff changeset
1199 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1200
a61af66fc99e Initial load
duke
parents:
diff changeset
1201 // Remember initial frame bottom
a61af66fc99e Initial load
duke
parents:
diff changeset
1202
a61af66fc99e Initial load
duke
parents:
diff changeset
1203 __ st_ptr(SP, XXX_STATE(_frame_bottom));
a61af66fc99e Initial load
duke
parents:
diff changeset
1204
a61af66fc99e Initial load
duke
parents:
diff changeset
1205 __ st_ptr(O2, XXX_STATE(_stack_base));
a61af66fc99e Initial load
duke
parents:
diff changeset
1206
a61af66fc99e Initial load
duke
parents:
diff changeset
1207 __ sub(O2, wordSize, O2); // prepush
a61af66fc99e Initial load
duke
parents:
diff changeset
1208 __ st_ptr(O2, XXX_STATE(_stack)); // PREPUSH
a61af66fc99e Initial load
duke
parents:
diff changeset
1209
a61af66fc99e Initial load
duke
parents:
diff changeset
1210 __ lduh(max_stack, O3); // Full size expression stack
2357
8033953d67ff 7012648: move JSR 292 to package java.lang.invoke and adjust names
jrose
parents: 1972
diff changeset
1211 guarantee(!EnableMethodHandles, "no support yet for java.lang.invoke.MethodHandle"); //6815692
710
e5b0439ef4ae 6655638: dynamic languages need method handles
jrose
parents: 196
diff changeset
1212 //6815692//if (EnableMethodHandles)
e5b0439ef4ae 6655638: dynamic languages need method handles
jrose
parents: 196
diff changeset
1213 //6815692// __ inc(O3, methodOopDesc::extra_stack_entries());
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1214 __ sll(O3, LogBytesPerWord, O3);
a61af66fc99e Initial load
duke
parents:
diff changeset
1215 __ sub(O2, O3, O3);
a61af66fc99e Initial load
duke
parents:
diff changeset
1216 // __ sub(O3, wordSize, O3); // so prepush doesn't look out of bounds
a61af66fc99e Initial load
duke
parents:
diff changeset
1217 __ st_ptr(O3, XXX_STATE(_stack_limit));
a61af66fc99e Initial load
duke
parents:
diff changeset
1218
a61af66fc99e Initial load
duke
parents:
diff changeset
1219 if (!native) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1220 //
a61af66fc99e Initial load
duke
parents:
diff changeset
1221 // Code to initialize locals
a61af66fc99e Initial load
duke
parents:
diff changeset
1222 //
a61af66fc99e Initial load
duke
parents:
diff changeset
1223 Register init_value = noreg; // will be G0 if we must clear locals
a61af66fc99e Initial load
duke
parents:
diff changeset
1224 // Now zero locals
a61af66fc99e Initial load
duke
parents:
diff changeset
1225 if (true /* zerolocals */ || ClearInterpreterLocals) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1226 // explicitly initialize locals
a61af66fc99e Initial load
duke
parents:
diff changeset
1227 init_value = G0;
a61af66fc99e Initial load
duke
parents:
diff changeset
1228 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1229 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
1230 // initialize locals to a garbage pattern for better debugging
a61af66fc99e Initial load
duke
parents:
diff changeset
1231 init_value = O3;
a61af66fc99e Initial load
duke
parents:
diff changeset
1232 __ set( 0x0F0F0F0F, init_value );
a61af66fc99e Initial load
duke
parents:
diff changeset
1233 #endif // ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
1234 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1235 if (init_value != noreg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1236 Label clear_loop;
a61af66fc99e Initial load
duke
parents:
diff changeset
1237
a61af66fc99e Initial load
duke
parents:
diff changeset
1238 // NOTE: If you change the frame layout, this code will need to
a61af66fc99e Initial load
duke
parents:
diff changeset
1239 // be updated!
a61af66fc99e Initial load
duke
parents:
diff changeset
1240 __ lduh( size_of_locals, O2 );
a61af66fc99e Initial load
duke
parents:
diff changeset
1241 __ lduh( size_of_parameters, O1 );
a61af66fc99e Initial load
duke
parents:
diff changeset
1242 __ sll( O2, LogBytesPerWord, O2);
a61af66fc99e Initial load
duke
parents:
diff changeset
1243 __ sll( O1, LogBytesPerWord, O1 );
a61af66fc99e Initial load
duke
parents:
diff changeset
1244 __ ld_ptr(XXX_STATE(_locals), L2_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
1245 __ sub( L2_scratch, O2, O2 );
a61af66fc99e Initial load
duke
parents:
diff changeset
1246 __ sub( L2_scratch, O1, O1 );
a61af66fc99e Initial load
duke
parents:
diff changeset
1247
a61af66fc99e Initial load
duke
parents:
diff changeset
1248 __ bind( clear_loop );
a61af66fc99e Initial load
duke
parents:
diff changeset
1249 __ inc( O2, wordSize );
a61af66fc99e Initial load
duke
parents:
diff changeset
1250
a61af66fc99e Initial load
duke
parents:
diff changeset
1251 __ cmp( O2, O1 );
a61af66fc99e Initial load
duke
parents:
diff changeset
1252 __ br( Assembler::lessEqualUnsigned, true, Assembler::pt, clear_loop );
a61af66fc99e Initial load
duke
parents:
diff changeset
1253 __ delayed()->st_ptr( init_value, O2, 0 );
a61af66fc99e Initial load
duke
parents:
diff changeset
1254 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1255 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1256 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1257 // Find preallocated monitor and lock method (C++ interpreter)
a61af66fc99e Initial load
duke
parents:
diff changeset
1258 //
a61af66fc99e Initial load
duke
parents:
diff changeset
1259 void InterpreterGenerator::lock_method(void) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1260 // Lock the current method.
a61af66fc99e Initial load
duke
parents:
diff changeset
1261 // Destroys registers L2_scratch, L3_scratch, O0
a61af66fc99e Initial load
duke
parents:
diff changeset
1262 //
a61af66fc99e Initial load
duke
parents:
diff changeset
1263 // Find everything relative to Lstate
a61af66fc99e Initial load
duke
parents:
diff changeset
1264
a61af66fc99e Initial load
duke
parents:
diff changeset
1265 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
1266 __ ld_ptr(STATE(_method), L2_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
1267 __ ld(L2_scratch, in_bytes(methodOopDesc::access_flags_offset()), O0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1268
a61af66fc99e Initial load
duke
parents:
diff changeset
1269 { Label ok;
a61af66fc99e Initial load
duke
parents:
diff changeset
1270 __ btst(JVM_ACC_SYNCHRONIZED, O0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1271 __ br( Assembler::notZero, false, Assembler::pt, ok);
a61af66fc99e Initial load
duke
parents:
diff changeset
1272 __ delayed()->nop();
a61af66fc99e Initial load
duke
parents:
diff changeset
1273 __ stop("method doesn't need synchronization");
a61af66fc99e Initial load
duke
parents:
diff changeset
1274 __ bind(ok);
a61af66fc99e Initial load
duke
parents:
diff changeset
1275 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1276 #endif // ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
1277
a61af66fc99e Initial load
duke
parents:
diff changeset
1278 // monitor is already allocated at stack base
a61af66fc99e Initial load
duke
parents:
diff changeset
1279 // and the lockee is already present
a61af66fc99e Initial load
duke
parents:
diff changeset
1280 __ ld_ptr(STATE(_stack_base), L2_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
1281 __ ld_ptr(L2_scratch, BasicObjectLock::obj_offset_in_bytes(), O0); // get object
a61af66fc99e Initial load
duke
parents:
diff changeset
1282 __ lock_object(L2_scratch, O0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1283
a61af66fc99e Initial load
duke
parents:
diff changeset
1284 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1285
a61af66fc99e Initial load
duke
parents:
diff changeset
1286 // Generate code for handling resuming a deopted method
a61af66fc99e Initial load
duke
parents:
diff changeset
1287 void CppInterpreterGenerator::generate_deopt_handling() {
a61af66fc99e Initial load
duke
parents:
diff changeset
1288
a61af66fc99e Initial load
duke
parents:
diff changeset
1289 Label return_from_deopt_common;
a61af66fc99e Initial load
duke
parents:
diff changeset
1290
a61af66fc99e Initial load
duke
parents:
diff changeset
1291 // deopt needs to jump to here to enter the interpreter (return a result)
a61af66fc99e Initial load
duke
parents:
diff changeset
1292 deopt_frame_manager_return_atos = __ pc();
a61af66fc99e Initial load
duke
parents:
diff changeset
1293
a61af66fc99e Initial load
duke
parents:
diff changeset
1294 // O0/O1 live
a61af66fc99e Initial load
duke
parents:
diff changeset
1295 __ ba(false, return_from_deopt_common);
a61af66fc99e Initial load
duke
parents:
diff changeset
1296 __ delayed()->set(AbstractInterpreter::BasicType_as_index(T_OBJECT), L3_scratch); // Result stub address array index
a61af66fc99e Initial load
duke
parents:
diff changeset
1297
a61af66fc99e Initial load
duke
parents:
diff changeset
1298
a61af66fc99e Initial load
duke
parents:
diff changeset
1299 // deopt needs to jump to here to enter the interpreter (return a result)
a61af66fc99e Initial load
duke
parents:
diff changeset
1300 deopt_frame_manager_return_btos = __ pc();
a61af66fc99e Initial load
duke
parents:
diff changeset
1301
a61af66fc99e Initial load
duke
parents:
diff changeset
1302 // O0/O1 live
a61af66fc99e Initial load
duke
parents:
diff changeset
1303 __ ba(false, return_from_deopt_common);
a61af66fc99e Initial load
duke
parents:
diff changeset
1304 __ delayed()->set(AbstractInterpreter::BasicType_as_index(T_BOOLEAN), L3_scratch); // Result stub address array index
a61af66fc99e Initial load
duke
parents:
diff changeset
1305
a61af66fc99e Initial load
duke
parents:
diff changeset
1306 // deopt needs to jump to here to enter the interpreter (return a result)
a61af66fc99e Initial load
duke
parents:
diff changeset
1307 deopt_frame_manager_return_itos = __ pc();
a61af66fc99e Initial load
duke
parents:
diff changeset
1308
a61af66fc99e Initial load
duke
parents:
diff changeset
1309 // O0/O1 live
a61af66fc99e Initial load
duke
parents:
diff changeset
1310 __ ba(false, return_from_deopt_common);
a61af66fc99e Initial load
duke
parents:
diff changeset
1311 __ delayed()->set(AbstractInterpreter::BasicType_as_index(T_INT), L3_scratch); // Result stub address array index
a61af66fc99e Initial load
duke
parents:
diff changeset
1312
a61af66fc99e Initial load
duke
parents:
diff changeset
1313 // deopt needs to jump to here to enter the interpreter (return a result)
a61af66fc99e Initial load
duke
parents:
diff changeset
1314
a61af66fc99e Initial load
duke
parents:
diff changeset
1315 deopt_frame_manager_return_ltos = __ pc();
a61af66fc99e Initial load
duke
parents:
diff changeset
1316 #if !defined(_LP64) && defined(COMPILER2)
a61af66fc99e Initial load
duke
parents:
diff changeset
1317 // All return values are where we want them, except for Longs. C2 returns
a61af66fc99e Initial load
duke
parents:
diff changeset
1318 // longs in G1 in the 32-bit build whereas the interpreter wants them in O0/O1.
a61af66fc99e Initial load
duke
parents:
diff changeset
1319 // Since the interpreter will return longs in G1 and O0/O1 in the 32bit
a61af66fc99e Initial load
duke
parents:
diff changeset
1320 // build even if we are returning from interpreted we just do a little
a61af66fc99e Initial load
duke
parents:
diff changeset
1321 // stupid shuffing.
a61af66fc99e Initial load
duke
parents:
diff changeset
1322 // Note: I tried to make c2 return longs in O0/O1 and G1 so we wouldn't have to
a61af66fc99e Initial load
duke
parents:
diff changeset
1323 // do this here. Unfortunately if we did a rethrow we'd see an machepilog node
a61af66fc99e Initial load
duke
parents:
diff changeset
1324 // first which would move g1 -> O0/O1 and destroy the exception we were throwing.
a61af66fc99e Initial load
duke
parents:
diff changeset
1325
a61af66fc99e Initial load
duke
parents:
diff changeset
1326 __ srl (G1, 0,O1);
a61af66fc99e Initial load
duke
parents:
diff changeset
1327 __ srlx(G1,32,O0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1328 #endif /* !_LP64 && COMPILER2 */
a61af66fc99e Initial load
duke
parents:
diff changeset
1329 // O0/O1 live
a61af66fc99e Initial load
duke
parents:
diff changeset
1330 __ ba(false, return_from_deopt_common);
a61af66fc99e Initial load
duke
parents:
diff changeset
1331 __ delayed()->set(AbstractInterpreter::BasicType_as_index(T_LONG), L3_scratch); // Result stub address array index
a61af66fc99e Initial load
duke
parents:
diff changeset
1332
a61af66fc99e Initial load
duke
parents:
diff changeset
1333 // deopt needs to jump to here to enter the interpreter (return a result)
a61af66fc99e Initial load
duke
parents:
diff changeset
1334
a61af66fc99e Initial load
duke
parents:
diff changeset
1335 deopt_frame_manager_return_ftos = __ pc();
a61af66fc99e Initial load
duke
parents:
diff changeset
1336 // O0/O1 live
a61af66fc99e Initial load
duke
parents:
diff changeset
1337 __ ba(false, return_from_deopt_common);
a61af66fc99e Initial load
duke
parents:
diff changeset
1338 __ delayed()->set(AbstractInterpreter::BasicType_as_index(T_FLOAT), L3_scratch); // Result stub address array index
a61af66fc99e Initial load
duke
parents:
diff changeset
1339
a61af66fc99e Initial load
duke
parents:
diff changeset
1340 // deopt needs to jump to here to enter the interpreter (return a result)
a61af66fc99e Initial load
duke
parents:
diff changeset
1341 deopt_frame_manager_return_dtos = __ pc();
a61af66fc99e Initial load
duke
parents:
diff changeset
1342
a61af66fc99e Initial load
duke
parents:
diff changeset
1343 // O0/O1 live
a61af66fc99e Initial load
duke
parents:
diff changeset
1344 __ ba(false, return_from_deopt_common);
a61af66fc99e Initial load
duke
parents:
diff changeset
1345 __ delayed()->set(AbstractInterpreter::BasicType_as_index(T_DOUBLE), L3_scratch); // Result stub address array index
a61af66fc99e Initial load
duke
parents:
diff changeset
1346
a61af66fc99e Initial load
duke
parents:
diff changeset
1347 // deopt needs to jump to here to enter the interpreter (return a result)
a61af66fc99e Initial load
duke
parents:
diff changeset
1348 deopt_frame_manager_return_vtos = __ pc();
a61af66fc99e Initial load
duke
parents:
diff changeset
1349
a61af66fc99e Initial load
duke
parents:
diff changeset
1350 // O0/O1 live
a61af66fc99e Initial load
duke
parents:
diff changeset
1351 __ set(AbstractInterpreter::BasicType_as_index(T_VOID), L3_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
1352
a61af66fc99e Initial load
duke
parents:
diff changeset
1353 // Deopt return common
a61af66fc99e Initial load
duke
parents:
diff changeset
1354 // an index is present that lets us move any possible result being
a61af66fc99e Initial load
duke
parents:
diff changeset
1355 // return to the interpreter's stack
a61af66fc99e Initial load
duke
parents:
diff changeset
1356 //
a61af66fc99e Initial load
duke
parents:
diff changeset
1357 __ bind(return_from_deopt_common);
a61af66fc99e Initial load
duke
parents:
diff changeset
1358
a61af66fc99e Initial load
duke
parents:
diff changeset
1359 // Result if any is in native abi result (O0..O1/F0..F1). The java expression
a61af66fc99e Initial load
duke
parents:
diff changeset
1360 // stack is in the state that the calling convention left it.
a61af66fc99e Initial load
duke
parents:
diff changeset
1361 // Copy the result from native abi result and place it on java expression stack.
a61af66fc99e Initial load
duke
parents:
diff changeset
1362
a61af66fc99e Initial load
duke
parents:
diff changeset
1363 // Current interpreter state is present in Lstate
a61af66fc99e Initial load
duke
parents:
diff changeset
1364
a61af66fc99e Initial load
duke
parents:
diff changeset
1365 // Get current pre-pushed top of interpreter stack
a61af66fc99e Initial load
duke
parents:
diff changeset
1366 // Any result (if any) is in native abi
a61af66fc99e Initial load
duke
parents:
diff changeset
1367 // result type index is in L3_scratch
a61af66fc99e Initial load
duke
parents:
diff changeset
1368
a61af66fc99e Initial load
duke
parents:
diff changeset
1369 __ ld_ptr(STATE(_stack), L1_scratch); // get top of java expr stack
a61af66fc99e Initial load
duke
parents:
diff changeset
1370
a61af66fc99e Initial load
duke
parents:
diff changeset
1371 __ set((intptr_t)CppInterpreter::_tosca_to_stack, L4_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
1372 __ sll(L3_scratch, LogBytesPerWord, L3_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
1373 __ ld_ptr(L4_scratch, L3_scratch, Lscratch); // get typed result converter address
a61af66fc99e Initial load
duke
parents:
diff changeset
1374 __ jmpl(Lscratch, G0, O7); // and convert it
a61af66fc99e Initial load
duke
parents:
diff changeset
1375 __ delayed()->nop();
a61af66fc99e Initial load
duke
parents:
diff changeset
1376
a61af66fc99e Initial load
duke
parents:
diff changeset
1377 // L1_scratch points to top of stack (prepushed)
a61af66fc99e Initial load
duke
parents:
diff changeset
1378 __ st_ptr(L1_scratch, STATE(_stack));
a61af66fc99e Initial load
duke
parents:
diff changeset
1379 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1380
a61af66fc99e Initial load
duke
parents:
diff changeset
1381 // Generate the code to handle a more_monitors message from the c++ interpreter
a61af66fc99e Initial load
duke
parents:
diff changeset
1382 void CppInterpreterGenerator::generate_more_monitors() {
a61af66fc99e Initial load
duke
parents:
diff changeset
1383
a61af66fc99e Initial load
duke
parents:
diff changeset
1384 Label entry, loop;
a61af66fc99e Initial load
duke
parents:
diff changeset
1385 const int entry_size = frame::interpreter_frame_monitor_size() * wordSize;
a61af66fc99e Initial load
duke
parents:
diff changeset
1386 // 1. compute new pointers // esp: old expression stack top
a61af66fc99e Initial load
duke
parents:
diff changeset
1387 __ delayed()->ld_ptr(STATE(_stack_base), L4_scratch); // current expression stack bottom
a61af66fc99e Initial load
duke
parents:
diff changeset
1388 __ sub(L4_scratch, entry_size, L4_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
1389 __ st_ptr(L4_scratch, STATE(_stack_base));
a61af66fc99e Initial load
duke
parents:
diff changeset
1390
a61af66fc99e Initial load
duke
parents:
diff changeset
1391 __ sub(SP, entry_size, SP); // Grow stack
a61af66fc99e Initial load
duke
parents:
diff changeset
1392 __ st_ptr(SP, STATE(_frame_bottom));
a61af66fc99e Initial load
duke
parents:
diff changeset
1393
a61af66fc99e Initial load
duke
parents:
diff changeset
1394 __ ld_ptr(STATE(_stack_limit), L2_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
1395 __ sub(L2_scratch, entry_size, L2_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
1396 __ st_ptr(L2_scratch, STATE(_stack_limit));
a61af66fc99e Initial load
duke
parents:
diff changeset
1397
a61af66fc99e Initial load
duke
parents:
diff changeset
1398 __ ld_ptr(STATE(_stack), L1_scratch); // Get current stack top
a61af66fc99e Initial load
duke
parents:
diff changeset
1399 __ sub(L1_scratch, entry_size, L1_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
1400 __ st_ptr(L1_scratch, STATE(_stack));
a61af66fc99e Initial load
duke
parents:
diff changeset
1401 __ ba(false, entry);
a61af66fc99e Initial load
duke
parents:
diff changeset
1402 __ delayed()->add(L1_scratch, wordSize, L1_scratch); // first real entry (undo prepush)
a61af66fc99e Initial load
duke
parents:
diff changeset
1403
a61af66fc99e Initial load
duke
parents:
diff changeset
1404 // 2. move expression stack
a61af66fc99e Initial load
duke
parents:
diff changeset
1405
a61af66fc99e Initial load
duke
parents:
diff changeset
1406 __ bind(loop);
a61af66fc99e Initial load
duke
parents:
diff changeset
1407 __ st_ptr(L3_scratch, Address(L1_scratch, 0));
a61af66fc99e Initial load
duke
parents:
diff changeset
1408 __ add(L1_scratch, wordSize, L1_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
1409 __ bind(entry);
a61af66fc99e Initial load
duke
parents:
diff changeset
1410 __ cmp(L1_scratch, L4_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
1411 __ br(Assembler::notEqual, false, Assembler::pt, loop);
a61af66fc99e Initial load
duke
parents:
diff changeset
1412 __ delayed()->ld_ptr(L1_scratch, entry_size, L3_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
1413
a61af66fc99e Initial load
duke
parents:
diff changeset
1414 // now zero the slot so we can find it.
123
9e5a7340635e 6688137: c++ interpreter fails on 64bit sparc
sgoldman
parents: 0
diff changeset
1415 __ st_ptr(G0, L4_scratch, BasicObjectLock::obj_offset_in_bytes());
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1416
a61af66fc99e Initial load
duke
parents:
diff changeset
1417 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1418
a61af66fc99e Initial load
duke
parents:
diff changeset
1419 // Initial entry to C++ interpreter from the call_stub.
a61af66fc99e Initial load
duke
parents:
diff changeset
1420 // This entry point is called the frame manager since it handles the generation
a61af66fc99e Initial load
duke
parents:
diff changeset
1421 // of interpreter activation frames via requests directly from the vm (via call_stub)
a61af66fc99e Initial load
duke
parents:
diff changeset
1422 // and via requests from the interpreter. The requests from the call_stub happen
a61af66fc99e Initial load
duke
parents:
diff changeset
1423 // directly thru the entry point. Requests from the interpreter happen via returning
a61af66fc99e Initial load
duke
parents:
diff changeset
1424 // from the interpreter and examining the message the interpreter has returned to
a61af66fc99e Initial load
duke
parents:
diff changeset
1425 // the frame manager. The frame manager can take the following requests:
a61af66fc99e Initial load
duke
parents:
diff changeset
1426
a61af66fc99e Initial load
duke
parents:
diff changeset
1427 // NO_REQUEST - error, should never happen.
a61af66fc99e Initial load
duke
parents:
diff changeset
1428 // MORE_MONITORS - need a new monitor. Shuffle the expression stack on down and
a61af66fc99e Initial load
duke
parents:
diff changeset
1429 // allocate a new monitor.
a61af66fc99e Initial load
duke
parents:
diff changeset
1430 // CALL_METHOD - setup a new activation to call a new method. Very similar to what
a61af66fc99e Initial load
duke
parents:
diff changeset
1431 // happens during entry during the entry via the call stub.
a61af66fc99e Initial load
duke
parents:
diff changeset
1432 // RETURN_FROM_METHOD - remove an activation. Return to interpreter or call stub.
a61af66fc99e Initial load
duke
parents:
diff changeset
1433 //
a61af66fc99e Initial load
duke
parents:
diff changeset
1434 // Arguments:
a61af66fc99e Initial load
duke
parents:
diff changeset
1435 //
a61af66fc99e Initial load
duke
parents:
diff changeset
1436 // ebx: methodOop
a61af66fc99e Initial load
duke
parents:
diff changeset
1437 // ecx: receiver - unused (retrieved from stack as needed)
a61af66fc99e Initial load
duke
parents:
diff changeset
1438 // esi: previous frame manager state (NULL from the call_stub/c1/c2)
a61af66fc99e Initial load
duke
parents:
diff changeset
1439 //
a61af66fc99e Initial load
duke
parents:
diff changeset
1440 //
a61af66fc99e Initial load
duke
parents:
diff changeset
1441 // Stack layout at entry
a61af66fc99e Initial load
duke
parents:
diff changeset
1442 //
a61af66fc99e Initial load
duke
parents:
diff changeset
1443 // [ return address ] <--- esp
a61af66fc99e Initial load
duke
parents:
diff changeset
1444 // [ parameter n ]
a61af66fc99e Initial load
duke
parents:
diff changeset
1445 // ...
a61af66fc99e Initial load
duke
parents:
diff changeset
1446 // [ parameter 1 ]
a61af66fc99e Initial load
duke
parents:
diff changeset
1447 // [ expression stack ]
a61af66fc99e Initial load
duke
parents:
diff changeset
1448 //
a61af66fc99e Initial load
duke
parents:
diff changeset
1449 //
a61af66fc99e Initial load
duke
parents:
diff changeset
1450 // We are free to blow any registers we like because the call_stub which brought us here
a61af66fc99e Initial load
duke
parents:
diff changeset
1451 // initially has preserved the callee save registers already.
a61af66fc99e Initial load
duke
parents:
diff changeset
1452 //
a61af66fc99e Initial load
duke
parents:
diff changeset
1453 //
a61af66fc99e Initial load
duke
parents:
diff changeset
1454
a61af66fc99e Initial load
duke
parents:
diff changeset
1455 static address interpreter_frame_manager = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
1456
a61af66fc99e Initial load
duke
parents:
diff changeset
1457 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
1458 #define VALIDATE_STATE(scratch, marker) \
a61af66fc99e Initial load
duke
parents:
diff changeset
1459 { \
a61af66fc99e Initial load
duke
parents:
diff changeset
1460 Label skip; \
a61af66fc99e Initial load
duke
parents:
diff changeset
1461 __ ld_ptr(STATE(_self_link), scratch); \
a61af66fc99e Initial load
duke
parents:
diff changeset
1462 __ cmp(Lstate, scratch); \
a61af66fc99e Initial load
duke
parents:
diff changeset
1463 __ brx(Assembler::equal, false, Assembler::pt, skip); \
a61af66fc99e Initial load
duke
parents:
diff changeset
1464 __ delayed()->nop(); \
a61af66fc99e Initial load
duke
parents:
diff changeset
1465 __ breakpoint_trap(); \
a61af66fc99e Initial load
duke
parents:
diff changeset
1466 __ emit_long(marker); \
a61af66fc99e Initial load
duke
parents:
diff changeset
1467 __ bind(skip); \
a61af66fc99e Initial load
duke
parents:
diff changeset
1468 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1469 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
1470 #define VALIDATE_STATE(scratch, marker)
a61af66fc99e Initial load
duke
parents:
diff changeset
1471 #endif /* ASSERT */
a61af66fc99e Initial load
duke
parents:
diff changeset
1472
a61af66fc99e Initial load
duke
parents:
diff changeset
1473 void CppInterpreterGenerator::adjust_callers_stack(Register args) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1474 //
a61af66fc99e Initial load
duke
parents:
diff changeset
1475 // Adjust caller's stack so that all the locals can be contiguous with
a61af66fc99e Initial load
duke
parents:
diff changeset
1476 // the parameters.
a61af66fc99e Initial load
duke
parents:
diff changeset
1477 // Worries about stack overflow make this a pain.
a61af66fc99e Initial load
duke
parents:
diff changeset
1478 //
a61af66fc99e Initial load
duke
parents:
diff changeset
1479 // Destroys args, G3_scratch, G3_scratch
a61af66fc99e Initial load
duke
parents:
diff changeset
1480 // In/Out O5_savedSP (sender's original SP)
a61af66fc99e Initial load
duke
parents:
diff changeset
1481 //
a61af66fc99e Initial load
duke
parents:
diff changeset
1482 // assert_different_registers(state, prev_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
1483 const Register Gtmp = G3_scratch;
a61af66fc99e Initial load
duke
parents:
diff changeset
1484 const Register tmp = O2;
a61af66fc99e Initial load
duke
parents:
diff changeset
1485 const Address size_of_parameters(G5_method, 0, in_bytes(methodOopDesc::size_of_parameters_offset()));
a61af66fc99e Initial load
duke
parents:
diff changeset
1486 const Address size_of_locals (G5_method, 0, in_bytes(methodOopDesc::size_of_locals_offset()));
a61af66fc99e Initial load
duke
parents:
diff changeset
1487
a61af66fc99e Initial load
duke
parents:
diff changeset
1488 __ lduh(size_of_parameters, tmp);
a61af66fc99e Initial load
duke
parents:
diff changeset
1489 __ sll(tmp, LogBytesPerWord, Gtmp); // parameter size in bytes
a61af66fc99e Initial load
duke
parents:
diff changeset
1490 __ add(args, Gtmp, Gargs); // points to first local + BytesPerWord
a61af66fc99e Initial load
duke
parents:
diff changeset
1491 // NEW
a61af66fc99e Initial load
duke
parents:
diff changeset
1492 __ add(Gargs, -wordSize, Gargs); // points to first local[0]
a61af66fc99e Initial load
duke
parents:
diff changeset
1493 // determine extra space for non-argument locals & adjust caller's SP
a61af66fc99e Initial load
duke
parents:
diff changeset
1494 // Gtmp1: parameter size in words
a61af66fc99e Initial load
duke
parents:
diff changeset
1495 __ lduh(size_of_locals, Gtmp);
a61af66fc99e Initial load
duke
parents:
diff changeset
1496 __ compute_extra_locals_size_in_bytes(tmp, Gtmp, Gtmp);
a61af66fc99e Initial load
duke
parents:
diff changeset
1497
a61af66fc99e Initial load
duke
parents:
diff changeset
1498 #if 1
a61af66fc99e Initial load
duke
parents:
diff changeset
1499 // c2i adapters place the final interpreter argument in the register save area for O0/I0
a61af66fc99e Initial load
duke
parents:
diff changeset
1500 // the call_stub will place the final interpreter argument at
a61af66fc99e Initial load
duke
parents:
diff changeset
1501 // frame::memory_parameter_word_sp_offset. This is mostly not noticable for either asm
a61af66fc99e Initial load
duke
parents:
diff changeset
1502 // or c++ interpreter. However with the c++ interpreter when we do a recursive call
a61af66fc99e Initial load
duke
parents:
diff changeset
1503 // and try to make it look good in the debugger we will store the argument to
a61af66fc99e Initial load
duke
parents:
diff changeset
1504 // RecursiveInterpreterActivation in the register argument save area. Without allocating
a61af66fc99e Initial load
duke
parents:
diff changeset
1505 // extra space for the compiler this will overwrite locals in the local array of the
a61af66fc99e Initial load
duke
parents:
diff changeset
1506 // interpreter.
a61af66fc99e Initial load
duke
parents:
diff changeset
1507 // QQQ still needed with frameless adapters???
a61af66fc99e Initial load
duke
parents:
diff changeset
1508
a61af66fc99e Initial load
duke
parents:
diff changeset
1509 const int c2i_adjust_words = frame::memory_parameter_word_sp_offset - frame::callee_register_argument_save_area_sp_offset;
a61af66fc99e Initial load
duke
parents:
diff changeset
1510
a61af66fc99e Initial load
duke
parents:
diff changeset
1511 __ add(Gtmp, c2i_adjust_words*wordSize, Gtmp);
a61af66fc99e Initial load
duke
parents:
diff changeset
1512 #endif // 1
a61af66fc99e Initial load
duke
parents:
diff changeset
1513
a61af66fc99e Initial load
duke
parents:
diff changeset
1514
a61af66fc99e Initial load
duke
parents:
diff changeset
1515 __ sub(SP, Gtmp, SP); // just caller's frame for the additional space we need.
a61af66fc99e Initial load
duke
parents:
diff changeset
1516 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1517
a61af66fc99e Initial load
duke
parents:
diff changeset
1518 address InterpreterGenerator::generate_normal_entry(bool synchronized) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1519
a61af66fc99e Initial load
duke
parents:
diff changeset
1520 // G5_method: methodOop
a61af66fc99e Initial load
duke
parents:
diff changeset
1521 // G2_thread: thread (unused)
a61af66fc99e Initial load
duke
parents:
diff changeset
1522 // Gargs: bottom of args (sender_sp)
a61af66fc99e Initial load
duke
parents:
diff changeset
1523 // O5: sender's sp
a61af66fc99e Initial load
duke
parents:
diff changeset
1524
a61af66fc99e Initial load
duke
parents:
diff changeset
1525 // A single frame manager is plenty as we don't specialize for synchronized. We could and
a61af66fc99e Initial load
duke
parents:
diff changeset
1526 // the code is pretty much ready. Would need to change the test below and for good measure
a61af66fc99e Initial load
duke
parents:
diff changeset
1527 // modify generate_interpreter_state to only do the (pre) sync stuff stuff for synchronized
a61af66fc99e Initial load
duke
parents:
diff changeset
1528 // routines. Not clear this is worth it yet.
a61af66fc99e Initial load
duke
parents:
diff changeset
1529
a61af66fc99e Initial load
duke
parents:
diff changeset
1530 if (interpreter_frame_manager) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1531 return interpreter_frame_manager;
a61af66fc99e Initial load
duke
parents:
diff changeset
1532 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1533
a61af66fc99e Initial load
duke
parents:
diff changeset
1534 __ bind(frame_manager_entry);
a61af66fc99e Initial load
duke
parents:
diff changeset
1535
a61af66fc99e Initial load
duke
parents:
diff changeset
1536 // the following temporary registers are used during frame creation
a61af66fc99e Initial load
duke
parents:
diff changeset
1537 const Register Gtmp1 = G3_scratch;
a61af66fc99e Initial load
duke
parents:
diff changeset
1538 // const Register Lmirror = L1; // native mirror (native calls only)
a61af66fc99e Initial load
duke
parents:
diff changeset
1539
a61af66fc99e Initial load
duke
parents:
diff changeset
1540 const Address constants (G5_method, 0, in_bytes(methodOopDesc::constants_offset()));
a61af66fc99e Initial load
duke
parents:
diff changeset
1541 const Address access_flags (G5_method, 0, in_bytes(methodOopDesc::access_flags_offset()));
a61af66fc99e Initial load
duke
parents:
diff changeset
1542 const Address size_of_parameters(G5_method, 0, in_bytes(methodOopDesc::size_of_parameters_offset()));
a61af66fc99e Initial load
duke
parents:
diff changeset
1543 const Address max_stack (G5_method, 0, in_bytes(methodOopDesc::max_stack_offset()));
a61af66fc99e Initial load
duke
parents:
diff changeset
1544 const Address size_of_locals (G5_method, 0, in_bytes(methodOopDesc::size_of_locals_offset()));
a61af66fc99e Initial load
duke
parents:
diff changeset
1545
a61af66fc99e Initial load
duke
parents:
diff changeset
1546 address entry_point = __ pc();
a61af66fc99e Initial load
duke
parents:
diff changeset
1547 __ mov(G0, prevState); // no current activation
a61af66fc99e Initial load
duke
parents:
diff changeset
1548
a61af66fc99e Initial load
duke
parents:
diff changeset
1549
a61af66fc99e Initial load
duke
parents:
diff changeset
1550 Label re_dispatch;
a61af66fc99e Initial load
duke
parents:
diff changeset
1551
a61af66fc99e Initial load
duke
parents:
diff changeset
1552 __ bind(re_dispatch);
a61af66fc99e Initial load
duke
parents:
diff changeset
1553
a61af66fc99e Initial load
duke
parents:
diff changeset
1554 // Interpreter needs to have locals completely contiguous. In order to do that
a61af66fc99e Initial load
duke
parents:
diff changeset
1555 // We must adjust the caller's stack pointer for any locals beyond just the
a61af66fc99e Initial load
duke
parents:
diff changeset
1556 // parameters
a61af66fc99e Initial load
duke
parents:
diff changeset
1557 adjust_callers_stack(Gargs);
a61af66fc99e Initial load
duke
parents:
diff changeset
1558
a61af66fc99e Initial load
duke
parents:
diff changeset
1559 // O5_savedSP still contains sender's sp
a61af66fc99e Initial load
duke
parents:
diff changeset
1560
a61af66fc99e Initial load
duke
parents:
diff changeset
1561 // NEW FRAME
a61af66fc99e Initial load
duke
parents:
diff changeset
1562
a61af66fc99e Initial load
duke
parents:
diff changeset
1563 generate_compute_interpreter_state(Lstate, prevState, false);
a61af66fc99e Initial load
duke
parents:
diff changeset
1564
a61af66fc99e Initial load
duke
parents:
diff changeset
1565 // At this point a new interpreter frame and state object are created and initialized
a61af66fc99e Initial load
duke
parents:
diff changeset
1566 // Lstate has the pointer to the new activation
a61af66fc99e Initial load
duke
parents:
diff changeset
1567 // Any stack banging or limit check should already be done.
a61af66fc99e Initial load
duke
parents:
diff changeset
1568
a61af66fc99e Initial load
duke
parents:
diff changeset
1569 Label call_interpreter;
a61af66fc99e Initial load
duke
parents:
diff changeset
1570
a61af66fc99e Initial load
duke
parents:
diff changeset
1571 __ bind(call_interpreter);
a61af66fc99e Initial load
duke
parents:
diff changeset
1572
a61af66fc99e Initial load
duke
parents:
diff changeset
1573
a61af66fc99e Initial load
duke
parents:
diff changeset
1574 #if 1
a61af66fc99e Initial load
duke
parents:
diff changeset
1575 __ set(0xdead002, Lmirror);
a61af66fc99e Initial load
duke
parents:
diff changeset
1576 __ set(0xdead002, L2_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
1577 __ set(0xdead003, L3_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
1578 __ set(0xdead004, L4_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
1579 __ set(0xdead005, Lscratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
1580 __ set(0xdead006, Lscratch2);
a61af66fc99e Initial load
duke
parents:
diff changeset
1581 __ set(0xdead007, L7_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
1582
a61af66fc99e Initial load
duke
parents:
diff changeset
1583 __ set(0xdeaf002, O2);
a61af66fc99e Initial load
duke
parents:
diff changeset
1584 __ set(0xdeaf003, O3);
a61af66fc99e Initial load
duke
parents:
diff changeset
1585 __ set(0xdeaf004, O4);
a61af66fc99e Initial load
duke
parents:
diff changeset
1586 __ set(0xdeaf005, O5);
a61af66fc99e Initial load
duke
parents:
diff changeset
1587 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
1588
a61af66fc99e Initial load
duke
parents:
diff changeset
1589 // Call interpreter (stack bang complete) enter here if message is
a61af66fc99e Initial load
duke
parents:
diff changeset
1590 // set and we know stack size is valid
a61af66fc99e Initial load
duke
parents:
diff changeset
1591
a61af66fc99e Initial load
duke
parents:
diff changeset
1592 Label call_interpreter_2;
a61af66fc99e Initial load
duke
parents:
diff changeset
1593
a61af66fc99e Initial load
duke
parents:
diff changeset
1594 __ bind(call_interpreter_2);
a61af66fc99e Initial load
duke
parents:
diff changeset
1595
a61af66fc99e Initial load
duke
parents:
diff changeset
1596 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
1597 {
a61af66fc99e Initial load
duke
parents:
diff changeset
1598 Label skip;
a61af66fc99e Initial load
duke
parents:
diff changeset
1599 __ ld_ptr(STATE(_frame_bottom), G3_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
1600 __ cmp(G3_scratch, SP);
a61af66fc99e Initial load
duke
parents:
diff changeset
1601 __ brx(Assembler::equal, false, Assembler::pt, skip);
a61af66fc99e Initial load
duke
parents:
diff changeset
1602 __ delayed()->nop();
a61af66fc99e Initial load
duke
parents:
diff changeset
1603 __ stop("SP not restored to frame bottom");
a61af66fc99e Initial load
duke
parents:
diff changeset
1604 __ bind(skip);
a61af66fc99e Initial load
duke
parents:
diff changeset
1605 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1606 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
1607
a61af66fc99e Initial load
duke
parents:
diff changeset
1608 VALIDATE_STATE(G3_scratch, 4);
a61af66fc99e Initial load
duke
parents:
diff changeset
1609 __ set_last_Java_frame(SP, noreg);
a61af66fc99e Initial load
duke
parents:
diff changeset
1610 __ mov(Lstate, O0); // (arg) pointer to current state
a61af66fc99e Initial load
duke
parents:
diff changeset
1611
a61af66fc99e Initial load
duke
parents:
diff changeset
1612 __ call(CAST_FROM_FN_PTR(address,
a61af66fc99e Initial load
duke
parents:
diff changeset
1613 JvmtiExport::can_post_interpreter_events() ?
a61af66fc99e Initial load
duke
parents:
diff changeset
1614 BytecodeInterpreter::runWithChecks
a61af66fc99e Initial load
duke
parents:
diff changeset
1615 : BytecodeInterpreter::run),
a61af66fc99e Initial load
duke
parents:
diff changeset
1616 relocInfo::runtime_call_type);
a61af66fc99e Initial load
duke
parents:
diff changeset
1617
a61af66fc99e Initial load
duke
parents:
diff changeset
1618 __ delayed()->nop();
a61af66fc99e Initial load
duke
parents:
diff changeset
1619
a61af66fc99e Initial load
duke
parents:
diff changeset
1620 __ ld_ptr(STATE(_thread), G2_thread);
a61af66fc99e Initial load
duke
parents:
diff changeset
1621 __ reset_last_Java_frame();
a61af66fc99e Initial load
duke
parents:
diff changeset
1622
a61af66fc99e Initial load
duke
parents:
diff changeset
1623 // examine msg from interpreter to determine next action
a61af66fc99e Initial load
duke
parents:
diff changeset
1624 __ ld_ptr(STATE(_thread), G2_thread); // restore G2_thread
a61af66fc99e Initial load
duke
parents:
diff changeset
1625
a61af66fc99e Initial load
duke
parents:
diff changeset
1626 __ ld(STATE(_msg), L1_scratch); // Get new message
a61af66fc99e Initial load
duke
parents:
diff changeset
1627
a61af66fc99e Initial load
duke
parents:
diff changeset
1628 Label call_method;
a61af66fc99e Initial load
duke
parents:
diff changeset
1629 Label return_from_interpreted_method;
a61af66fc99e Initial load
duke
parents:
diff changeset
1630 Label throw_exception;
a61af66fc99e Initial load
duke
parents:
diff changeset
1631 Label do_OSR;
a61af66fc99e Initial load
duke
parents:
diff changeset
1632 Label bad_msg;
a61af66fc99e Initial load
duke
parents:
diff changeset
1633 Label resume_interpreter;
a61af66fc99e Initial load
duke
parents:
diff changeset
1634
a61af66fc99e Initial load
duke
parents:
diff changeset
1635 __ cmp(L1_scratch, (int)BytecodeInterpreter::call_method);
a61af66fc99e Initial load
duke
parents:
diff changeset
1636 __ br(Assembler::equal, false, Assembler::pt, call_method);
a61af66fc99e Initial load
duke
parents:
diff changeset
1637 __ delayed()->cmp(L1_scratch, (int)BytecodeInterpreter::return_from_method);
a61af66fc99e Initial load
duke
parents:
diff changeset
1638 __ br(Assembler::equal, false, Assembler::pt, return_from_interpreted_method);
a61af66fc99e Initial load
duke
parents:
diff changeset
1639 __ delayed()->cmp(L1_scratch, (int)BytecodeInterpreter::throwing_exception);
a61af66fc99e Initial load
duke
parents:
diff changeset
1640 __ br(Assembler::equal, false, Assembler::pt, throw_exception);
a61af66fc99e Initial load
duke
parents:
diff changeset
1641 __ delayed()->cmp(L1_scratch, (int)BytecodeInterpreter::do_osr);
a61af66fc99e Initial load
duke
parents:
diff changeset
1642 __ br(Assembler::equal, false, Assembler::pt, do_OSR);
a61af66fc99e Initial load
duke
parents:
diff changeset
1643 __ delayed()->cmp(L1_scratch, (int)BytecodeInterpreter::more_monitors);
a61af66fc99e Initial load
duke
parents:
diff changeset
1644 __ br(Assembler::notEqual, false, Assembler::pt, bad_msg);
a61af66fc99e Initial load
duke
parents:
diff changeset
1645
a61af66fc99e Initial load
duke
parents:
diff changeset
1646 // Allocate more monitor space, shuffle expression stack....
a61af66fc99e Initial load
duke
parents:
diff changeset
1647
a61af66fc99e Initial load
duke
parents:
diff changeset
1648 generate_more_monitors();
a61af66fc99e Initial load
duke
parents:
diff changeset
1649
a61af66fc99e Initial load
duke
parents:
diff changeset
1650 // new monitor slot allocated, resume the interpreter.
a61af66fc99e Initial load
duke
parents:
diff changeset
1651
a61af66fc99e Initial load
duke
parents:
diff changeset
1652 __ set((int)BytecodeInterpreter::got_monitors, L1_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
1653 VALIDATE_STATE(G3_scratch, 5);
a61af66fc99e Initial load
duke
parents:
diff changeset
1654 __ ba(false, call_interpreter);
a61af66fc99e Initial load
duke
parents:
diff changeset
1655 __ delayed()->st(L1_scratch, STATE(_msg));
a61af66fc99e Initial load
duke
parents:
diff changeset
1656
a61af66fc99e Initial load
duke
parents:
diff changeset
1657 // uncommon trap needs to jump to here to enter the interpreter (re-execute current bytecode)
a61af66fc99e Initial load
duke
parents:
diff changeset
1658 unctrap_frame_manager_entry = __ pc();
a61af66fc99e Initial load
duke
parents:
diff changeset
1659
a61af66fc99e Initial load
duke
parents:
diff changeset
1660 // QQQ what message do we send
a61af66fc99e Initial load
duke
parents:
diff changeset
1661
a61af66fc99e Initial load
duke
parents:
diff changeset
1662 __ ba(false, call_interpreter);
a61af66fc99e Initial load
duke
parents:
diff changeset
1663 __ delayed()->ld_ptr(STATE(_frame_bottom), SP); // restore to full stack frame
a61af66fc99e Initial load
duke
parents:
diff changeset
1664
a61af66fc99e Initial load
duke
parents:
diff changeset
1665 //=============================================================================
a61af66fc99e Initial load
duke
parents:
diff changeset
1666 // Returning from a compiled method into a deopted method. The bytecode at the
a61af66fc99e Initial load
duke
parents:
diff changeset
1667 // bcp has completed. The result of the bytecode is in the native abi (the tosca
a61af66fc99e Initial load
duke
parents:
diff changeset
1668 // for the template based interpreter). Any stack space that was used by the
a61af66fc99e Initial load
duke
parents:
diff changeset
1669 // bytecode that has completed has been removed (e.g. parameters for an invoke)
a61af66fc99e Initial load
duke
parents:
diff changeset
1670 // so all that we have to do is place any pending result on the expression stack
a61af66fc99e Initial load
duke
parents:
diff changeset
1671 // and resume execution on the next bytecode.
a61af66fc99e Initial load
duke
parents:
diff changeset
1672
a61af66fc99e Initial load
duke
parents:
diff changeset
1673 generate_deopt_handling();
a61af66fc99e Initial load
duke
parents:
diff changeset
1674
a61af66fc99e Initial load
duke
parents:
diff changeset
1675 // ready to resume the interpreter
a61af66fc99e Initial load
duke
parents:
diff changeset
1676
a61af66fc99e Initial load
duke
parents:
diff changeset
1677 __ set((int)BytecodeInterpreter::deopt_resume, L1_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
1678 __ ba(false, call_interpreter);
a61af66fc99e Initial load
duke
parents:
diff changeset
1679 __ delayed()->st(L1_scratch, STATE(_msg));
a61af66fc99e Initial load
duke
parents:
diff changeset
1680
a61af66fc99e Initial load
duke
parents:
diff changeset
1681 // Current frame has caught an exception we need to dispatch to the
a61af66fc99e Initial load
duke
parents:
diff changeset
1682 // handler. We can get here because a native interpreter frame caught
a61af66fc99e Initial load
duke
parents:
diff changeset
1683 // an exception in which case there is no handler and we must rethrow
a61af66fc99e Initial load
duke
parents:
diff changeset
1684 // If it is a vanilla interpreted frame the we simply drop into the
a61af66fc99e Initial load
duke
parents:
diff changeset
1685 // interpreter and let it do the lookup.
a61af66fc99e Initial load
duke
parents:
diff changeset
1686
a61af66fc99e Initial load
duke
parents:
diff changeset
1687 Interpreter::_rethrow_exception_entry = __ pc();
a61af66fc99e Initial load
duke
parents:
diff changeset
1688
a61af66fc99e Initial load
duke
parents:
diff changeset
1689 Label return_with_exception;
a61af66fc99e Initial load
duke
parents:
diff changeset
1690 Label unwind_and_forward;
a61af66fc99e Initial load
duke
parents:
diff changeset
1691
a61af66fc99e Initial load
duke
parents:
diff changeset
1692 // O0: exception
a61af66fc99e Initial load
duke
parents:
diff changeset
1693 // O7: throwing pc
a61af66fc99e Initial load
duke
parents:
diff changeset
1694
a61af66fc99e Initial load
duke
parents:
diff changeset
1695 // We want exception in the thread no matter what we ultimately decide about frame type.
a61af66fc99e Initial load
duke
parents:
diff changeset
1696
a61af66fc99e Initial load
duke
parents:
diff changeset
1697 Address exception_addr (G2_thread, 0, in_bytes(Thread::pending_exception_offset()));
a61af66fc99e Initial load
duke
parents:
diff changeset
1698 __ verify_thread();
a61af66fc99e Initial load
duke
parents:
diff changeset
1699 __ st_ptr(O0, exception_addr);
a61af66fc99e Initial load
duke
parents:
diff changeset
1700
a61af66fc99e Initial load
duke
parents:
diff changeset
1701 // get the methodOop
a61af66fc99e Initial load
duke
parents:
diff changeset
1702 __ ld_ptr(STATE(_method), G5_method);
a61af66fc99e Initial load
duke
parents:
diff changeset
1703
a61af66fc99e Initial load
duke
parents:
diff changeset
1704 // if this current frame vanilla or native?
a61af66fc99e Initial load
duke
parents:
diff changeset
1705
a61af66fc99e Initial load
duke
parents:
diff changeset
1706 __ ld(access_flags, Gtmp1);
a61af66fc99e Initial load
duke
parents:
diff changeset
1707 __ btst(JVM_ACC_NATIVE, Gtmp1);
a61af66fc99e Initial load
duke
parents:
diff changeset
1708 __ br(Assembler::zero, false, Assembler::pt, return_with_exception); // vanilla interpreted frame handle directly
a61af66fc99e Initial load
duke
parents:
diff changeset
1709 __ delayed()->nop();
a61af66fc99e Initial load
duke
parents:
diff changeset
1710
a61af66fc99e Initial load
duke
parents:
diff changeset
1711 // We drop thru to unwind a native interpreted frame with a pending exception
a61af66fc99e Initial load
duke
parents:
diff changeset
1712 // We jump here for the initial interpreter frame with exception pending
a61af66fc99e Initial load
duke
parents:
diff changeset
1713 // We unwind the current acivation and forward it to our caller.
a61af66fc99e Initial load
duke
parents:
diff changeset
1714
a61af66fc99e Initial load
duke
parents:
diff changeset
1715 __ bind(unwind_and_forward);
a61af66fc99e Initial load
duke
parents:
diff changeset
1716
a61af66fc99e Initial load
duke
parents:
diff changeset
1717 // Unwind frame and jump to forward exception. unwinding will place throwing pc in O7
a61af66fc99e Initial load
duke
parents:
diff changeset
1718 // as expected by forward_exception.
a61af66fc99e Initial load
duke
parents:
diff changeset
1719
a61af66fc99e Initial load
duke
parents:
diff changeset
1720 __ restore(FP, G0, SP); // unwind interpreter state frame
a61af66fc99e Initial load
duke
parents:
diff changeset
1721 __ br(Assembler::always, false, Assembler::pt, StubRoutines::forward_exception_entry(), relocInfo::runtime_call_type);
a61af66fc99e Initial load
duke
parents:
diff changeset
1722 __ delayed()->mov(I5_savedSP->after_restore(), SP);
a61af66fc99e Initial load
duke
parents:
diff changeset
1723
a61af66fc99e Initial load
duke
parents:
diff changeset
1724 // Return point from a call which returns a result in the native abi
a61af66fc99e Initial load
duke
parents:
diff changeset
1725 // (c1/c2/jni-native). This result must be processed onto the java
a61af66fc99e Initial load
duke
parents:
diff changeset
1726 // expression stack.
a61af66fc99e Initial load
duke
parents:
diff changeset
1727 //
a61af66fc99e Initial load
duke
parents:
diff changeset
1728 // A pending exception may be present in which case there is no result present
a61af66fc99e Initial load
duke
parents:
diff changeset
1729
a61af66fc99e Initial load
duke
parents:
diff changeset
1730 address return_from_native_method = __ pc();
a61af66fc99e Initial load
duke
parents:
diff changeset
1731
a61af66fc99e Initial load
duke
parents:
diff changeset
1732 VALIDATE_STATE(G3_scratch, 6);
a61af66fc99e Initial load
duke
parents:
diff changeset
1733
a61af66fc99e Initial load
duke
parents:
diff changeset
1734 // Result if any is in native abi result (O0..O1/F0..F1). The java expression
a61af66fc99e Initial load
duke
parents:
diff changeset
1735 // stack is in the state that the calling convention left it.
a61af66fc99e Initial load
duke
parents:
diff changeset
1736 // Copy the result from native abi result and place it on java expression stack.
a61af66fc99e Initial load
duke
parents:
diff changeset
1737
a61af66fc99e Initial load
duke
parents:
diff changeset
1738 // Current interpreter state is present in Lstate
a61af66fc99e Initial load
duke
parents:
diff changeset
1739
a61af66fc99e Initial load
duke
parents:
diff changeset
1740 // Exception pending?
a61af66fc99e Initial load
duke
parents:
diff changeset
1741
a61af66fc99e Initial load
duke
parents:
diff changeset
1742 __ ld_ptr(STATE(_frame_bottom), SP); // restore to full stack frame
a61af66fc99e Initial load
duke
parents:
diff changeset
1743 __ ld_ptr(exception_addr, Lscratch); // get any pending exception
a61af66fc99e Initial load
duke
parents:
diff changeset
1744 __ tst(Lscratch); // exception pending?
a61af66fc99e Initial load
duke
parents:
diff changeset
1745 __ brx(Assembler::notZero, false, Assembler::pt, return_with_exception);
a61af66fc99e Initial load
duke
parents:
diff changeset
1746 __ delayed()->nop();
a61af66fc99e Initial load
duke
parents:
diff changeset
1747
a61af66fc99e Initial load
duke
parents:
diff changeset
1748 // Process the native abi result to java expression stack
a61af66fc99e Initial load
duke
parents:
diff changeset
1749
a61af66fc99e Initial load
duke
parents:
diff changeset
1750 __ ld_ptr(STATE(_result._to_call._callee), L4_scratch); // called method
a61af66fc99e Initial load
duke
parents:
diff changeset
1751 __ ld_ptr(STATE(_stack), L1_scratch); // get top of java expr stack
a61af66fc99e Initial load
duke
parents:
diff changeset
1752 __ lduh(L4_scratch, in_bytes(methodOopDesc::size_of_parameters_offset()), L2_scratch); // get parameter size
a61af66fc99e Initial load
duke
parents:
diff changeset
1753 __ sll(L2_scratch, LogBytesPerWord, L2_scratch ); // parameter size in bytes
a61af66fc99e Initial load
duke
parents:
diff changeset
1754 __ add(L1_scratch, L2_scratch, L1_scratch); // stack destination for result
123
9e5a7340635e 6688137: c++ interpreter fails on 64bit sparc
sgoldman
parents: 0
diff changeset
1755 __ ld(L4_scratch, in_bytes(methodOopDesc::result_index_offset()), L3_scratch); // called method result type index
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1756
a61af66fc99e Initial load
duke
parents:
diff changeset
1757 // tosca is really just native abi
a61af66fc99e Initial load
duke
parents:
diff changeset
1758 __ set((intptr_t)CppInterpreter::_tosca_to_stack, L4_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
1759 __ sll(L3_scratch, LogBytesPerWord, L3_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
1760 __ ld_ptr(L4_scratch, L3_scratch, Lscratch); // get typed result converter address
a61af66fc99e Initial load
duke
parents:
diff changeset
1761 __ jmpl(Lscratch, G0, O7); // and convert it
a61af66fc99e Initial load
duke
parents:
diff changeset
1762 __ delayed()->nop();
a61af66fc99e Initial load
duke
parents:
diff changeset
1763
a61af66fc99e Initial load
duke
parents:
diff changeset
1764 // L1_scratch points to top of stack (prepushed)
a61af66fc99e Initial load
duke
parents:
diff changeset
1765
a61af66fc99e Initial load
duke
parents:
diff changeset
1766 __ ba(false, resume_interpreter);
a61af66fc99e Initial load
duke
parents:
diff changeset
1767 __ delayed()->mov(L1_scratch, O1);
a61af66fc99e Initial load
duke
parents:
diff changeset
1768
a61af66fc99e Initial load
duke
parents:
diff changeset
1769 // An exception is being caught on return to a vanilla interpreter frame.
a61af66fc99e Initial load
duke
parents:
diff changeset
1770 // Empty the stack and resume interpreter
a61af66fc99e Initial load
duke
parents:
diff changeset
1771
a61af66fc99e Initial load
duke
parents:
diff changeset
1772 __ bind(return_with_exception);
a61af66fc99e Initial load
duke
parents:
diff changeset
1773
a61af66fc99e Initial load
duke
parents:
diff changeset
1774 __ ld_ptr(STATE(_frame_bottom), SP); // restore to full stack frame
a61af66fc99e Initial load
duke
parents:
diff changeset
1775 __ ld_ptr(STATE(_stack_base), O1); // empty java expression stack
a61af66fc99e Initial load
duke
parents:
diff changeset
1776 __ ba(false, resume_interpreter);
a61af66fc99e Initial load
duke
parents:
diff changeset
1777 __ delayed()->sub(O1, wordSize, O1); // account for prepush
a61af66fc99e Initial load
duke
parents:
diff changeset
1778
a61af66fc99e Initial load
duke
parents:
diff changeset
1779 // Return from interpreted method we return result appropriate to the caller (i.e. "recursive"
a61af66fc99e Initial load
duke
parents:
diff changeset
1780 // interpreter call, or native) and unwind this interpreter activation.
a61af66fc99e Initial load
duke
parents:
diff changeset
1781 // All monitors should be unlocked.
a61af66fc99e Initial load
duke
parents:
diff changeset
1782
a61af66fc99e Initial load
duke
parents:
diff changeset
1783 __ bind(return_from_interpreted_method);
a61af66fc99e Initial load
duke
parents:
diff changeset
1784
a61af66fc99e Initial load
duke
parents:
diff changeset
1785 VALIDATE_STATE(G3_scratch, 7);
a61af66fc99e Initial load
duke
parents:
diff changeset
1786
a61af66fc99e Initial load
duke
parents:
diff changeset
1787 Label return_to_initial_caller;
a61af66fc99e Initial load
duke
parents:
diff changeset
1788
a61af66fc99e Initial load
duke
parents:
diff changeset
1789 // Interpreted result is on the top of the completed activation expression stack.
a61af66fc99e Initial load
duke
parents:
diff changeset
1790 // We must return it to the top of the callers stack if caller was interpreted
a61af66fc99e Initial load
duke
parents:
diff changeset
1791 // otherwise we convert to native abi result and return to call_stub/c1/c2
a61af66fc99e Initial load
duke
parents:
diff changeset
1792 // The caller's expression stack was truncated by the call however the current activation
a61af66fc99e Initial load
duke
parents:
diff changeset
1793 // has enough stuff on the stack that we have usable space there no matter what. The
a61af66fc99e Initial load
duke
parents:
diff changeset
1794 // other thing that makes it easy is that the top of the caller's stack is stored in STATE(_locals)
a61af66fc99e Initial load
duke
parents:
diff changeset
1795 // for the current activation
a61af66fc99e Initial load
duke
parents:
diff changeset
1796
a61af66fc99e Initial load
duke
parents:
diff changeset
1797 __ ld_ptr(STATE(_prev_link), L1_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
1798 __ ld_ptr(STATE(_method), L2_scratch); // get method just executed
123
9e5a7340635e 6688137: c++ interpreter fails on 64bit sparc
sgoldman
parents: 0
diff changeset
1799 __ ld(L2_scratch, in_bytes(methodOopDesc::result_index_offset()), L2_scratch);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1800 __ tst(L1_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
1801 __ brx(Assembler::zero, false, Assembler::pt, return_to_initial_caller);
a61af66fc99e Initial load
duke
parents:
diff changeset
1802 __ delayed()->sll(L2_scratch, LogBytesPerWord, L2_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
1803
a61af66fc99e Initial load
duke
parents:
diff changeset
1804 // Copy result to callers java stack
a61af66fc99e Initial load
duke
parents:
diff changeset
1805
a61af66fc99e Initial load
duke
parents:
diff changeset
1806 __ set((intptr_t)CppInterpreter::_stack_to_stack, L4_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
1807 __ ld_ptr(L4_scratch, L2_scratch, Lscratch); // get typed result converter address
a61af66fc99e Initial load
duke
parents:
diff changeset
1808 __ ld_ptr(STATE(_stack), O0); // current top (prepushed)
a61af66fc99e Initial load
duke
parents:
diff changeset
1809 __ ld_ptr(STATE(_locals), O1); // stack destination
a61af66fc99e Initial load
duke
parents:
diff changeset
1810
a61af66fc99e Initial load
duke
parents:
diff changeset
1811 // O0 - will be source, O1 - will be destination (preserved)
a61af66fc99e Initial load
duke
parents:
diff changeset
1812 __ jmpl(Lscratch, G0, O7); // and convert it
a61af66fc99e Initial load
duke
parents:
diff changeset
1813 __ delayed()->add(O0, wordSize, O0); // get source (top of current expr stack)
a61af66fc99e Initial load
duke
parents:
diff changeset
1814
a61af66fc99e Initial load
duke
parents:
diff changeset
1815 // O1 == &locals[0]
a61af66fc99e Initial load
duke
parents:
diff changeset
1816
a61af66fc99e Initial load
duke
parents:
diff changeset
1817 // Result is now on caller's stack. Just unwind current activation and resume
a61af66fc99e Initial load
duke
parents:
diff changeset
1818
a61af66fc99e Initial load
duke
parents:
diff changeset
1819 Label unwind_recursive_activation;
a61af66fc99e Initial load
duke
parents:
diff changeset
1820
a61af66fc99e Initial load
duke
parents:
diff changeset
1821
a61af66fc99e Initial load
duke
parents:
diff changeset
1822 __ bind(unwind_recursive_activation);
a61af66fc99e Initial load
duke
parents:
diff changeset
1823
a61af66fc99e Initial load
duke
parents:
diff changeset
1824 // O1 == &locals[0] (really callers stacktop) for activation now returning
a61af66fc99e Initial load
duke
parents:
diff changeset
1825 // returning to interpreter method from "recursive" interpreter call
a61af66fc99e Initial load
duke
parents:
diff changeset
1826 // result converter left O1 pointing to top of the( prepushed) java stack for method we are returning
a61af66fc99e Initial load
duke
parents:
diff changeset
1827 // to. Now all we must do is unwind the state from the completed call
a61af66fc99e Initial load
duke
parents:
diff changeset
1828
a61af66fc99e Initial load
duke
parents:
diff changeset
1829 // Must restore stack
a61af66fc99e Initial load
duke
parents:
diff changeset
1830 VALIDATE_STATE(G3_scratch, 8);
a61af66fc99e Initial load
duke
parents:
diff changeset
1831
a61af66fc99e Initial load
duke
parents:
diff changeset
1832 // Return to interpreter method after a method call (interpreted/native/c1/c2) has completed.
a61af66fc99e Initial load
duke
parents:
diff changeset
1833 // Result if any is already on the caller's stack. All we must do now is remove the now dead
a61af66fc99e Initial load
duke
parents:
diff changeset
1834 // frame and tell interpreter to resume.
a61af66fc99e Initial load
duke
parents:
diff changeset
1835
a61af66fc99e Initial load
duke
parents:
diff changeset
1836
a61af66fc99e Initial load
duke
parents:
diff changeset
1837 __ mov(O1, I1); // pass back new stack top across activation
a61af66fc99e Initial load
duke
parents:
diff changeset
1838 // POP FRAME HERE ==================================
a61af66fc99e Initial load
duke
parents:
diff changeset
1839 __ restore(FP, G0, SP); // unwind interpreter state frame
a61af66fc99e Initial load
duke
parents:
diff changeset
1840 __ ld_ptr(STATE(_frame_bottom), SP); // restore to full stack frame
a61af66fc99e Initial load
duke
parents:
diff changeset
1841
a61af66fc99e Initial load
duke
parents:
diff changeset
1842
a61af66fc99e Initial load
duke
parents:
diff changeset
1843 // Resume the interpreter. The current frame contains the current interpreter
a61af66fc99e Initial load
duke
parents:
diff changeset
1844 // state object.
a61af66fc99e Initial load
duke
parents:
diff changeset
1845 //
a61af66fc99e Initial load
duke
parents:
diff changeset
1846 // O1 == new java stack pointer
a61af66fc99e Initial load
duke
parents:
diff changeset
1847
a61af66fc99e Initial load
duke
parents:
diff changeset
1848 __ bind(resume_interpreter);
a61af66fc99e Initial load
duke
parents:
diff changeset
1849 VALIDATE_STATE(G3_scratch, 10);
a61af66fc99e Initial load
duke
parents:
diff changeset
1850
a61af66fc99e Initial load
duke
parents:
diff changeset
1851 // A frame we have already used before so no need to bang stack so use call_interpreter_2 entry
a61af66fc99e Initial load
duke
parents:
diff changeset
1852
a61af66fc99e Initial load
duke
parents:
diff changeset
1853 __ set((int)BytecodeInterpreter::method_resume, L1_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
1854 __ st(L1_scratch, STATE(_msg));
a61af66fc99e Initial load
duke
parents:
diff changeset
1855 __ ba(false, call_interpreter_2);
a61af66fc99e Initial load
duke
parents:
diff changeset
1856 __ delayed()->st_ptr(O1, STATE(_stack));
a61af66fc99e Initial load
duke
parents:
diff changeset
1857
a61af66fc99e Initial load
duke
parents:
diff changeset
1858
a61af66fc99e Initial load
duke
parents:
diff changeset
1859 // Fast accessor methods share this entry point.
a61af66fc99e Initial load
duke
parents:
diff changeset
1860 // This works because frame manager is in the same codelet
a61af66fc99e Initial load
duke
parents:
diff changeset
1861 // This can either be an entry via call_stub/c1/c2 or a recursive interpreter call
a61af66fc99e Initial load
duke
parents:
diff changeset
1862 // we need to do a little register fixup here once we distinguish the two of them
a61af66fc99e Initial load
duke
parents:
diff changeset
1863 if (UseFastAccessorMethods && !synchronized) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1864 // Call stub_return address still in O7
a61af66fc99e Initial load
duke
parents:
diff changeset
1865 __ bind(fast_accessor_slow_entry_path);
a61af66fc99e Initial load
duke
parents:
diff changeset
1866 __ set((intptr_t)return_from_native_method - 8, Gtmp1);
a61af66fc99e Initial load
duke
parents:
diff changeset
1867 __ cmp(Gtmp1, O7); // returning to interpreter?
a61af66fc99e Initial load
duke
parents:
diff changeset
1868 __ brx(Assembler::equal, true, Assembler::pt, re_dispatch); // yep
a61af66fc99e Initial load
duke
parents:
diff changeset
1869 __ delayed()->nop();
a61af66fc99e Initial load
duke
parents:
diff changeset
1870 __ ba(false, re_dispatch);
a61af66fc99e Initial load
duke
parents:
diff changeset
1871 __ delayed()->mov(G0, prevState); // initial entry
a61af66fc99e Initial load
duke
parents:
diff changeset
1872
a61af66fc99e Initial load
duke
parents:
diff changeset
1873 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1874
a61af66fc99e Initial load
duke
parents:
diff changeset
1875 // interpreter returning to native code (call_stub/c1/c2)
a61af66fc99e Initial load
duke
parents:
diff changeset
1876 // convert result and unwind initial activation
a61af66fc99e Initial load
duke
parents:
diff changeset
1877 // L2_scratch - scaled result type index
a61af66fc99e Initial load
duke
parents:
diff changeset
1878
a61af66fc99e Initial load
duke
parents:
diff changeset
1879 __ bind(return_to_initial_caller);
a61af66fc99e Initial load
duke
parents:
diff changeset
1880
a61af66fc99e Initial load
duke
parents:
diff changeset
1881 __ set((intptr_t)CppInterpreter::_stack_to_native_abi, L4_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
1882 __ ld_ptr(L4_scratch, L2_scratch, Lscratch); // get typed result converter address
a61af66fc99e Initial load
duke
parents:
diff changeset
1883 __ ld_ptr(STATE(_stack), O0); // current top (prepushed)
a61af66fc99e Initial load
duke
parents:
diff changeset
1884 __ jmpl(Lscratch, G0, O7); // and convert it
a61af66fc99e Initial load
duke
parents:
diff changeset
1885 __ delayed()->add(O0, wordSize, O0); // get source (top of current expr stack)
a61af66fc99e Initial load
duke
parents:
diff changeset
1886
a61af66fc99e Initial load
duke
parents:
diff changeset
1887 Label unwind_initial_activation;
a61af66fc99e Initial load
duke
parents:
diff changeset
1888 __ bind(unwind_initial_activation);
a61af66fc99e Initial load
duke
parents:
diff changeset
1889
a61af66fc99e Initial load
duke
parents:
diff changeset
1890 // RETURN TO CALL_STUB/C1/C2 code (result if any in I0..I1/(F0/..F1)
a61af66fc99e Initial load
duke
parents:
diff changeset
1891 // we can return here with an exception that wasn't handled by interpreted code
a61af66fc99e Initial load
duke
parents:
diff changeset
1892 // how does c1/c2 see it on return?
a61af66fc99e Initial load
duke
parents:
diff changeset
1893
a61af66fc99e Initial load
duke
parents:
diff changeset
1894 // compute resulting sp before/after args popped depending upon calling convention
a61af66fc99e Initial load
duke
parents:
diff changeset
1895 // __ ld_ptr(STATE(_saved_sp), Gtmp1);
a61af66fc99e Initial load
duke
parents:
diff changeset
1896 //
a61af66fc99e Initial load
duke
parents:
diff changeset
1897 // POP FRAME HERE ==================================
a61af66fc99e Initial load
duke
parents:
diff changeset
1898 __ restore(FP, G0, SP);
a61af66fc99e Initial load
duke
parents:
diff changeset
1899 __ retl();
a61af66fc99e Initial load
duke
parents:
diff changeset
1900 __ delayed()->mov(I5_savedSP->after_restore(), SP);
a61af66fc99e Initial load
duke
parents:
diff changeset
1901
a61af66fc99e Initial load
duke
parents:
diff changeset
1902 // OSR request, unwind the current frame and transfer to the OSR entry
a61af66fc99e Initial load
duke
parents:
diff changeset
1903 // and enter OSR nmethod
a61af66fc99e Initial load
duke
parents:
diff changeset
1904
a61af66fc99e Initial load
duke
parents:
diff changeset
1905 __ bind(do_OSR);
a61af66fc99e Initial load
duke
parents:
diff changeset
1906 Label remove_initial_frame;
a61af66fc99e Initial load
duke
parents:
diff changeset
1907 __ ld_ptr(STATE(_prev_link), L1_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
1908 __ ld_ptr(STATE(_result._osr._osr_buf), G1_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
1909
a61af66fc99e Initial load
duke
parents:
diff changeset
1910 // We are going to pop this frame. Is there another interpreter frame underneath
a61af66fc99e Initial load
duke
parents:
diff changeset
1911 // it or is it callstub/compiled?
a61af66fc99e Initial load
duke
parents:
diff changeset
1912
a61af66fc99e Initial load
duke
parents:
diff changeset
1913 __ tst(L1_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
1914 __ brx(Assembler::zero, false, Assembler::pt, remove_initial_frame);
a61af66fc99e Initial load
duke
parents:
diff changeset
1915 __ delayed()->ld_ptr(STATE(_result._osr._osr_entry), G3_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
1916
a61af66fc99e Initial load
duke
parents:
diff changeset
1917 // Frame underneath is an interpreter frame simply unwind
a61af66fc99e Initial load
duke
parents:
diff changeset
1918 // POP FRAME HERE ==================================
a61af66fc99e Initial load
duke
parents:
diff changeset
1919 __ restore(FP, G0, SP); // unwind interpreter state frame
a61af66fc99e Initial load
duke
parents:
diff changeset
1920 __ mov(I5_savedSP->after_restore(), SP);
a61af66fc99e Initial load
duke
parents:
diff changeset
1921
a61af66fc99e Initial load
duke
parents:
diff changeset
1922 // Since we are now calling native need to change our "return address" from the
a61af66fc99e Initial load
duke
parents:
diff changeset
1923 // dummy RecursiveInterpreterActivation to a return from native
a61af66fc99e Initial load
duke
parents:
diff changeset
1924
a61af66fc99e Initial load
duke
parents:
diff changeset
1925 __ set((intptr_t)return_from_native_method - 8, O7);
a61af66fc99e Initial load
duke
parents:
diff changeset
1926
a61af66fc99e Initial load
duke
parents:
diff changeset
1927 __ jmpl(G3_scratch, G0, G0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1928 __ delayed()->mov(G1_scratch, O0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1929
a61af66fc99e Initial load
duke
parents:
diff changeset
1930 __ bind(remove_initial_frame);
a61af66fc99e Initial load
duke
parents:
diff changeset
1931
a61af66fc99e Initial load
duke
parents:
diff changeset
1932 // POP FRAME HERE ==================================
a61af66fc99e Initial load
duke
parents:
diff changeset
1933 __ restore(FP, G0, SP);
a61af66fc99e Initial load
duke
parents:
diff changeset
1934 __ mov(I5_savedSP->after_restore(), SP);
a61af66fc99e Initial load
duke
parents:
diff changeset
1935 __ jmpl(G3_scratch, G0, G0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1936 __ delayed()->mov(G1_scratch, O0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1937
a61af66fc99e Initial load
duke
parents:
diff changeset
1938 // Call a new method. All we do is (temporarily) trim the expression stack
a61af66fc99e Initial load
duke
parents:
diff changeset
1939 // push a return address to bring us back to here and leap to the new entry.
a61af66fc99e Initial load
duke
parents:
diff changeset
1940 // At this point we have a topmost frame that was allocated by the frame manager
a61af66fc99e Initial load
duke
parents:
diff changeset
1941 // which contains the current method interpreted state. We trim this frame
a61af66fc99e Initial load
duke
parents:
diff changeset
1942 // of excess java expression stack entries and then recurse.
a61af66fc99e Initial load
duke
parents:
diff changeset
1943
a61af66fc99e Initial load
duke
parents:
diff changeset
1944 __ bind(call_method);
a61af66fc99e Initial load
duke
parents:
diff changeset
1945
a61af66fc99e Initial load
duke
parents:
diff changeset
1946 // stack points to next free location and not top element on expression stack
a61af66fc99e Initial load
duke
parents:
diff changeset
1947 // method expects sp to be pointing to topmost element
a61af66fc99e Initial load
duke
parents:
diff changeset
1948
a61af66fc99e Initial load
duke
parents:
diff changeset
1949 __ ld_ptr(STATE(_thread), G2_thread);
a61af66fc99e Initial load
duke
parents:
diff changeset
1950 __ ld_ptr(STATE(_result._to_call._callee), G5_method);
a61af66fc99e Initial load
duke
parents:
diff changeset
1951
a61af66fc99e Initial load
duke
parents:
diff changeset
1952
a61af66fc99e Initial load
duke
parents:
diff changeset
1953 // SP already takes in to account the 2 extra words we use for slop
a61af66fc99e Initial load
duke
parents:
diff changeset
1954 // when we call a "static long no_params()" method. So if
a61af66fc99e Initial load
duke
parents:
diff changeset
1955 // we trim back sp by the amount of unused java expression stack
a61af66fc99e Initial load
duke
parents:
diff changeset
1956 // there will be automagically the 2 extra words we need.
a61af66fc99e Initial load
duke
parents:
diff changeset
1957 // We also have to worry about keeping SP aligned.
a61af66fc99e Initial load
duke
parents:
diff changeset
1958
a61af66fc99e Initial load
duke
parents:
diff changeset
1959 __ ld_ptr(STATE(_stack), Gargs);
a61af66fc99e Initial load
duke
parents:
diff changeset
1960 __ ld_ptr(STATE(_stack_limit), L1_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
1961
a61af66fc99e Initial load
duke
parents:
diff changeset
1962 // compute the unused java stack size
a61af66fc99e Initial load
duke
parents:
diff changeset
1963 __ sub(Gargs, L1_scratch, L2_scratch); // compute unused space
a61af66fc99e Initial load
duke
parents:
diff changeset
1964
123
9e5a7340635e 6688137: c++ interpreter fails on 64bit sparc
sgoldman
parents: 0
diff changeset
1965 // Round down the unused space to that stack is always 16-byte aligned
9e5a7340635e 6688137: c++ interpreter fails on 64bit sparc
sgoldman
parents: 0
diff changeset
1966 // by making the unused space a multiple of the size of two longs.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1967
123
9e5a7340635e 6688137: c++ interpreter fails on 64bit sparc
sgoldman
parents: 0
diff changeset
1968 __ and3(L2_scratch, -2*BytesPerLong, L2_scratch);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1969
a61af66fc99e Initial load
duke
parents:
diff changeset
1970 // Now trim the stack
a61af66fc99e Initial load
duke
parents:
diff changeset
1971 __ add(SP, L2_scratch, SP);
a61af66fc99e Initial load
duke
parents:
diff changeset
1972
a61af66fc99e Initial load
duke
parents:
diff changeset
1973
a61af66fc99e Initial load
duke
parents:
diff changeset
1974 // Now point to the final argument (account for prepush)
a61af66fc99e Initial load
duke
parents:
diff changeset
1975 __ add(Gargs, wordSize, Gargs);
a61af66fc99e Initial load
duke
parents:
diff changeset
1976 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
1977 // Make sure we have space for the window
a61af66fc99e Initial load
duke
parents:
diff changeset
1978 __ sub(Gargs, SP, L1_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
1979 __ cmp(L1_scratch, 16*wordSize);
a61af66fc99e Initial load
duke
parents:
diff changeset
1980 {
a61af66fc99e Initial load
duke
parents:
diff changeset
1981 Label skip;
a61af66fc99e Initial load
duke
parents:
diff changeset
1982 __ brx(Assembler::greaterEqual, false, Assembler::pt, skip);
a61af66fc99e Initial load
duke
parents:
diff changeset
1983 __ delayed()->nop();
a61af66fc99e Initial load
duke
parents:
diff changeset
1984 __ stop("killed stack");
a61af66fc99e Initial load
duke
parents:
diff changeset
1985 __ bind(skip);
a61af66fc99e Initial load
duke
parents:
diff changeset
1986 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1987 #endif // ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
1988
a61af66fc99e Initial load
duke
parents:
diff changeset
1989 // Create a new frame where we can store values that make it look like the interpreter
a61af66fc99e Initial load
duke
parents:
diff changeset
1990 // really recursed.
a61af66fc99e Initial load
duke
parents:
diff changeset
1991
a61af66fc99e Initial load
duke
parents:
diff changeset
1992 // prepare to recurse or call specialized entry
a61af66fc99e Initial load
duke
parents:
diff changeset
1993
a61af66fc99e Initial load
duke
parents:
diff changeset
1994 // First link the registers we need
a61af66fc99e Initial load
duke
parents:
diff changeset
1995
a61af66fc99e Initial load
duke
parents:
diff changeset
1996 // make the pc look good in debugger
a61af66fc99e Initial load
duke
parents:
diff changeset
1997 __ set(CAST_FROM_FN_PTR(intptr_t, RecursiveInterpreterActivation), O7);
a61af66fc99e Initial load
duke
parents:
diff changeset
1998 // argument too
a61af66fc99e Initial load
duke
parents:
diff changeset
1999 __ mov(Lstate, I0);
a61af66fc99e Initial load
duke
parents:
diff changeset
2000
a61af66fc99e Initial load
duke
parents:
diff changeset
2001 // Record our sending SP
a61af66fc99e Initial load
duke
parents:
diff changeset
2002 __ mov(SP, O5_savedSP);
a61af66fc99e Initial load
duke
parents:
diff changeset
2003
a61af66fc99e Initial load
duke
parents:
diff changeset
2004 __ ld_ptr(STATE(_result._to_call._callee_entry_point), L2_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
2005 __ set((intptr_t) entry_point, L1_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
2006 __ cmp(L1_scratch, L2_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
2007 __ brx(Assembler::equal, false, Assembler::pt, re_dispatch);
a61af66fc99e Initial load
duke
parents:
diff changeset
2008 __ delayed()->mov(Lstate, prevState); // link activations
a61af66fc99e Initial load
duke
parents:
diff changeset
2009
a61af66fc99e Initial load
duke
parents:
diff changeset
2010 // method uses specialized entry, push a return so we look like call stub setup
a61af66fc99e Initial load
duke
parents:
diff changeset
2011 // this path will handle fact that result is returned in registers and not
a61af66fc99e Initial load
duke
parents:
diff changeset
2012 // on the java stack.
a61af66fc99e Initial load
duke
parents:
diff changeset
2013
a61af66fc99e Initial load
duke
parents:
diff changeset
2014 __ set((intptr_t)return_from_native_method - 8, O7);
a61af66fc99e Initial load
duke
parents:
diff changeset
2015 __ jmpl(L2_scratch, G0, G0); // Do specialized entry
a61af66fc99e Initial load
duke
parents:
diff changeset
2016 __ delayed()->nop();
a61af66fc99e Initial load
duke
parents:
diff changeset
2017
a61af66fc99e Initial load
duke
parents:
diff changeset
2018 //
a61af66fc99e Initial load
duke
parents:
diff changeset
2019 // Bad Message from interpreter
a61af66fc99e Initial load
duke
parents:
diff changeset
2020 //
a61af66fc99e Initial load
duke
parents:
diff changeset
2021 __ bind(bad_msg);
a61af66fc99e Initial load
duke
parents:
diff changeset
2022 __ stop("Bad message from interpreter");
a61af66fc99e Initial load
duke
parents:
diff changeset
2023
a61af66fc99e Initial load
duke
parents:
diff changeset
2024 // Interpreted method "returned" with an exception pass it on...
a61af66fc99e Initial load
duke
parents:
diff changeset
2025 // Pass result, unwind activation and continue/return to interpreter/call_stub
a61af66fc99e Initial load
duke
parents:
diff changeset
2026 // We handle result (if any) differently based on return to interpreter or call_stub
a61af66fc99e Initial load
duke
parents:
diff changeset
2027
a61af66fc99e Initial load
duke
parents:
diff changeset
2028 __ bind(throw_exception);
a61af66fc99e Initial load
duke
parents:
diff changeset
2029 __ ld_ptr(STATE(_prev_link), L1_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
2030 __ tst(L1_scratch);
a61af66fc99e Initial load
duke
parents:
diff changeset
2031 __ brx(Assembler::zero, false, Assembler::pt, unwind_and_forward);
a61af66fc99e Initial load
duke
parents:
diff changeset
2032 __ delayed()->nop();
a61af66fc99e Initial load
duke
parents:
diff changeset
2033
a61af66fc99e Initial load
duke
parents:
diff changeset
2034 __ ld_ptr(STATE(_locals), O1); // get result of popping callee's args
a61af66fc99e Initial load
duke
parents:
diff changeset
2035 __ ba(false, unwind_recursive_activation);
a61af66fc99e Initial load
duke
parents:
diff changeset
2036 __ delayed()->nop();
a61af66fc99e Initial load
duke
parents:
diff changeset
2037
a61af66fc99e Initial load
duke
parents:
diff changeset
2038 interpreter_frame_manager = entry_point;
a61af66fc99e Initial load
duke
parents:
diff changeset
2039 return entry_point;
a61af66fc99e Initial load
duke
parents:
diff changeset
2040 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2041
a61af66fc99e Initial load
duke
parents:
diff changeset
2042 InterpreterGenerator::InterpreterGenerator(StubQueue* code)
a61af66fc99e Initial load
duke
parents:
diff changeset
2043 : CppInterpreterGenerator(code) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2044 generate_all(); // down here so it can be "virtual"
a61af66fc99e Initial load
duke
parents:
diff changeset
2045 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2046
a61af66fc99e Initial load
duke
parents:
diff changeset
2047
a61af66fc99e Initial load
duke
parents:
diff changeset
2048 static int size_activation_helper(int callee_extra_locals, int max_stack, int monitor_size) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2049
a61af66fc99e Initial load
duke
parents:
diff changeset
2050 // Figure out the size of an interpreter frame (in words) given that we have a fully allocated
a61af66fc99e Initial load
duke
parents:
diff changeset
2051 // expression stack, the callee will have callee_extra_locals (so we can account for
a61af66fc99e Initial load
duke
parents:
diff changeset
2052 // frame extension) and monitor_size for monitors. Basically we need to calculate
a61af66fc99e Initial load
duke
parents:
diff changeset
2053 // this exactly like generate_fixed_frame/generate_compute_interpreter_state.
a61af66fc99e Initial load
duke
parents:
diff changeset
2054 //
a61af66fc99e Initial load
duke
parents:
diff changeset
2055 //
a61af66fc99e Initial load
duke
parents:
diff changeset
2056 // The big complicating thing here is that we must ensure that the stack stays properly
a61af66fc99e Initial load
duke
parents:
diff changeset
2057 // aligned. This would be even uglier if monitor size wasn't modulo what the stack
a61af66fc99e Initial load
duke
parents:
diff changeset
2058 // needs to be aligned for). We are given that the sp (fp) is already aligned by
a61af66fc99e Initial load
duke
parents:
diff changeset
2059 // the caller so we must ensure that it is properly aligned for our callee.
a61af66fc99e Initial load
duke
parents:
diff changeset
2060 //
a61af66fc99e Initial load
duke
parents:
diff changeset
2061 // Ths c++ interpreter always makes sure that we have a enough extra space on the
a61af66fc99e Initial load
duke
parents:
diff changeset
2062 // stack at all times to deal with the "stack long no_params()" method issue. This
a61af66fc99e Initial load
duke
parents:
diff changeset
2063 // is "slop_factor" here.
a61af66fc99e Initial load
duke
parents:
diff changeset
2064 const int slop_factor = 2;
a61af66fc99e Initial load
duke
parents:
diff changeset
2065
a61af66fc99e Initial load
duke
parents:
diff changeset
2066 const int fixed_size = sizeof(BytecodeInterpreter)/wordSize + // interpreter state object
a61af66fc99e Initial load
duke
parents:
diff changeset
2067 frame::memory_parameter_word_sp_offset; // register save area + param window
710
e5b0439ef4ae 6655638: dynamic languages need method handles
jrose
parents: 196
diff changeset
2068 const int extra_stack = 0; //6815692//methodOopDesc::extra_stack_entries();
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2069 return (round_to(max_stack +
710
e5b0439ef4ae 6655638: dynamic languages need method handles
jrose
parents: 196
diff changeset
2070 extra_stack +
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2071 slop_factor +
a61af66fc99e Initial load
duke
parents:
diff changeset
2072 fixed_size +
a61af66fc99e Initial load
duke
parents:
diff changeset
2073 monitor_size +
a61af66fc99e Initial load
duke
parents:
diff changeset
2074 (callee_extra_locals * Interpreter::stackElementWords()), WordsPerLong));
a61af66fc99e Initial load
duke
parents:
diff changeset
2075
a61af66fc99e Initial load
duke
parents:
diff changeset
2076 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2077
a61af66fc99e Initial load
duke
parents:
diff changeset
2078 int AbstractInterpreter::size_top_interpreter_activation(methodOop method) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2079
a61af66fc99e Initial load
duke
parents:
diff changeset
2080 // See call_stub code
a61af66fc99e Initial load
duke
parents:
diff changeset
2081 int call_stub_size = round_to(7 + frame::memory_parameter_word_sp_offset,
a61af66fc99e Initial load
duke
parents:
diff changeset
2082 WordsPerLong); // 7 + register save area
a61af66fc99e Initial load
duke
parents:
diff changeset
2083
a61af66fc99e Initial load
duke
parents:
diff changeset
2084 // Save space for one monitor to get into the interpreted method in case
a61af66fc99e Initial load
duke
parents:
diff changeset
2085 // the method is synchronized
a61af66fc99e Initial load
duke
parents:
diff changeset
2086 int monitor_size = method->is_synchronized() ?
a61af66fc99e Initial load
duke
parents:
diff changeset
2087 1*frame::interpreter_frame_monitor_size() : 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
2088 return size_activation_helper(method->max_locals(), method->max_stack(),
a61af66fc99e Initial load
duke
parents:
diff changeset
2089 monitor_size) + call_stub_size;
a61af66fc99e Initial load
duke
parents:
diff changeset
2090 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2091
a61af66fc99e Initial load
duke
parents:
diff changeset
2092 void BytecodeInterpreter::layout_interpreterState(interpreterState to_fill,
a61af66fc99e Initial load
duke
parents:
diff changeset
2093 frame* caller,
a61af66fc99e Initial load
duke
parents:
diff changeset
2094 frame* current,
a61af66fc99e Initial load
duke
parents:
diff changeset
2095 methodOop method,
a61af66fc99e Initial load
duke
parents:
diff changeset
2096 intptr_t* locals,
a61af66fc99e Initial load
duke
parents:
diff changeset
2097 intptr_t* stack,
a61af66fc99e Initial load
duke
parents:
diff changeset
2098 intptr_t* stack_base,
a61af66fc99e Initial load
duke
parents:
diff changeset
2099 intptr_t* monitor_base,
a61af66fc99e Initial load
duke
parents:
diff changeset
2100 intptr_t* frame_bottom,
a61af66fc99e Initial load
duke
parents:
diff changeset
2101 bool is_top_frame
a61af66fc99e Initial load
duke
parents:
diff changeset
2102 )
a61af66fc99e Initial load
duke
parents:
diff changeset
2103 {
a61af66fc99e Initial load
duke
parents:
diff changeset
2104 // What about any vtable?
a61af66fc99e Initial load
duke
parents:
diff changeset
2105 //
a61af66fc99e Initial load
duke
parents:
diff changeset
2106 to_fill->_thread = JavaThread::current();
a61af66fc99e Initial load
duke
parents:
diff changeset
2107 // This gets filled in later but make it something recognizable for now
a61af66fc99e Initial load
duke
parents:
diff changeset
2108 to_fill->_bcp = method->code_base();
a61af66fc99e Initial load
duke
parents:
diff changeset
2109 to_fill->_locals = locals;
a61af66fc99e Initial load
duke
parents:
diff changeset
2110 to_fill->_constants = method->constants()->cache();
a61af66fc99e Initial load
duke
parents:
diff changeset
2111 to_fill->_method = method;
a61af66fc99e Initial load
duke
parents:
diff changeset
2112 to_fill->_mdx = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
2113 to_fill->_stack = stack;
a61af66fc99e Initial load
duke
parents:
diff changeset
2114 if (is_top_frame && JavaThread::current()->popframe_forcing_deopt_reexecution() ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2115 to_fill->_msg = deopt_resume2;
a61af66fc99e Initial load
duke
parents:
diff changeset
2116 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2117 to_fill->_msg = method_resume;
a61af66fc99e Initial load
duke
parents:
diff changeset
2118 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2119 to_fill->_result._to_call._bcp_advance = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
2120 to_fill->_result._to_call._callee_entry_point = NULL; // doesn't matter to anyone
a61af66fc99e Initial load
duke
parents:
diff changeset
2121 to_fill->_result._to_call._callee = NULL; // doesn't matter to anyone
a61af66fc99e Initial load
duke
parents:
diff changeset
2122 to_fill->_prev_link = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
2123
a61af66fc99e Initial load
duke
parents:
diff changeset
2124 // Fill in the registers for the frame
a61af66fc99e Initial load
duke
parents:
diff changeset
2125
a61af66fc99e Initial load
duke
parents:
diff changeset
2126 // Need to install _sender_sp. Actually not too hard in C++!
a61af66fc99e Initial load
duke
parents:
diff changeset
2127 // When the skeletal frames are layed out we fill in a value
a61af66fc99e Initial load
duke
parents:
diff changeset
2128 // for _sender_sp. That value is only correct for the oldest
a61af66fc99e Initial load
duke
parents:
diff changeset
2129 // skeletal frame constructed (because there is only a single
a61af66fc99e Initial load
duke
parents:
diff changeset
2130 // entry for "caller_adjustment". While the skeletal frames
a61af66fc99e Initial load
duke
parents:
diff changeset
2131 // exist that is good enough. We correct that calculation
a61af66fc99e Initial load
duke
parents:
diff changeset
2132 // here and get all the frames correct.
a61af66fc99e Initial load
duke
parents:
diff changeset
2133
a61af66fc99e Initial load
duke
parents:
diff changeset
2134 // to_fill->_sender_sp = locals - (method->size_of_parameters() - 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
2135
a61af66fc99e Initial load
duke
parents:
diff changeset
2136 *current->register_addr(Lstate) = (intptr_t) to_fill;
a61af66fc99e Initial load
duke
parents:
diff changeset
2137 // skeletal already places a useful value here and this doesn't account
a61af66fc99e Initial load
duke
parents:
diff changeset
2138 // for alignment so don't bother.
a61af66fc99e Initial load
duke
parents:
diff changeset
2139 // *current->register_addr(I5_savedSP) = (intptr_t) locals - (method->size_of_parameters() - 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
2140
a61af66fc99e Initial load
duke
parents:
diff changeset
2141 if (caller->is_interpreted_frame()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2142 interpreterState prev = caller->get_interpreterState();
a61af66fc99e Initial load
duke
parents:
diff changeset
2143 to_fill->_prev_link = prev;
a61af66fc99e Initial load
duke
parents:
diff changeset
2144 // Make the prev callee look proper
a61af66fc99e Initial load
duke
parents:
diff changeset
2145 prev->_result._to_call._callee = method;
a61af66fc99e Initial load
duke
parents:
diff changeset
2146 if (*prev->_bcp == Bytecodes::_invokeinterface) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2147 prev->_result._to_call._bcp_advance = 5;
a61af66fc99e Initial load
duke
parents:
diff changeset
2148 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2149 prev->_result._to_call._bcp_advance = 3;
a61af66fc99e Initial load
duke
parents:
diff changeset
2150 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2151 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2152 to_fill->_oop_temp = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
2153 to_fill->_stack_base = stack_base;
a61af66fc99e Initial load
duke
parents:
diff changeset
2154 // Need +1 here because stack_base points to the word just above the first expr stack entry
a61af66fc99e Initial load
duke
parents:
diff changeset
2155 // and stack_limit is supposed to point to the word just below the last expr stack entry.
a61af66fc99e Initial load
duke
parents:
diff changeset
2156 // See generate_compute_interpreter_state.
710
e5b0439ef4ae 6655638: dynamic languages need method handles
jrose
parents: 196
diff changeset
2157 int extra_stack = 0; //6815692//methodOopDesc::extra_stack_entries();
e5b0439ef4ae 6655638: dynamic languages need method handles
jrose
parents: 196
diff changeset
2158 to_fill->_stack_limit = stack_base - (method->max_stack() + 1 + extra_stack);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2159 to_fill->_monitor_base = (BasicObjectLock*) monitor_base;
a61af66fc99e Initial load
duke
parents:
diff changeset
2160
a61af66fc99e Initial load
duke
parents:
diff changeset
2161 // sparc specific
a61af66fc99e Initial load
duke
parents:
diff changeset
2162 to_fill->_frame_bottom = frame_bottom;
a61af66fc99e Initial load
duke
parents:
diff changeset
2163 to_fill->_self_link = to_fill;
a61af66fc99e Initial load
duke
parents:
diff changeset
2164 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
2165 to_fill->_native_fresult = 123456.789;
a61af66fc99e Initial load
duke
parents:
diff changeset
2166 to_fill->_native_lresult = CONST64(0xdeadcafedeafcafe);
a61af66fc99e Initial load
duke
parents:
diff changeset
2167 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
2168 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2169
a61af66fc99e Initial load
duke
parents:
diff changeset
2170 void BytecodeInterpreter::pd_layout_interpreterState(interpreterState istate, address last_Java_pc, intptr_t* last_Java_fp) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2171 istate->_last_Java_pc = (intptr_t*) last_Java_pc;
a61af66fc99e Initial load
duke
parents:
diff changeset
2172 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2173
a61af66fc99e Initial load
duke
parents:
diff changeset
2174
a61af66fc99e Initial load
duke
parents:
diff changeset
2175 int AbstractInterpreter::layout_activation(methodOop method,
a61af66fc99e Initial load
duke
parents:
diff changeset
2176 int tempcount, // Number of slots on java expression stack in use
a61af66fc99e Initial load
duke
parents:
diff changeset
2177 int popframe_extra_args,
a61af66fc99e Initial load
duke
parents:
diff changeset
2178 int moncount, // Number of active monitors
a61af66fc99e Initial load
duke
parents:
diff changeset
2179 int callee_param_size,
a61af66fc99e Initial load
duke
parents:
diff changeset
2180 int callee_locals_size,
a61af66fc99e Initial load
duke
parents:
diff changeset
2181 frame* caller,
a61af66fc99e Initial load
duke
parents:
diff changeset
2182 frame* interpreter_frame,
a61af66fc99e Initial load
duke
parents:
diff changeset
2183 bool is_top_frame) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2184
a61af66fc99e Initial load
duke
parents:
diff changeset
2185 assert(popframe_extra_args == 0, "NEED TO FIX");
a61af66fc99e Initial load
duke
parents:
diff changeset
2186 // NOTE this code must exactly mimic what InterpreterGenerator::generate_compute_interpreter_state()
a61af66fc99e Initial load
duke
parents:
diff changeset
2187 // does as far as allocating an interpreter frame.
a61af66fc99e Initial load
duke
parents:
diff changeset
2188 // If interpreter_frame!=NULL, set up the method, locals, and monitors.
a61af66fc99e Initial load
duke
parents:
diff changeset
2189 // The frame interpreter_frame, if not NULL, is guaranteed to be the right size,
a61af66fc99e Initial load
duke
parents:
diff changeset
2190 // as determined by a previous call to this method.
a61af66fc99e Initial load
duke
parents:
diff changeset
2191 // It is also guaranteed to be walkable even though it is in a skeletal state
a61af66fc99e Initial load
duke
parents:
diff changeset
2192 // NOTE: return size is in words not bytes
a61af66fc99e Initial load
duke
parents:
diff changeset
2193 // NOTE: tempcount is the current size of the java expression stack. For top most
a61af66fc99e Initial load
duke
parents:
diff changeset
2194 // frames we will allocate a full sized expression stack and not the curback
a61af66fc99e Initial load
duke
parents:
diff changeset
2195 // version that non-top frames have.
a61af66fc99e Initial load
duke
parents:
diff changeset
2196
a61af66fc99e Initial load
duke
parents:
diff changeset
2197 // Calculate the amount our frame will be adjust by the callee. For top frame
a61af66fc99e Initial load
duke
parents:
diff changeset
2198 // this is zero.
a61af66fc99e Initial load
duke
parents:
diff changeset
2199
a61af66fc99e Initial load
duke
parents:
diff changeset
2200 // NOTE: ia64 seems to do this wrong (or at least backwards) in that it
a61af66fc99e Initial load
duke
parents:
diff changeset
2201 // calculates the extra locals based on itself. Not what the callee does
a61af66fc99e Initial load
duke
parents:
diff changeset
2202 // to it. So it ignores last_frame_adjust value. Seems suspicious as far
a61af66fc99e Initial load
duke
parents:
diff changeset
2203 // as getting sender_sp correct.
a61af66fc99e Initial load
duke
parents:
diff changeset
2204
a61af66fc99e Initial load
duke
parents:
diff changeset
2205 int extra_locals_size = callee_locals_size - callee_param_size;
a61af66fc99e Initial load
duke
parents:
diff changeset
2206 int monitor_size = (sizeof(BasicObjectLock) * moncount) / wordSize;
a61af66fc99e Initial load
duke
parents:
diff changeset
2207 int full_frame_words = size_activation_helper(extra_locals_size, method->max_stack(), monitor_size);
a61af66fc99e Initial load
duke
parents:
diff changeset
2208 int short_frame_words = size_activation_helper(extra_locals_size, method->max_stack(), monitor_size);
a61af66fc99e Initial load
duke
parents:
diff changeset
2209 int frame_words = is_top_frame ? full_frame_words : short_frame_words;
a61af66fc99e Initial load
duke
parents:
diff changeset
2210
a61af66fc99e Initial load
duke
parents:
diff changeset
2211
a61af66fc99e Initial load
duke
parents:
diff changeset
2212 /*
a61af66fc99e Initial load
duke
parents:
diff changeset
2213 if we actually have a frame to layout we must now fill in all the pieces. This means both
a61af66fc99e Initial load
duke
parents:
diff changeset
2214 the interpreterState and the registers.
a61af66fc99e Initial load
duke
parents:
diff changeset
2215 */
a61af66fc99e Initial load
duke
parents:
diff changeset
2216 if (interpreter_frame != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2217
a61af66fc99e Initial load
duke
parents:
diff changeset
2218 // MUCHO HACK
a61af66fc99e Initial load
duke
parents:
diff changeset
2219
a61af66fc99e Initial load
duke
parents:
diff changeset
2220 intptr_t* frame_bottom = interpreter_frame->sp() - (full_frame_words - frame_words);
123
9e5a7340635e 6688137: c++ interpreter fails on 64bit sparc
sgoldman
parents: 0
diff changeset
2221 // 'interpreter_frame->sp()' is unbiased while 'frame_bottom' must be a biased value in 64bit mode.
9e5a7340635e 6688137: c++ interpreter fails on 64bit sparc
sgoldman
parents: 0
diff changeset
2222 assert(((intptr_t)frame_bottom & 0xf) == 0, "SP biased in layout_activation");
9e5a7340635e 6688137: c++ interpreter fails on 64bit sparc
sgoldman
parents: 0
diff changeset
2223 frame_bottom = (intptr_t*)((intptr_t)frame_bottom - STACK_BIAS);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2224
a61af66fc99e Initial load
duke
parents:
diff changeset
2225 /* Now fillin the interpreterState object */
a61af66fc99e Initial load
duke
parents:
diff changeset
2226
a61af66fc99e Initial load
duke
parents:
diff changeset
2227 interpreterState cur_state = (interpreterState) ((intptr_t)interpreter_frame->fp() - sizeof(BytecodeInterpreter));
a61af66fc99e Initial load
duke
parents:
diff changeset
2228
a61af66fc99e Initial load
duke
parents:
diff changeset
2229
a61af66fc99e Initial load
duke
parents:
diff changeset
2230 intptr_t* locals;
a61af66fc99e Initial load
duke
parents:
diff changeset
2231
a61af66fc99e Initial load
duke
parents:
diff changeset
2232 // Calculate the postion of locals[0]. This is painful because of
a61af66fc99e Initial load
duke
parents:
diff changeset
2233 // stack alignment (same as ia64). The problem is that we can
a61af66fc99e Initial load
duke
parents:
diff changeset
2234 // not compute the location of locals from fp(). fp() will account
a61af66fc99e Initial load
duke
parents:
diff changeset
2235 // for the extra locals but it also accounts for aligning the stack
a61af66fc99e Initial load
duke
parents:
diff changeset
2236 // and we can't determine if the locals[0] was misaligned but max_locals
a61af66fc99e Initial load
duke
parents:
diff changeset
2237 // was enough to have the
a61af66fc99e Initial load
duke
parents:
diff changeset
2238 // calculate postion of locals. fp already accounts for extra locals.
a61af66fc99e Initial load
duke
parents:
diff changeset
2239 // +2 for the static long no_params() issue.
a61af66fc99e Initial load
duke
parents:
diff changeset
2240
a61af66fc99e Initial load
duke
parents:
diff changeset
2241 if (caller->is_interpreted_frame()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2242 // locals must agree with the caller because it will be used to set the
a61af66fc99e Initial load
duke
parents:
diff changeset
2243 // caller's tos when we return.
a61af66fc99e Initial load
duke
parents:
diff changeset
2244 interpreterState prev = caller->get_interpreterState();
a61af66fc99e Initial load
duke
parents:
diff changeset
2245 // stack() is prepushed.
a61af66fc99e Initial load
duke
parents:
diff changeset
2246 locals = prev->stack() + method->size_of_parameters();
a61af66fc99e Initial load
duke
parents:
diff changeset
2247 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2248 // Lay out locals block in the caller adjacent to the register window save area.
a61af66fc99e Initial load
duke
parents:
diff changeset
2249 //
a61af66fc99e Initial load
duke
parents:
diff changeset
2250 // Compiled frames do not allocate a varargs area which is why this if
a61af66fc99e Initial load
duke
parents:
diff changeset
2251 // statement is needed.
a61af66fc99e Initial load
duke
parents:
diff changeset
2252 //
a61af66fc99e Initial load
duke
parents:
diff changeset
2253 intptr_t* fp = interpreter_frame->fp();
a61af66fc99e Initial load
duke
parents:
diff changeset
2254 int local_words = method->max_locals() * Interpreter::stackElementWords();
a61af66fc99e Initial load
duke
parents:
diff changeset
2255
a61af66fc99e Initial load
duke
parents:
diff changeset
2256 if (caller->is_compiled_frame()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2257 locals = fp + frame::register_save_words + local_words - 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
2258 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2259 locals = fp + frame::memory_parameter_word_sp_offset + local_words - 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
2260 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2261
a61af66fc99e Initial load
duke
parents:
diff changeset
2262 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2263 // END MUCHO HACK
a61af66fc99e Initial load
duke
parents:
diff changeset
2264
a61af66fc99e Initial load
duke
parents:
diff changeset
2265 intptr_t* monitor_base = (intptr_t*) cur_state;
a61af66fc99e Initial load
duke
parents:
diff changeset
2266 intptr_t* stack_base = monitor_base - monitor_size;
a61af66fc99e Initial load
duke
parents:
diff changeset
2267 /* +1 because stack is always prepushed */
a61af66fc99e Initial load
duke
parents:
diff changeset
2268 intptr_t* stack = stack_base - (tempcount + 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
2269
a61af66fc99e Initial load
duke
parents:
diff changeset
2270
a61af66fc99e Initial load
duke
parents:
diff changeset
2271 BytecodeInterpreter::layout_interpreterState(cur_state,
a61af66fc99e Initial load
duke
parents:
diff changeset
2272 caller,
a61af66fc99e Initial load
duke
parents:
diff changeset
2273 interpreter_frame,
a61af66fc99e Initial load
duke
parents:
diff changeset
2274 method,
a61af66fc99e Initial load
duke
parents:
diff changeset
2275 locals,
a61af66fc99e Initial load
duke
parents:
diff changeset
2276 stack,
a61af66fc99e Initial load
duke
parents:
diff changeset
2277 stack_base,
a61af66fc99e Initial load
duke
parents:
diff changeset
2278 monitor_base,
a61af66fc99e Initial load
duke
parents:
diff changeset
2279 frame_bottom,
a61af66fc99e Initial load
duke
parents:
diff changeset
2280 is_top_frame);
a61af66fc99e Initial load
duke
parents:
diff changeset
2281
a61af66fc99e Initial load
duke
parents:
diff changeset
2282 BytecodeInterpreter::pd_layout_interpreterState(cur_state, interpreter_return_address, interpreter_frame->fp());
a61af66fc99e Initial load
duke
parents:
diff changeset
2283
a61af66fc99e Initial load
duke
parents:
diff changeset
2284 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2285 return frame_words;
a61af66fc99e Initial load
duke
parents:
diff changeset
2286 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2287
a61af66fc99e Initial load
duke
parents:
diff changeset
2288 #endif // CC_INTERP