blob: 3b708f6d8ff66eff3f91eb04ed30a892a5da804f [file] [log] [blame]
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +01001/*
2 * Copyright (C) 2014 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 "transaction.h"
18
19#include "base/stl_util.h"
20#include "base/logging.h"
21#include "gc/accounting/card_table-inl.h"
22#include "intern_table.h"
23#include "mirror/object-inl.h"
24#include "mirror/object_array-inl.h"
25
26#include <list>
27
28namespace art {
29
30// TODO: remove (only used for debugging purpose).
31static constexpr bool kEnableTransactionStats = false;
32
Sebastien Hertz1c80bec2015-02-03 11:58:06 +010033Transaction::Transaction()
34 : log_lock_("transaction log lock", kTransactionLogLock), aborted_(false) {
Mathieu Chartiere5f13e52015-02-24 09:37:21 -080035 CHECK(Runtime::Current()->IsAotCompiler());
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010036}
37
38Transaction::~Transaction() {
39 if (kEnableTransactionStats) {
40 MutexLock mu(Thread::Current(), log_lock_);
41 size_t objects_count = object_logs_.size();
42 size_t field_values_count = 0;
43 for (auto it : object_logs_) {
44 field_values_count += it.second.Size();
45 }
46 size_t array_count = array_logs_.size();
47 size_t array_values_count = 0;
48 for (auto it : array_logs_) {
49 array_values_count += it.second.Size();
50 }
51 size_t string_count = intern_string_logs_.size();
52 LOG(INFO) << "Transaction::~Transaction"
53 << ": objects_count=" << objects_count
54 << ", field_values_count=" << field_values_count
55 << ", array_count=" << array_count
56 << ", array_values_count=" << array_values_count
57 << ", string_count=" << string_count;
58 }
59}
60
Sebastien Hertz1c80bec2015-02-03 11:58:06 +010061void Transaction::Abort(const std::string& abort_message) {
62 MutexLock mu(Thread::Current(), log_lock_);
63 // We may abort more than once if the java.lang.InternalError thrown at the
64 // time of the abort has been caught during execution of a class initializer.
65 // We just keep the message of the first abort because it will cause the
66 // transaction to be rolled back anyway.
67 if (!aborted_) {
68 aborted_ = true;
69 abort_message_ = abort_message;
70 }
71}
72
Sebastien Hertzbd9cf9f2015-03-03 12:16:13 +010073void Transaction::ThrowInternalError(Thread* self, bool rethrow) {
74 if (kIsDebugBuild && rethrow) {
75 CHECK(IsAborted()) << "Rethrow InternalError while transaction is not aborted";
76 }
Sebastien Hertz1c80bec2015-02-03 11:58:06 +010077 std::string abort_msg(GetAbortMessage());
Andreas Gampe2969bcd2015-03-09 12:57:41 -070078 self->ThrowNewWrappedException("Ljava/lang/InternalError;", abort_msg.c_str());
Sebastien Hertz1c80bec2015-02-03 11:58:06 +010079}
80
81bool Transaction::IsAborted() {
82 MutexLock mu(Thread::Current(), log_lock_);
83 return aborted_;
84}
85
86const std::string& Transaction::GetAbortMessage() {
87 MutexLock mu(Thread::Current(), log_lock_);
88 return abort_message_;
89}
90
Fred Shih37f05ef2014-07-16 18:38:08 -070091void Transaction::RecordWriteFieldBoolean(mirror::Object* obj, MemberOffset field_offset,
92 uint8_t value, bool is_volatile) {
93 DCHECK(obj != nullptr);
94 MutexLock mu(Thread::Current(), log_lock_);
95 ObjectLog& object_log = object_logs_[obj];
96 object_log.LogBooleanValue(field_offset, value, is_volatile);
97}
98
99void Transaction::RecordWriteFieldByte(mirror::Object* obj, MemberOffset field_offset,
100 int8_t value, bool is_volatile) {
101 DCHECK(obj != nullptr);
102 MutexLock mu(Thread::Current(), log_lock_);
103 ObjectLog& object_log = object_logs_[obj];
104 object_log.LogByteValue(field_offset, value, is_volatile);
105}
106
107void Transaction::RecordWriteFieldChar(mirror::Object* obj, MemberOffset field_offset,
108 uint16_t value, bool is_volatile) {
109 DCHECK(obj != nullptr);
110 MutexLock mu(Thread::Current(), log_lock_);
111 ObjectLog& object_log = object_logs_[obj];
112 object_log.LogCharValue(field_offset, value, is_volatile);
113}
114
115
116void Transaction::RecordWriteFieldShort(mirror::Object* obj, MemberOffset field_offset,
117 int16_t value, bool is_volatile) {
118 DCHECK(obj != nullptr);
119 MutexLock mu(Thread::Current(), log_lock_);
120 ObjectLog& object_log = object_logs_[obj];
121 object_log.LogShortValue(field_offset, value, is_volatile);
122}
123
124
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100125void Transaction::RecordWriteField32(mirror::Object* obj, MemberOffset field_offset, uint32_t value,
126 bool is_volatile) {
127 DCHECK(obj != nullptr);
128 MutexLock mu(Thread::Current(), log_lock_);
129 ObjectLog& object_log = object_logs_[obj];
130 object_log.Log32BitsValue(field_offset, value, is_volatile);
131}
132
133void Transaction::RecordWriteField64(mirror::Object* obj, MemberOffset field_offset, uint64_t value,
134 bool is_volatile) {
135 DCHECK(obj != nullptr);
136 MutexLock mu(Thread::Current(), log_lock_);
137 ObjectLog& object_log = object_logs_[obj];
138 object_log.Log64BitsValue(field_offset, value, is_volatile);
139}
140
141void Transaction::RecordWriteFieldReference(mirror::Object* obj, MemberOffset field_offset,
142 mirror::Object* value, bool is_volatile) {
143 DCHECK(obj != nullptr);
144 MutexLock mu(Thread::Current(), log_lock_);
145 ObjectLog& object_log = object_logs_[obj];
146 object_log.LogReferenceValue(field_offset, value, is_volatile);
147}
148
149void Transaction::RecordWriteArray(mirror::Array* array, size_t index, uint64_t value) {
150 DCHECK(array != nullptr);
151 DCHECK(array->IsArrayInstance());
Sebastien Hertzee1d79a2014-02-21 15:46:30 +0100152 DCHECK(!array->IsObjectArray());
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100153 MutexLock mu(Thread::Current(), log_lock_);
154 ArrayLog& array_log = array_logs_[array];
155 array_log.LogValue(index, value);
156}
157
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700158void Transaction::RecordStrongStringInsertion(mirror::String* s) {
159 InternStringLog log(s, InternStringLog::kStrongString, InternStringLog::kInsert);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100160 LogInternedString(log);
161}
162
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700163void Transaction::RecordWeakStringInsertion(mirror::String* s) {
164 InternStringLog log(s, InternStringLog::kWeakString, InternStringLog::kInsert);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100165 LogInternedString(log);
166}
167
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700168void Transaction::RecordStrongStringRemoval(mirror::String* s) {
169 InternStringLog log(s, InternStringLog::kStrongString, InternStringLog::kRemove);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100170 LogInternedString(log);
171}
172
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700173void Transaction::RecordWeakStringRemoval(mirror::String* s) {
174 InternStringLog log(s, InternStringLog::kWeakString, InternStringLog::kRemove);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100175 LogInternedString(log);
176}
177
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700178void Transaction::LogInternedString(const InternStringLog& log) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100179 Locks::intern_table_lock_->AssertExclusiveHeld(Thread::Current());
180 MutexLock mu(Thread::Current(), log_lock_);
181 intern_string_logs_.push_front(log);
182}
183
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100184void Transaction::Rollback() {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100185 CHECK(!Runtime::Current()->IsActiveTransaction());
186 Thread* self = Thread::Current();
187 self->AssertNoPendingException();
188 MutexLock mu1(self, *Locks::intern_table_lock_);
189 MutexLock mu2(self, log_lock_);
190 UndoObjectModifications();
191 UndoArrayModifications();
192 UndoInternStringTableModifications();
193}
194
195void Transaction::UndoObjectModifications() {
196 // TODO we may not need to restore objects allocated during this transaction. Or we could directly
197 // remove them from the heap.
198 for (auto it : object_logs_) {
199 it.second.Undo(it.first);
200 }
201 object_logs_.clear();
202}
203
204void Transaction::UndoArrayModifications() {
205 // TODO we may not need to restore array allocated during this transaction. Or we could directly
206 // remove them from the heap.
207 for (auto it : array_logs_) {
208 it.second.Undo(it.first);
209 }
210 array_logs_.clear();
211}
212
213void Transaction::UndoInternStringTableModifications() {
214 InternTable* const intern_table = Runtime::Current()->GetInternTable();
215 // We want to undo each operation from the most recent to the oldest. List has been filled so the
216 // most recent operation is at list begin so just have to iterate over it.
217 for (InternStringLog& string_log : intern_string_logs_) {
218 string_log.Undo(intern_table);
219 }
220 intern_string_logs_.clear();
221}
222
223void Transaction::VisitRoots(RootCallback* callback, void* arg) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100224 MutexLock mu(Thread::Current(), log_lock_);
225 VisitObjectLogs(callback, arg);
226 VisitArrayLogs(callback, arg);
227 VisitStringLogs(callback, arg);
228}
229
230void Transaction::VisitObjectLogs(RootCallback* callback, void* arg) {
231 // List of moving roots.
232 typedef std::pair<mirror::Object*, mirror::Object*> ObjectPair;
233 std::list<ObjectPair> moving_roots;
234
235 // Visit roots.
236 for (auto it : object_logs_) {
237 it.second.VisitRoots(callback, arg);
238 mirror::Object* old_root = it.first;
Mathieu Chartier815873e2014-02-13 18:02:13 -0800239 mirror::Object* new_root = old_root;
Mathieu Chartiere34fa1d2015-01-14 14:55:47 -0800240 callback(&new_root, arg, RootInfo(kRootUnknown));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100241 if (new_root != old_root) {
242 moving_roots.push_back(std::make_pair(old_root, new_root));
243 }
244 }
245
246 // Update object logs with moving roots.
247 for (const ObjectPair& pair : moving_roots) {
248 mirror::Object* old_root = pair.first;
249 mirror::Object* new_root = pair.second;
250 auto old_root_it = object_logs_.find(old_root);
251 CHECK(old_root_it != object_logs_.end());
252 CHECK(object_logs_.find(new_root) == object_logs_.end());
253 object_logs_.insert(std::make_pair(new_root, old_root_it->second));
254 object_logs_.erase(old_root_it);
255 }
256}
257
258void Transaction::VisitArrayLogs(RootCallback* callback, void* arg) {
259 // List of moving roots.
260 typedef std::pair<mirror::Array*, mirror::Array*> ArrayPair;
261 std::list<ArrayPair> moving_roots;
262
263 for (auto it : array_logs_) {
264 mirror::Array* old_root = it.first;
Sebastien Hertzee1d79a2014-02-21 15:46:30 +0100265 CHECK(!old_root->IsObjectArray());
Mathieu Chartier815873e2014-02-13 18:02:13 -0800266 mirror::Array* new_root = old_root;
Mathieu Chartiere34fa1d2015-01-14 14:55:47 -0800267 callback(reinterpret_cast<mirror::Object**>(&new_root), arg, RootInfo(kRootUnknown));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100268 if (new_root != old_root) {
269 moving_roots.push_back(std::make_pair(old_root, new_root));
270 }
271 }
272
273 // Update array logs with moving roots.
274 for (const ArrayPair& pair : moving_roots) {
275 mirror::Array* old_root = pair.first;
276 mirror::Array* new_root = pair.second;
277 auto old_root_it = array_logs_.find(old_root);
278 CHECK(old_root_it != array_logs_.end());
279 CHECK(array_logs_.find(new_root) == array_logs_.end());
280 array_logs_.insert(std::make_pair(new_root, old_root_it->second));
281 array_logs_.erase(old_root_it);
282 }
283}
284
285void Transaction::VisitStringLogs(RootCallback* callback, void* arg) {
286 for (InternStringLog& log : intern_string_logs_) {
287 log.VisitRoots(callback, arg);
288 }
289}
290
Fred Shih37f05ef2014-07-16 18:38:08 -0700291void Transaction::ObjectLog::LogBooleanValue(MemberOffset offset, uint8_t value, bool is_volatile) {
292 LogValue(ObjectLog::kBoolean, offset, value, is_volatile);
293}
294
295void Transaction::ObjectLog::LogByteValue(MemberOffset offset, int8_t value, bool is_volatile) {
296 LogValue(ObjectLog::kByte, offset, value, is_volatile);
297}
298
299void Transaction::ObjectLog::LogCharValue(MemberOffset offset, uint16_t value, bool is_volatile) {
300 LogValue(ObjectLog::kChar, offset, value, is_volatile);
301}
302
303void Transaction::ObjectLog::LogShortValue(MemberOffset offset, int16_t value, bool is_volatile) {
304 LogValue(ObjectLog::kShort, offset, value, is_volatile);
305}
306
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100307void Transaction::ObjectLog::Log32BitsValue(MemberOffset offset, uint32_t value, bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700308 LogValue(ObjectLog::k32Bits, offset, value, is_volatile);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100309}
310
311void Transaction::ObjectLog::Log64BitsValue(MemberOffset offset, uint64_t value, bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700312 LogValue(ObjectLog::k64Bits, offset, value, is_volatile);
313}
314
315void Transaction::ObjectLog::LogReferenceValue(MemberOffset offset, mirror::Object* obj, bool is_volatile) {
316 LogValue(ObjectLog::kReference, offset, reinterpret_cast<uintptr_t>(obj), is_volatile);
317}
318
319void Transaction::ObjectLog::LogValue(ObjectLog::FieldValueKind kind,
320 MemberOffset offset, uint64_t value, bool is_volatile) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100321 auto it = field_values_.find(offset.Uint32Value());
322 if (it == field_values_.end()) {
323 ObjectLog::FieldValue field_value;
324 field_value.value = value;
325 field_value.is_volatile = is_volatile;
Fred Shih37f05ef2014-07-16 18:38:08 -0700326 field_value.kind = kind;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100327 field_values_.insert(std::make_pair(offset.Uint32Value(), field_value));
328 }
329}
330
331void Transaction::ObjectLog::Undo(mirror::Object* obj) {
332 for (auto& it : field_values_) {
333 // Garbage collector needs to access object's class and array's length. So we don't rollback
334 // these values.
335 MemberOffset field_offset(it.first);
336 if (field_offset.Uint32Value() == mirror::Class::ClassOffset().Uint32Value()) {
337 // Skip Object::class field.
338 continue;
339 }
340 if (obj->IsArrayInstance() &&
341 field_offset.Uint32Value() == mirror::Array::LengthOffset().Uint32Value()) {
342 // Skip Array::length field.
343 continue;
344 }
345 FieldValue& field_value = it.second;
346 UndoFieldWrite(obj, field_offset, field_value);
347 }
348}
349
350void Transaction::ObjectLog::UndoFieldWrite(mirror::Object* obj, MemberOffset field_offset,
351 const FieldValue& field_value) {
352 // TODO We may want to abort a transaction while still being in transaction mode. In this case,
353 // we'd need to disable the check.
354 constexpr bool kCheckTransaction = true;
355 switch (field_value.kind) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700356 case kBoolean:
357 if (UNLIKELY(field_value.is_volatile)) {
358 obj->SetFieldBooleanVolatile<false, kCheckTransaction>(field_offset,
359 static_cast<bool>(field_value.value));
360 } else {
361 obj->SetFieldBoolean<false, kCheckTransaction>(field_offset,
362 static_cast<bool>(field_value.value));
363 }
364 break;
365 case kByte:
366 if (UNLIKELY(field_value.is_volatile)) {
367 obj->SetFieldByteVolatile<false, kCheckTransaction>(field_offset,
368 static_cast<int8_t>(field_value.value));
369 } else {
370 obj->SetFieldByte<false, kCheckTransaction>(field_offset,
371 static_cast<int8_t>(field_value.value));
372 }
373 break;
374 case kChar:
375 if (UNLIKELY(field_value.is_volatile)) {
376 obj->SetFieldCharVolatile<false, kCheckTransaction>(field_offset,
377 static_cast<uint16_t>(field_value.value));
378 } else {
379 obj->SetFieldChar<false, kCheckTransaction>(field_offset,
380 static_cast<uint16_t>(field_value.value));
381 }
382 break;
383 case kShort:
384 if (UNLIKELY(field_value.is_volatile)) {
385 obj->SetFieldShortVolatile<false, kCheckTransaction>(field_offset,
386 static_cast<int16_t>(field_value.value));
387 } else {
388 obj->SetFieldShort<false, kCheckTransaction>(field_offset,
389 static_cast<int16_t>(field_value.value));
390 }
391 break;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100392 case k32Bits:
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700393 if (UNLIKELY(field_value.is_volatile)) {
394 obj->SetField32Volatile<false, kCheckTransaction>(field_offset,
395 static_cast<uint32_t>(field_value.value));
396 } else {
397 obj->SetField32<false, kCheckTransaction>(field_offset,
398 static_cast<uint32_t>(field_value.value));
399 }
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100400 break;
401 case k64Bits:
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700402 if (UNLIKELY(field_value.is_volatile)) {
403 obj->SetField64Volatile<false, kCheckTransaction>(field_offset, field_value.value);
404 } else {
405 obj->SetField64<false, kCheckTransaction>(field_offset, field_value.value);
406 }
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100407 break;
408 case kReference:
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700409 if (UNLIKELY(field_value.is_volatile)) {
410 obj->SetFieldObjectVolatile<false, kCheckTransaction>(field_offset,
411 reinterpret_cast<mirror::Object*>(field_value.value));
412 } else {
413 obj->SetFieldObject<false, kCheckTransaction>(field_offset,
414 reinterpret_cast<mirror::Object*>(field_value.value));
415 }
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100416 break;
417 default:
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700418 LOG(FATAL) << "Unknown value kind " << static_cast<int>(field_value.kind);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100419 break;
420 }
421}
422
423void Transaction::ObjectLog::VisitRoots(RootCallback* callback, void* arg) {
424 for (auto it : field_values_) {
425 FieldValue& field_value = it.second;
426 if (field_value.kind == ObjectLog::kReference) {
Mathieu Chartier815873e2014-02-13 18:02:13 -0800427 mirror::Object* obj =
428 reinterpret_cast<mirror::Object*>(static_cast<uintptr_t>(field_value.value));
Sebastien Hertza559ccb2014-02-21 15:36:13 +0100429 if (obj != nullptr) {
Mathieu Chartiere34fa1d2015-01-14 14:55:47 -0800430 callback(&obj, arg, RootInfo(kRootUnknown));
Sebastien Hertza559ccb2014-02-21 15:36:13 +0100431 field_value.value = reinterpret_cast<uintptr_t>(obj);
432 }
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100433 }
434 }
435}
436
437void Transaction::InternStringLog::Undo(InternTable* intern_table) {
438 DCHECK(intern_table != nullptr);
439 switch (string_op_) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700440 case InternStringLog::kInsert: {
441 switch (string_kind_) {
442 case InternStringLog::kStrongString:
443 intern_table->RemoveStrongFromTransaction(str_);
444 break;
445 case InternStringLog::kWeakString:
446 intern_table->RemoveWeakFromTransaction(str_);
447 break;
448 default:
449 LOG(FATAL) << "Unknown interned string kind";
450 break;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100451 }
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700452 break;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100453 }
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700454 case InternStringLog::kRemove: {
455 switch (string_kind_) {
456 case InternStringLog::kStrongString:
457 intern_table->InsertStrongFromTransaction(str_);
458 break;
459 case InternStringLog::kWeakString:
460 intern_table->InsertWeakFromTransaction(str_);
461 break;
462 default:
463 LOG(FATAL) << "Unknown interned string kind";
464 break;
465 }
466 break;
467 }
468 default:
469 LOG(FATAL) << "Unknown interned string op";
470 break;
471 }
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100472}
473
474void Transaction::InternStringLog::VisitRoots(RootCallback* callback, void* arg) {
Mathieu Chartiere34fa1d2015-01-14 14:55:47 -0800475 callback(reinterpret_cast<mirror::Object**>(&str_), arg, RootInfo(kRootInternedString));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100476}
477
478void Transaction::ArrayLog::LogValue(size_t index, uint64_t value) {
479 auto it = array_values_.find(index);
480 if (it == array_values_.end()) {
481 array_values_.insert(std::make_pair(index, value));
482 }
483}
484
485void Transaction::ArrayLog::Undo(mirror::Array* array) {
486 DCHECK(array != nullptr);
487 DCHECK(array->IsArrayInstance());
488 Primitive::Type type = array->GetClass()->GetComponentType()->GetPrimitiveType();
489 for (auto it : array_values_) {
490 UndoArrayWrite(array, type, it.first, it.second);
491 }
492}
493
494void Transaction::ArrayLog::UndoArrayWrite(mirror::Array* array, Primitive::Type array_type,
495 size_t index, uint64_t value) {
496 // TODO We may want to abort a transaction while still being in transaction mode. In this case,
497 // we'd need to disable the check.
498 switch (array_type) {
499 case Primitive::kPrimBoolean:
500 array->AsBooleanArray()->SetWithoutChecks<false>(index, static_cast<uint8_t>(value));
501 break;
502 case Primitive::kPrimByte:
503 array->AsByteArray()->SetWithoutChecks<false>(index, static_cast<int8_t>(value));
504 break;
505 case Primitive::kPrimChar:
506 array->AsCharArray()->SetWithoutChecks<false>(index, static_cast<uint16_t>(value));
507 break;
508 case Primitive::kPrimShort:
509 array->AsShortArray()->SetWithoutChecks<false>(index, static_cast<int16_t>(value));
510 break;
511 case Primitive::kPrimInt:
512 array->AsIntArray()->SetWithoutChecks<false>(index, static_cast<int32_t>(value));
513 break;
514 case Primitive::kPrimFloat:
515 array->AsFloatArray()->SetWithoutChecks<false>(index, static_cast<float>(value));
516 break;
517 case Primitive::kPrimLong:
518 array->AsLongArray()->SetWithoutChecks<false>(index, static_cast<int64_t>(value));
519 break;
520 case Primitive::kPrimDouble:
521 array->AsDoubleArray()->SetWithoutChecks<false>(index, static_cast<double>(value));
522 break;
Sebastien Hertzee1d79a2014-02-21 15:46:30 +0100523 case Primitive::kPrimNot:
524 LOG(FATAL) << "ObjectArray should be treated as Object";
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100525 break;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100526 default:
527 LOG(FATAL) << "Unsupported type " << array_type;
528 }
529}
530
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100531} // namespace art