annotate src/share/vm/shark/sharkNativeWrapper.cpp @ 10185:d50cc62e94ff

8012715: G1: GraphKit accesses PtrQueue::_index as int but is size_t Summary: In graphKit INT operations were generated to access PtrQueue::_index which has type size_t. This is 64 bit on 64-bit machines. No problems occur on little endian machines as long as the index fits into 32 bit, but on big endian machines the upper part is read, which is zero. This leads to unnecessary branches to the slow path in the runtime. Reviewed-by: twisti, johnc Contributed-by: Martin Doerr <martin.doerr@sap.com>
author johnc
date Wed, 24 Apr 2013 14:48:43 -0700
parents 2cd5e15048e6
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1692
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
1 /*
2426
1d1603768966 7010070: Update all 2010 Oracle-changed OpenJDK files to have the proper copyright dates - second pass
trims
parents: 2376
diff changeset
2 * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
1692
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
3 * Copyright 2009, 2010 Red Hat, Inc.
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
5 *
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
6 * This code is free software; you can redistribute it and/or modify it
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
7 * under the terms of the GNU General Public License version 2 only, as
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
8 * published by the Free Software Foundation.
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
9 *
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
10 * This code is distributed in the hope that it will be useful, but WITHOUT
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
13 * version 2 for more details (a copy is included in the LICENSE file that
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
14 * accompanied this code).
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
15 *
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
16 * You should have received a copy of the GNU General Public License version
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
17 * 2 along with this work; if not, write to the Free Software Foundation,
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
19 *
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
21 * or visit www.oracle.com if you need additional information or have any
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
22 * questions.
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
23 *
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
24 */
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
25
1972
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1692
diff changeset
26 #include "precompiled.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1692
diff changeset
27 #include "shark/llvmHeaders.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1692
diff changeset
28 #include "shark/sharkNativeWrapper.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1692
diff changeset
29 #include "shark/sharkType.hpp"
1692
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
30
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
31 using namespace llvm;
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
32
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
33 void SharkNativeWrapper::initialize(const char *name) {
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
34 // Create the function
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
35 _function = Function::Create(
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
36 SharkType::entry_point_type(),
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
37 GlobalVariable::InternalLinkage,
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
38 name);
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
39
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
40 // Get our arguments
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
41 Function::arg_iterator ai = function()->arg_begin();
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
42 Argument *method = ai++;
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
43 method->setName("method");
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
44 Argument *base_pc = ai++;
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
45 base_pc->setName("base_pc");
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
46 code_buffer()->set_base_pc(base_pc);
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
47 Argument *thread = ai++;
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
48 thread->setName("thread");
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
49 set_thread(thread);
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
50
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
51 // Create and push our stack frame
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
52 builder()->SetInsertPoint(CreateBlock());
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
53 _stack = SharkStack::CreateBuildAndPushFrame(this, method);
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
54 NOT_PRODUCT(method = NULL);
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
55
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
56 // Create the oopmap. We use the one oopmap for every call site in
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
57 // the wrapper, which results in the odd mild inefficiency but is a
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
58 // damn sight easier to code.
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
59 OopMap *oopmap = new OopMap(
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
60 SharkStack::oopmap_slot_munge(stack()->oopmap_frame_size()),
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
61 SharkStack::oopmap_slot_munge(arg_size()));
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
62
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
63 // Set up the oop_tmp slot if required:
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
64 // - For static methods we use it to handlize the class argument
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
65 // for the call, and to protect the same during slow path locks
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
66 // (if synchronized).
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
67 // - For methods returning oops, we use it to protect the return
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
68 // value across safepoints or slow path unlocking.
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
69 if (is_static() || is_returning_oop()) {
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
70 _oop_tmp_slot = stack()->slot_addr(
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
71 stack()->oop_tmp_slot_offset(),
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
72 SharkType::oop_type(),
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
73 "oop_tmp_slot");
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
74
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
75 oopmap->set_oop(SharkStack::slot2reg(stack()->oop_tmp_slot_offset()));
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
76 }
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
77
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
78 // Set up the monitor slot, for synchronized methods
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
79 if (is_synchronized()) {
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
80 Unimplemented();
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
81 _lock_slot_offset = 23;
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
82 }
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
83
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
84 // Start building the argument list
7195
2cd5e15048e6 8003868: fix shark for latest HotSpot and LLVM
twisti
parents: 2426
diff changeset
85 std::vector<Type*> param_types;
1692
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
86 std::vector<Value*> param_values;
7195
2cd5e15048e6 8003868: fix shark for latest HotSpot and LLVM
twisti
parents: 2426
diff changeset
87 PointerType *box_type = PointerType::getUnqual(SharkType::oop_type());
1692
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
88
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
89 // First argument is the JNIEnv
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
90 param_types.push_back(SharkType::jniEnv_type());
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
91 param_values.push_back(
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
92 builder()->CreateAddressOfStructEntry(
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
93 thread,
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
94 JavaThread::jni_environment_offset(),
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
95 SharkType::jniEnv_type(),
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
96 "jni_environment"));
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
97
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
98 // For static methods, the second argument is the class
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
99 if (is_static()) {
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
100 builder()->CreateStore(
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
101 builder()->CreateInlineOop(
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
102 JNIHandles::make_local(
2376
c7f3d0b4570f 7017732: move static fields into Class to prepare for perm gen removal
never
parents: 1972
diff changeset
103 target()->method_holder()->java_mirror())),
1692
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
104 oop_tmp_slot());
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
105
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
106 param_types.push_back(box_type);
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
107 param_values.push_back(oop_tmp_slot());
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
108
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
109 _receiver_slot_offset = stack()->oop_tmp_slot_offset();
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
110 }
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
111 else if (is_returning_oop()) {
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
112 // The oop_tmp slot is registered in the oopmap,
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
113 // so we need to clear it. This is one of the
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
114 // mild inefficiencies I mentioned earlier.
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
115 builder()->CreateStore(LLVMValue::null(), oop_tmp_slot());
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
116 }
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
117
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
118 // Parse the arguments
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
119 for (int i = 0; i < arg_size(); i++) {
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
120 int slot_offset = stack()->locals_slots_offset() + arg_size() - 1 - i;
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
121 int adjusted_offset = slot_offset;
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
122 BasicBlock *null, *not_null, *merge;
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
123 Value *box;
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
124 PHINode *phi;
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
125
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
126 switch (arg_type(i)) {
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
127 case T_VOID:
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
128 break;
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
129
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
130 case T_OBJECT:
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
131 case T_ARRAY:
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
132 null = CreateBlock("null");
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
133 not_null = CreateBlock("not_null");
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
134 merge = CreateBlock("merge");
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
135
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
136 box = stack()->slot_addr(slot_offset, SharkType::oop_type());
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
137 builder()->CreateCondBr(
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
138 builder()->CreateICmp(
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
139 ICmpInst::ICMP_EQ,
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
140 builder()->CreateLoad(box),
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
141 LLVMValue::null()),
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
142 null, not_null);
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
143
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
144 builder()->SetInsertPoint(null);
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
145 builder()->CreateBr(merge);
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
146
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
147 builder()->SetInsertPoint(not_null);
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
148 builder()->CreateBr(merge);
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
149
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
150 builder()->SetInsertPoint(merge);
7195
2cd5e15048e6 8003868: fix shark for latest HotSpot and LLVM
twisti
parents: 2426
diff changeset
151 phi = builder()->CreatePHI(box_type, 0, "boxed_object");
1692
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
152 phi->addIncoming(ConstantPointerNull::get(box_type), null);
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
153 phi->addIncoming(box, not_null);
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
154 box = phi;
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
155
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
156 param_types.push_back(box_type);
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
157 param_values.push_back(box);
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
158
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
159 oopmap->set_oop(SharkStack::slot2reg(slot_offset));
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
160
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
161 if (i == 0 && !is_static())
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
162 _receiver_slot_offset = slot_offset;
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
163
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
164 break;
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
165
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
166 case T_LONG:
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
167 case T_DOUBLE:
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
168 adjusted_offset--;
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
169 // fall through
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
170
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
171 default:
7195
2cd5e15048e6 8003868: fix shark for latest HotSpot and LLVM
twisti
parents: 2426
diff changeset
172 Type *param_type = SharkType::to_stackType(arg_type(i));
1692
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
173
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
174 param_types.push_back(param_type);
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
175 param_values.push_back(
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
176 builder()->CreateLoad(stack()->slot_addr(adjusted_offset, param_type)));
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
177 }
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
178 }
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
179
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
180 // The oopmap is now complete, and everything is written
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
181 // into the frame except the PC.
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
182 int pc_offset = code_buffer()->create_unique_offset();
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
183
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
184 _oop_maps = new OopMapSet();
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
185 oop_maps()->add_gc_map(pc_offset, oopmap);
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
186
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
187 builder()->CreateStore(
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
188 builder()->code_buffer_address(pc_offset),
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
189 stack()->slot_addr(stack()->pc_slot_offset()));
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
190
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
191 // Set up the Java frame anchor
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
192 stack()->CreateSetLastJavaFrame();
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
193
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
194 // Lock if necessary
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
195 if (is_synchronized())
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
196 Unimplemented();
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
197
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
198 // Change the thread state to _thread_in_native
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
199 CreateSetThreadState(_thread_in_native);
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
200
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
201 // Make the call
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
202 BasicType result_type = target()->result_type();
7195
2cd5e15048e6 8003868: fix shark for latest HotSpot and LLVM
twisti
parents: 2426
diff changeset
203 Type* return_type;
1692
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
204 if (result_type == T_VOID)
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
205 return_type = SharkType::void_type();
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
206 else if (is_returning_oop())
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
207 return_type = box_type;
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
208 else
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
209 return_type = SharkType::to_arrayType(result_type);
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
210 Value* native_function = builder()->CreateIntToPtr(
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
211 LLVMValue::intptr_constant((intptr_t) target()->native_function()),
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
212 PointerType::getUnqual(
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
213 FunctionType::get(return_type, param_types, false)));
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
214 Value *result = builder()->CreateCall(
7195
2cd5e15048e6 8003868: fix shark for latest HotSpot and LLVM
twisti
parents: 2426
diff changeset
215 native_function, llvm::makeArrayRef(param_values));
1692
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
216
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
217 // Start the transition back to _thread_in_Java
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
218 CreateSetThreadState(_thread_in_native_trans);
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
219
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
220 // Make sure new state is visible in the GC thread
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
221 if (os::is_MP()) {
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
222 if (UseMembar)
7195
2cd5e15048e6 8003868: fix shark for latest HotSpot and LLVM
twisti
parents: 2426
diff changeset
223 builder()->CreateFence(llvm::SequentiallyConsistent, llvm::CrossThread);
1692
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
224 else
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
225 CreateWriteMemorySerializePage();
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
226 }
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
227
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
228 // Handle safepoint operations, pending suspend requests,
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
229 // and pending asynchronous exceptions.
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
230 BasicBlock *check_thread = CreateBlock("check_thread");
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
231 BasicBlock *do_safepoint = CreateBlock("do_safepoint");
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
232 BasicBlock *safepointed = CreateBlock("safepointed");
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
233
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
234 Value *global_state = builder()->CreateLoad(
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
235 builder()->CreateIntToPtr(
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
236 LLVMValue::intptr_constant(
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
237 (intptr_t) SafepointSynchronize::address_of_state()),
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
238 PointerType::getUnqual(SharkType::jint_type())),
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
239 "global_state");
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
240
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
241 builder()->CreateCondBr(
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
242 builder()->CreateICmpNE(
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
243 global_state,
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
244 LLVMValue::jint_constant(SafepointSynchronize::_not_synchronized)),
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
245 do_safepoint, check_thread);
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
246
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
247 builder()->SetInsertPoint(check_thread);
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
248 Value *thread_state = builder()->CreateValueOfStructEntry(
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
249 thread,
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
250 JavaThread::suspend_flags_offset(),
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
251 SharkType::jint_type(),
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
252 "thread_state");
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
253
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
254 builder()->CreateCondBr(
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
255 builder()->CreateICmpNE(
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
256 thread_state,
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
257 LLVMValue::jint_constant(0)),
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
258 do_safepoint, safepointed);
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
259
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
260 builder()->SetInsertPoint(do_safepoint);
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
261 builder()->CreateCall(
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
262 builder()->check_special_condition_for_native_trans(), thread);
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
263 builder()->CreateBr(safepointed);
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
264
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
265 // Finally we can change the thread state to _thread_in_Java
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
266 builder()->SetInsertPoint(safepointed);
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
267 CreateSetThreadState(_thread_in_Java);
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
268
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
269 // Clear the frame anchor
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
270 stack()->CreateResetLastJavaFrame();
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
271
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
272 // If there is a pending exception then we can just unwind and
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
273 // return. It seems totally wrong that unlocking is skipped here
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
274 // but apparently the template interpreter does this so we do too.
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
275 BasicBlock *exception = CreateBlock("exception");
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
276 BasicBlock *no_exception = CreateBlock("no_exception");
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
277
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
278 builder()->CreateCondBr(
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
279 builder()->CreateICmpEQ(
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
280 CreateLoadPendingException(),
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
281 LLVMValue::null()),
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
282 no_exception, exception);
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
283
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
284 builder()->SetInsertPoint(exception);
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
285 CreateResetHandleBlock();
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
286 stack()->CreatePopFrame(0);
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
287 builder()->CreateRet(LLVMValue::jint_constant(0));
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
288
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
289 builder()->SetInsertPoint(no_exception);
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
290
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
291 // If the result was an oop then unbox it before
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
292 // releasing the handle it might be protected by
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
293 if (is_returning_oop()) {
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
294 BasicBlock *null = builder()->GetInsertBlock();
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
295 BasicBlock *not_null = CreateBlock("not_null");
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
296 BasicBlock *merge = CreateBlock("merge");
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
297
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
298 builder()->CreateCondBr(
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
299 builder()->CreateICmpNE(result, ConstantPointerNull::get(box_type)),
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
300 not_null, merge);
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
301
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
302 builder()->SetInsertPoint(not_null);
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
303 Value *unboxed_result = builder()->CreateLoad(result);
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
304 builder()->CreateBr(merge);
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
305
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
306 builder()->SetInsertPoint(merge);
7195
2cd5e15048e6 8003868: fix shark for latest HotSpot and LLVM
twisti
parents: 2426
diff changeset
307 PHINode *phi = builder()->CreatePHI(SharkType::oop_type(), 0, "result");
1692
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
308 phi->addIncoming(LLVMValue::null(), null);
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
309 phi->addIncoming(unboxed_result, not_null);
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
310 result = phi;
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
311 }
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
312
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
313 // Reset handle block
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
314 CreateResetHandleBlock();
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
315
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
316 // Unlock if necessary.
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
317 if (is_synchronized())
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
318 Unimplemented();
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
319
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
320 // Unwind and return
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
321 Value *result_addr = stack()->CreatePopFrame(type2size[result_type]);
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
322 if (result_type != T_VOID) {
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
323 bool needs_cast = false;
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
324 bool is_signed = false;
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
325 switch (result_type) {
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
326 case T_BOOLEAN:
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
327 result = builder()->CreateICmpNE(result, LLVMValue::jbyte_constant(0));
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
328 needs_cast = true;
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
329 break;
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
330
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
331 case T_CHAR:
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
332 needs_cast = true;
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
333 break;
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
334
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
335 case T_BYTE:
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
336 case T_SHORT:
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
337 needs_cast = true;
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
338 is_signed = true;
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
339 break;
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
340 }
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
341 if (needs_cast) {
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
342 result = builder()->CreateIntCast(
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
343 result, SharkType::to_stackType(result_type), is_signed);
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
344 }
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
345
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
346 builder()->CreateStore(
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
347 result,
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
348 builder()->CreateIntToPtr(
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
349 result_addr,
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
350 PointerType::getUnqual(SharkType::to_stackType(result_type))));
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
351 }
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
352 builder()->CreateRet(LLVMValue::jint_constant(0));
d2ede61b7a12 6976186: integrate Shark HotSpot changes
twisti
parents:
diff changeset
353 }