blob: 4992031f254d6b0ec68a540a6ade32880211b235 [file] [log] [blame]
Sebastien Hertz8ece0502013-08-07 11:26:41 +02001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "interpreter_common.h"
18
19namespace art {
20namespace interpreter {
21
Sebastien Hertzc61124b2013-09-10 11:44:19 +020022static void UnstartedRuntimeInvoke(Thread* self, MethodHelper& mh,
23 const DexFile::CodeItem* code_item, ShadowFrame* shadow_frame,
24 JValue* result, size_t arg_offset)
25 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
Sebastien Hertz8ece0502013-08-07 11:26:41 +020026
Sebastien Hertzc61124b2013-09-10 11:44:19 +020027template<bool is_range, bool do_assignability_check>
28bool DoCall(ArtMethod* method, Object* receiver, Thread* self, ShadowFrame& shadow_frame,
29 const Instruction* inst, uint16_t inst_data, JValue* result) {
30 // Compute method information.
Sebastien Hertz8ece0502013-08-07 11:26:41 +020031 MethodHelper mh(method);
32 const DexFile::CodeItem* code_item = mh.GetCodeItem();
Sebastien Hertzc61124b2013-09-10 11:44:19 +020033 const uint16_t num_ins = (is_range) ? inst->VRegA_3rc(inst_data) : inst->VRegA_35c(inst_data);
Sebastien Hertz8ece0502013-08-07 11:26:41 +020034 uint16_t num_regs;
Sebastien Hertz8ece0502013-08-07 11:26:41 +020035 if (LIKELY(code_item != NULL)) {
36 num_regs = code_item->registers_size_;
Sebastien Hertzc61124b2013-09-10 11:44:19 +020037 DCHECK_EQ(num_ins, code_item->ins_size_);
Sebastien Hertz8ece0502013-08-07 11:26:41 +020038 } else {
39 DCHECK(method->IsNative() || method->IsProxyMethod());
Sebastien Hertzc61124b2013-09-10 11:44:19 +020040 num_regs = num_ins;
Sebastien Hertz8ece0502013-08-07 11:26:41 +020041 }
42
Sebastien Hertzc61124b2013-09-10 11:44:19 +020043 // Allocate shadow frame on the stack.
Sebastien Hertz8ece0502013-08-07 11:26:41 +020044 void* memory = alloca(ShadowFrame::ComputeSize(num_regs));
45 ShadowFrame* new_shadow_frame(ShadowFrame::Create(num_regs, &shadow_frame, method, 0, memory));
Sebastien Hertzc61124b2013-09-10 11:44:19 +020046
47 // Initialize new shadow frame.
Sebastien Hertz8ece0502013-08-07 11:26:41 +020048 size_t cur_reg = num_regs - num_ins;
Sebastien Hertzc61124b2013-09-10 11:44:19 +020049 size_t arg_offset = 0;
Sebastien Hertz8ece0502013-08-07 11:26:41 +020050 if (receiver != NULL) {
Sebastien Hertzc61124b2013-09-10 11:44:19 +020051 DCHECK(!method->IsStatic());
Sebastien Hertz8ece0502013-08-07 11:26:41 +020052 new_shadow_frame->SetVRegReference(cur_reg, receiver);
53 ++cur_reg;
Sebastien Hertzc61124b2013-09-10 11:44:19 +020054 ++arg_offset;
55 } else {
56 DCHECK(method->IsStatic());
Sebastien Hertz8ece0502013-08-07 11:26:41 +020057 }
58
Jeff Haoa3faaf42013-09-03 19:07:00 -070059 const DexFile::TypeList* params;
60 if (do_assignability_check) {
61 params = mh.GetParameterTypeList();
62 }
Sebastien Hertz8ece0502013-08-07 11:26:41 +020063 const char* shorty = mh.GetShorty();
Sebastien Hertzc61124b2013-09-10 11:44:19 +020064 // TODO: find a cleaner way to separate non-range and range information.
65 uint32_t arg[5]; // only used in invoke-XXX.
66 uint32_t vregC; // only used in invoke-XXX-range.
67 if (is_range) {
68 vregC = inst->VRegC_3rc();
69 } else {
70 inst->GetArgs(arg, inst_data);
Sebastien Hertz8ece0502013-08-07 11:26:41 +020071 }
Sebastien Hertzc61124b2013-09-10 11:44:19 +020072 for (size_t shorty_pos = 0; cur_reg < num_regs; ++shorty_pos, ++cur_reg, ++arg_offset) {
Sebastien Hertz8ece0502013-08-07 11:26:41 +020073 DCHECK_LT(shorty_pos + 1, mh.GetShortyLength());
Sebastien Hertzc61124b2013-09-10 11:44:19 +020074 size_t arg_pos = (is_range) ? vregC + arg_offset : arg[arg_offset];
Sebastien Hertz8ece0502013-08-07 11:26:41 +020075 switch (shorty[shorty_pos + 1]) {
76 case 'L': {
77 Object* o = shadow_frame.GetVRegReference(arg_pos);
Jeff Haoa3faaf42013-09-03 19:07:00 -070078 if (do_assignability_check && o != NULL) {
79 Class* arg_type = mh.GetClassFromTypeIdx(params->GetTypeItem(shorty_pos).type_idx_);
80 if (arg_type == NULL) {
81 CHECK(self->IsExceptionPending());
82 return false;
83 }
84 if (!o->VerifierInstanceOf(arg_type)) {
85 // This should never happen.
86 self->ThrowNewExceptionF(self->GetCurrentLocationForThrow(),
87 "Ljava/lang/VirtualMachineError;",
88 "Invoking %s with bad arg %d, type '%s' not instance of '%s'",
89 mh.GetName(), shorty_pos,
90 ClassHelper(o->GetClass()).GetDescriptor(),
91 ClassHelper(arg_type).GetDescriptor());
92 return false;
93 }
94 }
Sebastien Hertz8ece0502013-08-07 11:26:41 +020095 new_shadow_frame->SetVRegReference(cur_reg, o);
96 break;
97 }
98 case 'J': case 'D': {
99 uint64_t wide_value = (static_cast<uint64_t>(shadow_frame.GetVReg(arg_pos + 1)) << 32) |
100 static_cast<uint32_t>(shadow_frame.GetVReg(arg_pos));
101 new_shadow_frame->SetVRegLong(cur_reg, wide_value);
Sebastien Hertzc61124b2013-09-10 11:44:19 +0200102 ++cur_reg;
103 ++arg_offset;
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200104 break;
105 }
106 default:
107 new_shadow_frame->SetVReg(cur_reg, shadow_frame.GetVReg(arg_pos));
108 break;
109 }
110 }
111
Sebastien Hertzc61124b2013-09-10 11:44:19 +0200112 // Do the call now.
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200113 if (LIKELY(Runtime::Current()->IsStarted())) {
114 (method->GetEntryPointFromInterpreter())(self, mh, code_item, new_shadow_frame, result);
115 } else {
116 UnstartedRuntimeInvoke(self, mh, code_item, new_shadow_frame, result, num_regs - num_ins);
117 }
118 return !self->IsExceptionPending();
119}
120
121template <bool is_range, bool do_access_check>
122bool DoFilledNewArray(const Instruction* inst, const ShadowFrame& shadow_frame,
123 Thread* self, JValue* result) {
124 DCHECK(inst->Opcode() == Instruction::FILLED_NEW_ARRAY ||
125 inst->Opcode() == Instruction::FILLED_NEW_ARRAY_RANGE);
126 const int32_t length = is_range ? inst->VRegA_3rc() : inst->VRegA_35c();
127 if (!is_range) {
128 // Checks FILLED_NEW_ARRAY's length does not exceed 5 arguments.
129 CHECK_LE(length, 5);
130 }
131 if (UNLIKELY(length < 0)) {
132 ThrowNegativeArraySizeException(length);
133 return false;
134 }
135 uint16_t type_idx = is_range ? inst->VRegB_3rc() : inst->VRegB_35c();
136 Class* arrayClass = ResolveVerifyAndClinit(type_idx, shadow_frame.GetMethod(),
137 self, false, do_access_check);
138 if (UNLIKELY(arrayClass == NULL)) {
139 DCHECK(self->IsExceptionPending());
140 return false;
141 }
142 CHECK(arrayClass->IsArrayClass());
143 Class* componentClass = arrayClass->GetComponentType();
144 if (UNLIKELY(componentClass->IsPrimitive() && !componentClass->IsPrimitiveInt())) {
145 if (componentClass->IsPrimitiveLong() || componentClass->IsPrimitiveDouble()) {
146 ThrowRuntimeException("Bad filled array request for type %s",
147 PrettyDescriptor(componentClass).c_str());
148 } else {
149 self->ThrowNewExceptionF(shadow_frame.GetCurrentLocationForThrow(),
150 "Ljava/lang/InternalError;",
151 "Found type %s; filled-new-array not implemented for anything but \'int\'",
152 PrettyDescriptor(componentClass).c_str());
153 }
154 return false;
155 }
156 Object* newArray = Array::Alloc(self, arrayClass, length);
157 if (UNLIKELY(newArray == NULL)) {
158 DCHECK(self->IsExceptionPending());
159 return false;
160 }
161 if (is_range) {
162 uint32_t vregC = inst->VRegC_3rc();
163 const bool is_primitive_int_component = componentClass->IsPrimitiveInt();
164 for (int32_t i = 0; i < length; ++i) {
165 if (is_primitive_int_component) {
166 newArray->AsIntArray()->Set(i, shadow_frame.GetVReg(vregC + i));
167 } else {
168 newArray->AsObjectArray<Object>()->Set(i, shadow_frame.GetVRegReference(vregC + i));
169 }
170 }
171 } else {
172 uint32_t arg[5];
173 inst->GetArgs(arg);
174 const bool is_primitive_int_component = componentClass->IsPrimitiveInt();
175 for (int32_t i = 0; i < length; ++i) {
176 if (is_primitive_int_component) {
177 newArray->AsIntArray()->Set(i, shadow_frame.GetVReg(arg[i]));
178 } else {
179 newArray->AsObjectArray<Object>()->Set(i, shadow_frame.GetVRegReference(arg[i]));
180 }
181 }
182 }
183
184 result->SetL(newArray);
185 return true;
186}
187
Sebastien Hertzc61124b2013-09-10 11:44:19 +0200188static void UnstartedRuntimeInvoke(Thread* self, MethodHelper& mh,
189 const DexFile::CodeItem* code_item, ShadowFrame* shadow_frame,
190 JValue* result, size_t arg_offset) {
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200191 // In a runtime that's not started we intercept certain methods to avoid complicated dependency
192 // problems in core libraries.
193 std::string name(PrettyMethod(shadow_frame->GetMethod()));
194 if (name == "java.lang.Class java.lang.Class.forName(java.lang.String)") {
195 std::string descriptor(DotToDescriptor(shadow_frame->GetVRegReference(arg_offset)->AsString()->ToModifiedUtf8().c_str()));
196 ClassLoader* class_loader = NULL; // shadow_frame.GetMethod()->GetDeclaringClass()->GetClassLoader();
197 Class* found = Runtime::Current()->GetClassLinker()->FindClass(descriptor.c_str(),
198 class_loader);
199 CHECK(found != NULL) << "Class.forName failed in un-started runtime for class: "
200 << PrettyDescriptor(descriptor);
201 result->SetL(found);
202 } else if (name == "java.lang.Object java.lang.Class.newInstance()") {
203 Class* klass = shadow_frame->GetVRegReference(arg_offset)->AsClass();
204 ArtMethod* c = klass->FindDeclaredDirectMethod("<init>", "()V");
205 CHECK(c != NULL);
206 SirtRef<Object> obj(self, klass->AllocObject(self));
207 CHECK(obj.get() != NULL);
208 EnterInterpreterFromInvoke(self, c, obj.get(), NULL, NULL);
209 result->SetL(obj.get());
210 } else if (name == "java.lang.reflect.Field java.lang.Class.getDeclaredField(java.lang.String)") {
211 // Special managed code cut-out to allow field lookup in a un-started runtime that'd fail
212 // going the reflective Dex way.
213 Class* klass = shadow_frame->GetVRegReference(arg_offset)->AsClass();
214 String* name = shadow_frame->GetVRegReference(arg_offset + 1)->AsString();
215 ArtField* found = NULL;
216 FieldHelper fh;
217 ObjectArray<ArtField>* fields = klass->GetIFields();
218 for (int32_t i = 0; i < fields->GetLength() && found == NULL; ++i) {
219 ArtField* f = fields->Get(i);
220 fh.ChangeField(f);
221 if (name->Equals(fh.GetName())) {
222 found = f;
223 }
224 }
225 if (found == NULL) {
226 fields = klass->GetSFields();
227 for (int32_t i = 0; i < fields->GetLength() && found == NULL; ++i) {
228 ArtField* f = fields->Get(i);
229 fh.ChangeField(f);
230 if (name->Equals(fh.GetName())) {
231 found = f;
232 }
233 }
234 }
235 CHECK(found != NULL)
236 << "Failed to find field in Class.getDeclaredField in un-started runtime. name="
237 << name->ToModifiedUtf8() << " class=" << PrettyDescriptor(klass);
238 // TODO: getDeclaredField calls GetType once the field is found to ensure a
239 // NoClassDefFoundError is thrown if the field's type cannot be resolved.
240 Class* jlr_Field = self->DecodeJObject(WellKnownClasses::java_lang_reflect_Field)->AsClass();
241 SirtRef<Object> field(self, jlr_Field->AllocObject(self));
242 CHECK(field.get() != NULL);
243 ArtMethod* c = jlr_Field->FindDeclaredDirectMethod("<init>", "(Ljava/lang/reflect/ArtField;)V");
244 uint32_t args[1];
245 args[0] = reinterpret_cast<uint32_t>(found);
246 EnterInterpreterFromInvoke(self, c, field.get(), args, NULL);
247 result->SetL(field.get());
248 } else if (name == "void java.lang.System.arraycopy(java.lang.Object, int, java.lang.Object, int, int)" ||
249 name == "void java.lang.System.arraycopy(char[], int, char[], int, int)") {
250 // Special case array copying without initializing System.
251 Class* ctype = shadow_frame->GetVRegReference(arg_offset)->GetClass()->GetComponentType();
252 jint srcPos = shadow_frame->GetVReg(arg_offset + 1);
253 jint dstPos = shadow_frame->GetVReg(arg_offset + 3);
254 jint length = shadow_frame->GetVReg(arg_offset + 4);
255 if (!ctype->IsPrimitive()) {
256 ObjectArray<Object>* src = shadow_frame->GetVRegReference(arg_offset)->AsObjectArray<Object>();
257 ObjectArray<Object>* dst = shadow_frame->GetVRegReference(arg_offset + 2)->AsObjectArray<Object>();
258 for (jint i = 0; i < length; ++i) {
259 dst->Set(dstPos + i, src->Get(srcPos + i));
260 }
261 } else if (ctype->IsPrimitiveChar()) {
262 CharArray* src = shadow_frame->GetVRegReference(arg_offset)->AsCharArray();
263 CharArray* dst = shadow_frame->GetVRegReference(arg_offset + 2)->AsCharArray();
264 for (jint i = 0; i < length; ++i) {
265 dst->Set(dstPos + i, src->Get(srcPos + i));
266 }
267 } else if (ctype->IsPrimitiveInt()) {
268 IntArray* src = shadow_frame->GetVRegReference(arg_offset)->AsIntArray();
269 IntArray* dst = shadow_frame->GetVRegReference(arg_offset + 2)->AsIntArray();
270 for (jint i = 0; i < length; ++i) {
271 dst->Set(dstPos + i, src->Get(srcPos + i));
272 }
273 } else {
274 UNIMPLEMENTED(FATAL) << "System.arraycopy of unexpected type: " << PrettyDescriptor(ctype);
275 }
276 } else {
277 // Not special, continue with regular interpreter execution.
278 artInterpreterToInterpreterBridge(self, mh, code_item, shadow_frame, result);
279 }
280}
281
Sebastien Hertzc61124b2013-09-10 11:44:19 +0200282// Explicit DoCall template function declarations.
283#define EXPLICIT_DO_CALL_TEMPLATE_DECL(_is_range, _do_assignability_check) \
284template bool DoCall<_is_range, _do_assignability_check>(ArtMethod* method, Object* receiver, \
285 Thread* self, ShadowFrame& shadow_frame, \
286 const Instruction* inst, \
287 uint16_t inst_data, JValue* result)
288EXPLICIT_DO_CALL_TEMPLATE_DECL(false, false);
289EXPLICIT_DO_CALL_TEMPLATE_DECL(false, true);
290EXPLICIT_DO_CALL_TEMPLATE_DECL(true, false);
291EXPLICIT_DO_CALL_TEMPLATE_DECL(true, true);
292#undef EXPLICIT_DO_CALL_TEMPLATE_DECL
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200293
294// Explicit DoFilledNewArray template function declarations.
295#define EXPLICIT_DO_FILLED_NEW_ARRAY_TEMPLATE_DECL(_is_range_, _check) \
296 template bool DoFilledNewArray<_is_range_, _check>(const Instruction* inst, \
297 const ShadowFrame& shadow_frame, \
298 Thread* self, JValue* result)
299EXPLICIT_DO_FILLED_NEW_ARRAY_TEMPLATE_DECL(false, false);
300EXPLICIT_DO_FILLED_NEW_ARRAY_TEMPLATE_DECL(false, true);
301EXPLICIT_DO_FILLED_NEW_ARRAY_TEMPLATE_DECL(true, false);
302EXPLICIT_DO_FILLED_NEW_ARRAY_TEMPLATE_DECL(true, true);
303#undef EXPLICIT_DO_FILLED_NEW_ARRAY_TEMPLATE_DECL
304
305} // namespace interpreter
306} // namespace art