blob: 186cfea0fec97854a5ce1e0eed6d533cf5020801 [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 Gampe328dd442015-04-01 14:28:09 -070078 // Temporary workaround for b/20019689.
79 if (self->IsExceptionPending()) {
80 self->ClearException();
81 }
82 self->ThrowNewException("Ljava/lang/InternalError;", abort_msg.c_str());
Sebastien Hertz1c80bec2015-02-03 11:58:06 +010083}
84
85bool Transaction::IsAborted() {
86 MutexLock mu(Thread::Current(), log_lock_);
87 return aborted_;
88}
89
90const std::string& Transaction::GetAbortMessage() {
91 MutexLock mu(Thread::Current(), log_lock_);
92 return abort_message_;
93}
94
Fred Shih37f05ef2014-07-16 18:38:08 -070095void Transaction::RecordWriteFieldBoolean(mirror::Object* obj, MemberOffset field_offset,
96 uint8_t value, bool is_volatile) {
97 DCHECK(obj != nullptr);
98 MutexLock mu(Thread::Current(), log_lock_);
99 ObjectLog& object_log = object_logs_[obj];
100 object_log.LogBooleanValue(field_offset, value, is_volatile);
101}
102
103void Transaction::RecordWriteFieldByte(mirror::Object* obj, MemberOffset field_offset,
104 int8_t value, bool is_volatile) {
105 DCHECK(obj != nullptr);
106 MutexLock mu(Thread::Current(), log_lock_);
107 ObjectLog& object_log = object_logs_[obj];
108 object_log.LogByteValue(field_offset, value, is_volatile);
109}
110
111void Transaction::RecordWriteFieldChar(mirror::Object* obj, MemberOffset field_offset,
112 uint16_t value, bool is_volatile) {
113 DCHECK(obj != nullptr);
114 MutexLock mu(Thread::Current(), log_lock_);
115 ObjectLog& object_log = object_logs_[obj];
116 object_log.LogCharValue(field_offset, value, is_volatile);
117}
118
119
120void Transaction::RecordWriteFieldShort(mirror::Object* obj, MemberOffset field_offset,
121 int16_t value, bool is_volatile) {
122 DCHECK(obj != nullptr);
123 MutexLock mu(Thread::Current(), log_lock_);
124 ObjectLog& object_log = object_logs_[obj];
125 object_log.LogShortValue(field_offset, value, is_volatile);
126}
127
128
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100129void Transaction::RecordWriteField32(mirror::Object* obj, MemberOffset field_offset, uint32_t value,
130 bool is_volatile) {
131 DCHECK(obj != nullptr);
132 MutexLock mu(Thread::Current(), log_lock_);
133 ObjectLog& object_log = object_logs_[obj];
134 object_log.Log32BitsValue(field_offset, value, is_volatile);
135}
136
137void Transaction::RecordWriteField64(mirror::Object* obj, MemberOffset field_offset, uint64_t value,
138 bool is_volatile) {
139 DCHECK(obj != nullptr);
140 MutexLock mu(Thread::Current(), log_lock_);
141 ObjectLog& object_log = object_logs_[obj];
142 object_log.Log64BitsValue(field_offset, value, is_volatile);
143}
144
145void Transaction::RecordWriteFieldReference(mirror::Object* obj, MemberOffset field_offset,
146 mirror::Object* value, bool is_volatile) {
147 DCHECK(obj != nullptr);
148 MutexLock mu(Thread::Current(), log_lock_);
149 ObjectLog& object_log = object_logs_[obj];
150 object_log.LogReferenceValue(field_offset, value, is_volatile);
151}
152
153void Transaction::RecordWriteArray(mirror::Array* array, size_t index, uint64_t value) {
154 DCHECK(array != nullptr);
155 DCHECK(array->IsArrayInstance());
Sebastien Hertzee1d79a2014-02-21 15:46:30 +0100156 DCHECK(!array->IsObjectArray());
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100157 MutexLock mu(Thread::Current(), log_lock_);
158 ArrayLog& array_log = array_logs_[array];
159 array_log.LogValue(index, value);
160}
161
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700162void Transaction::RecordStrongStringInsertion(mirror::String* s) {
163 InternStringLog log(s, InternStringLog::kStrongString, InternStringLog::kInsert);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100164 LogInternedString(log);
165}
166
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700167void Transaction::RecordWeakStringInsertion(mirror::String* s) {
168 InternStringLog log(s, InternStringLog::kWeakString, InternStringLog::kInsert);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100169 LogInternedString(log);
170}
171
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700172void Transaction::RecordStrongStringRemoval(mirror::String* s) {
173 InternStringLog log(s, InternStringLog::kStrongString, InternStringLog::kRemove);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100174 LogInternedString(log);
175}
176
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700177void Transaction::RecordWeakStringRemoval(mirror::String* s) {
178 InternStringLog log(s, InternStringLog::kWeakString, InternStringLog::kRemove);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100179 LogInternedString(log);
180}
181
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700182void Transaction::LogInternedString(const InternStringLog& log) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100183 Locks::intern_table_lock_->AssertExclusiveHeld(Thread::Current());
184 MutexLock mu(Thread::Current(), log_lock_);
185 intern_string_logs_.push_front(log);
186}
187
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100188void Transaction::Rollback() {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100189 CHECK(!Runtime::Current()->IsActiveTransaction());
190 Thread* self = Thread::Current();
191 self->AssertNoPendingException();
192 MutexLock mu1(self, *Locks::intern_table_lock_);
193 MutexLock mu2(self, log_lock_);
194 UndoObjectModifications();
195 UndoArrayModifications();
196 UndoInternStringTableModifications();
197}
198
199void Transaction::UndoObjectModifications() {
200 // TODO we may not need to restore objects allocated during this transaction. Or we could directly
201 // remove them from the heap.
202 for (auto it : object_logs_) {
203 it.second.Undo(it.first);
204 }
205 object_logs_.clear();
206}
207
208void Transaction::UndoArrayModifications() {
209 // TODO we may not need to restore array allocated during this transaction. Or we could directly
210 // remove them from the heap.
211 for (auto it : array_logs_) {
212 it.second.Undo(it.first);
213 }
214 array_logs_.clear();
215}
216
217void Transaction::UndoInternStringTableModifications() {
218 InternTable* const intern_table = Runtime::Current()->GetInternTable();
219 // We want to undo each operation from the most recent to the oldest. List has been filled so the
220 // most recent operation is at list begin so just have to iterate over it.
221 for (InternStringLog& string_log : intern_string_logs_) {
222 string_log.Undo(intern_table);
223 }
224 intern_string_logs_.clear();
225}
226
227void Transaction::VisitRoots(RootCallback* callback, void* arg) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100228 MutexLock mu(Thread::Current(), log_lock_);
229 VisitObjectLogs(callback, arg);
230 VisitArrayLogs(callback, arg);
231 VisitStringLogs(callback, arg);
232}
233
234void Transaction::VisitObjectLogs(RootCallback* callback, void* arg) {
235 // List of moving roots.
236 typedef std::pair<mirror::Object*, mirror::Object*> ObjectPair;
237 std::list<ObjectPair> moving_roots;
238
239 // Visit roots.
240 for (auto it : object_logs_) {
241 it.second.VisitRoots(callback, arg);
242 mirror::Object* old_root = it.first;
Mathieu Chartier815873e2014-02-13 18:02:13 -0800243 mirror::Object* new_root = old_root;
Mathieu Chartiere34fa1d2015-01-14 14:55:47 -0800244 callback(&new_root, arg, RootInfo(kRootUnknown));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100245 if (new_root != old_root) {
246 moving_roots.push_back(std::make_pair(old_root, new_root));
247 }
248 }
249
250 // Update object logs with moving roots.
251 for (const ObjectPair& pair : moving_roots) {
252 mirror::Object* old_root = pair.first;
253 mirror::Object* new_root = pair.second;
254 auto old_root_it = object_logs_.find(old_root);
255 CHECK(old_root_it != object_logs_.end());
256 CHECK(object_logs_.find(new_root) == object_logs_.end());
257 object_logs_.insert(std::make_pair(new_root, old_root_it->second));
258 object_logs_.erase(old_root_it);
259 }
260}
261
262void Transaction::VisitArrayLogs(RootCallback* callback, void* arg) {
263 // List of moving roots.
264 typedef std::pair<mirror::Array*, mirror::Array*> ArrayPair;
265 std::list<ArrayPair> moving_roots;
266
267 for (auto it : array_logs_) {
268 mirror::Array* old_root = it.first;
Sebastien Hertzee1d79a2014-02-21 15:46:30 +0100269 CHECK(!old_root->IsObjectArray());
Mathieu Chartier815873e2014-02-13 18:02:13 -0800270 mirror::Array* new_root = old_root;
Mathieu Chartiere34fa1d2015-01-14 14:55:47 -0800271 callback(reinterpret_cast<mirror::Object**>(&new_root), arg, RootInfo(kRootUnknown));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100272 if (new_root != old_root) {
273 moving_roots.push_back(std::make_pair(old_root, new_root));
274 }
275 }
276
277 // Update array logs with moving roots.
278 for (const ArrayPair& pair : moving_roots) {
279 mirror::Array* old_root = pair.first;
280 mirror::Array* new_root = pair.second;
281 auto old_root_it = array_logs_.find(old_root);
282 CHECK(old_root_it != array_logs_.end());
283 CHECK(array_logs_.find(new_root) == array_logs_.end());
284 array_logs_.insert(std::make_pair(new_root, old_root_it->second));
285 array_logs_.erase(old_root_it);
286 }
287}
288
289void Transaction::VisitStringLogs(RootCallback* callback, void* arg) {
290 for (InternStringLog& log : intern_string_logs_) {
291 log.VisitRoots(callback, arg);
292 }
293}
294
Fred Shih37f05ef2014-07-16 18:38:08 -0700295void Transaction::ObjectLog::LogBooleanValue(MemberOffset offset, uint8_t value, bool is_volatile) {
296 LogValue(ObjectLog::kBoolean, offset, value, is_volatile);
297}
298
299void Transaction::ObjectLog::LogByteValue(MemberOffset offset, int8_t value, bool is_volatile) {
300 LogValue(ObjectLog::kByte, offset, value, is_volatile);
301}
302
303void Transaction::ObjectLog::LogCharValue(MemberOffset offset, uint16_t value, bool is_volatile) {
304 LogValue(ObjectLog::kChar, offset, value, is_volatile);
305}
306
307void Transaction::ObjectLog::LogShortValue(MemberOffset offset, int16_t value, bool is_volatile) {
308 LogValue(ObjectLog::kShort, offset, value, is_volatile);
309}
310
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100311void Transaction::ObjectLog::Log32BitsValue(MemberOffset offset, uint32_t value, bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700312 LogValue(ObjectLog::k32Bits, offset, value, is_volatile);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100313}
314
315void Transaction::ObjectLog::Log64BitsValue(MemberOffset offset, uint64_t value, bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700316 LogValue(ObjectLog::k64Bits, offset, value, is_volatile);
317}
318
319void Transaction::ObjectLog::LogReferenceValue(MemberOffset offset, mirror::Object* obj, bool is_volatile) {
320 LogValue(ObjectLog::kReference, offset, reinterpret_cast<uintptr_t>(obj), is_volatile);
321}
322
323void Transaction::ObjectLog::LogValue(ObjectLog::FieldValueKind kind,
324 MemberOffset offset, uint64_t value, bool is_volatile) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100325 auto it = field_values_.find(offset.Uint32Value());
326 if (it == field_values_.end()) {
327 ObjectLog::FieldValue field_value;
328 field_value.value = value;
329 field_value.is_volatile = is_volatile;
Fred Shih37f05ef2014-07-16 18:38:08 -0700330 field_value.kind = kind;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100331 field_values_.insert(std::make_pair(offset.Uint32Value(), field_value));
332 }
333}
334
335void Transaction::ObjectLog::Undo(mirror::Object* obj) {
336 for (auto& it : field_values_) {
337 // Garbage collector needs to access object's class and array's length. So we don't rollback
338 // these values.
339 MemberOffset field_offset(it.first);
340 if (field_offset.Uint32Value() == mirror::Class::ClassOffset().Uint32Value()) {
341 // Skip Object::class field.
342 continue;
343 }
344 if (obj->IsArrayInstance() &&
345 field_offset.Uint32Value() == mirror::Array::LengthOffset().Uint32Value()) {
346 // Skip Array::length field.
347 continue;
348 }
349 FieldValue& field_value = it.second;
350 UndoFieldWrite(obj, field_offset, field_value);
351 }
352}
353
354void Transaction::ObjectLog::UndoFieldWrite(mirror::Object* obj, MemberOffset field_offset,
355 const FieldValue& field_value) {
356 // TODO We may want to abort a transaction while still being in transaction mode. In this case,
357 // we'd need to disable the check.
358 constexpr bool kCheckTransaction = true;
359 switch (field_value.kind) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700360 case kBoolean:
361 if (UNLIKELY(field_value.is_volatile)) {
362 obj->SetFieldBooleanVolatile<false, kCheckTransaction>(field_offset,
363 static_cast<bool>(field_value.value));
364 } else {
365 obj->SetFieldBoolean<false, kCheckTransaction>(field_offset,
366 static_cast<bool>(field_value.value));
367 }
368 break;
369 case kByte:
370 if (UNLIKELY(field_value.is_volatile)) {
371 obj->SetFieldByteVolatile<false, kCheckTransaction>(field_offset,
372 static_cast<int8_t>(field_value.value));
373 } else {
374 obj->SetFieldByte<false, kCheckTransaction>(field_offset,
375 static_cast<int8_t>(field_value.value));
376 }
377 break;
378 case kChar:
379 if (UNLIKELY(field_value.is_volatile)) {
380 obj->SetFieldCharVolatile<false, kCheckTransaction>(field_offset,
381 static_cast<uint16_t>(field_value.value));
382 } else {
383 obj->SetFieldChar<false, kCheckTransaction>(field_offset,
384 static_cast<uint16_t>(field_value.value));
385 }
386 break;
387 case kShort:
388 if (UNLIKELY(field_value.is_volatile)) {
389 obj->SetFieldShortVolatile<false, kCheckTransaction>(field_offset,
390 static_cast<int16_t>(field_value.value));
391 } else {
392 obj->SetFieldShort<false, kCheckTransaction>(field_offset,
393 static_cast<int16_t>(field_value.value));
394 }
395 break;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100396 case k32Bits:
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700397 if (UNLIKELY(field_value.is_volatile)) {
398 obj->SetField32Volatile<false, kCheckTransaction>(field_offset,
399 static_cast<uint32_t>(field_value.value));
400 } else {
401 obj->SetField32<false, kCheckTransaction>(field_offset,
402 static_cast<uint32_t>(field_value.value));
403 }
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100404 break;
405 case k64Bits:
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700406 if (UNLIKELY(field_value.is_volatile)) {
407 obj->SetField64Volatile<false, kCheckTransaction>(field_offset, field_value.value);
408 } else {
409 obj->SetField64<false, kCheckTransaction>(field_offset, field_value.value);
410 }
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100411 break;
412 case kReference:
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700413 if (UNLIKELY(field_value.is_volatile)) {
414 obj->SetFieldObjectVolatile<false, kCheckTransaction>(field_offset,
415 reinterpret_cast<mirror::Object*>(field_value.value));
416 } else {
417 obj->SetFieldObject<false, kCheckTransaction>(field_offset,
418 reinterpret_cast<mirror::Object*>(field_value.value));
419 }
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100420 break;
421 default:
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700422 LOG(FATAL) << "Unknown value kind " << static_cast<int>(field_value.kind);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100423 break;
424 }
425}
426
427void Transaction::ObjectLog::VisitRoots(RootCallback* callback, void* arg) {
428 for (auto it : field_values_) {
429 FieldValue& field_value = it.second;
430 if (field_value.kind == ObjectLog::kReference) {
Mathieu Chartier815873e2014-02-13 18:02:13 -0800431 mirror::Object* obj =
432 reinterpret_cast<mirror::Object*>(static_cast<uintptr_t>(field_value.value));
Sebastien Hertza559ccb2014-02-21 15:36:13 +0100433 if (obj != nullptr) {
Mathieu Chartiere34fa1d2015-01-14 14:55:47 -0800434 callback(&obj, arg, RootInfo(kRootUnknown));
Sebastien Hertza559ccb2014-02-21 15:36:13 +0100435 field_value.value = reinterpret_cast<uintptr_t>(obj);
436 }
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100437 }
438 }
439}
440
441void Transaction::InternStringLog::Undo(InternTable* intern_table) {
442 DCHECK(intern_table != nullptr);
443 switch (string_op_) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700444 case InternStringLog::kInsert: {
445 switch (string_kind_) {
446 case InternStringLog::kStrongString:
447 intern_table->RemoveStrongFromTransaction(str_);
448 break;
449 case InternStringLog::kWeakString:
450 intern_table->RemoveWeakFromTransaction(str_);
451 break;
452 default:
453 LOG(FATAL) << "Unknown interned string kind";
454 break;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100455 }
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700456 break;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100457 }
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700458 case InternStringLog::kRemove: {
459 switch (string_kind_) {
460 case InternStringLog::kStrongString:
461 intern_table->InsertStrongFromTransaction(str_);
462 break;
463 case InternStringLog::kWeakString:
464 intern_table->InsertWeakFromTransaction(str_);
465 break;
466 default:
467 LOG(FATAL) << "Unknown interned string kind";
468 break;
469 }
470 break;
471 }
472 default:
473 LOG(FATAL) << "Unknown interned string op";
474 break;
475 }
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100476}
477
478void Transaction::InternStringLog::VisitRoots(RootCallback* callback, void* arg) {
Mathieu Chartiere34fa1d2015-01-14 14:55:47 -0800479 callback(reinterpret_cast<mirror::Object**>(&str_), arg, RootInfo(kRootInternedString));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100480}
481
482void Transaction::ArrayLog::LogValue(size_t index, uint64_t value) {
483 auto it = array_values_.find(index);
484 if (it == array_values_.end()) {
485 array_values_.insert(std::make_pair(index, value));
486 }
487}
488
489void Transaction::ArrayLog::Undo(mirror::Array* array) {
490 DCHECK(array != nullptr);
491 DCHECK(array->IsArrayInstance());
492 Primitive::Type type = array->GetClass()->GetComponentType()->GetPrimitiveType();
493 for (auto it : array_values_) {
494 UndoArrayWrite(array, type, it.first, it.second);
495 }
496}
497
498void Transaction::ArrayLog::UndoArrayWrite(mirror::Array* array, Primitive::Type array_type,
499 size_t index, uint64_t value) {
500 // TODO We may want to abort a transaction while still being in transaction mode. In this case,
501 // we'd need to disable the check.
502 switch (array_type) {
503 case Primitive::kPrimBoolean:
504 array->AsBooleanArray()->SetWithoutChecks<false>(index, static_cast<uint8_t>(value));
505 break;
506 case Primitive::kPrimByte:
507 array->AsByteArray()->SetWithoutChecks<false>(index, static_cast<int8_t>(value));
508 break;
509 case Primitive::kPrimChar:
510 array->AsCharArray()->SetWithoutChecks<false>(index, static_cast<uint16_t>(value));
511 break;
512 case Primitive::kPrimShort:
513 array->AsShortArray()->SetWithoutChecks<false>(index, static_cast<int16_t>(value));
514 break;
515 case Primitive::kPrimInt:
516 array->AsIntArray()->SetWithoutChecks<false>(index, static_cast<int32_t>(value));
517 break;
518 case Primitive::kPrimFloat:
519 array->AsFloatArray()->SetWithoutChecks<false>(index, static_cast<float>(value));
520 break;
521 case Primitive::kPrimLong:
522 array->AsLongArray()->SetWithoutChecks<false>(index, static_cast<int64_t>(value));
523 break;
524 case Primitive::kPrimDouble:
525 array->AsDoubleArray()->SetWithoutChecks<false>(index, static_cast<double>(value));
526 break;
Sebastien Hertzee1d79a2014-02-21 15:46:30 +0100527 case Primitive::kPrimNot:
528 LOG(FATAL) << "ObjectArray should be treated as Object";
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100529 break;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100530 default:
531 LOG(FATAL) << "Unsupported type " << array_type;
532 }
533}
534
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100535} // namespace art