summaryrefslogtreecommitdiffstats
path: root/runtime/entrypoints/quick
diff options
context:
space:
mode:
authorSebastien Hertz <shertz@google.com>2014-01-15 10:20:56 +0100
committerSebastien Hertz <shertz@google.com>2014-02-17 11:32:15 +0100
commitd2fe10a3a34af171bf1631219cd2d6ff6b7778b5 (patch)
treeb6b7eb8eba23a5c2723518da99c03bf47b97f58a /runtime/entrypoints/quick
parent5a3f55ad9519e87c0d3bbddaf3d8a186a887a79b (diff)
downloadart-d2fe10a3a34af171bf1631219cd2d6ff6b7778b5.zip
art-d2fe10a3a34af171bf1631219cd2d6ff6b7778b5.tar.gz
art-d2fe10a3a34af171bf1631219cd2d6ff6b7778b5.tar.bz2
Remove blacklist
Removes the class initialization blacklist and use transaction to detect and revert class initialization attempting to invoke native method. This only concerns class initialization happening at compilation time when generating an image (like boot.art for the system). In transactional mode, we log every object's field assignment and array update. Therefore we're able to abort a transaction to restore values of fields and array as they were before the transaction starts. We also log changes to the intern string table so we can restore its state prior to transaction start. Since transactional mode only happens at compilation time, we don't need to log all these changes at runtime. In order to reduce the overhead of testing if transactional mode is on/off, we templatize interfaces of mirror::Object and mirror::Array, respectively responsible for setting a field and setting an array element. For various reasons, we skip some specific fields from transaction: - Object's class and array's length must remain unchanged so garbage collector can compute object's size. - Immutable fields only set during class loading: list of fields, method, dex caches, vtables, ... as all classes have been loaded and verified before a transaction occurs. - Object's monitor for performance reason. Before generating the image, we browse the heap to collect objects that need to be written into it. Since the heap may still holds references to unreachable objects due to aborted transactions, we trigger one collection at the end of the class preinitialization phase. Since the transaction is held by the runtime and all compilation threads share the same runtime, we need to ensure only one compilation thread has exclusive access to the runtime. To workaround this issue, we force class initialization phase to run with only one thread. Note this is only done when generating image so application compilation is not impacted. This issue will be addressed in a separate CL. Bug: 9676614 Change-Id: I221910a9183a5ba6c2b99a277f5a5a68bc69b5f9
Diffstat (limited to 'runtime/entrypoints/quick')
-rw-r--r--runtime/entrypoints/quick/quick_field_entrypoints.cc36
-rw-r--r--runtime/entrypoints/quick/quick_trampoline_entrypoints.cc4
2 files changed, 26 insertions, 14 deletions
diff --git a/runtime/entrypoints/quick/quick_field_entrypoints.cc b/runtime/entrypoints/quick/quick_field_entrypoints.cc
index 93ff7aa..2d5c07d 100644
--- a/runtime/entrypoints/quick/quick_field_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_field_entrypoints.cc
@@ -154,13 +154,15 @@ extern "C" int artSet32StaticFromCode(uint32_t field_idx, uint32_t new_value,
mirror::ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite,
sizeof(int32_t));
if (LIKELY(field != NULL)) {
- field->Set32(field->GetDeclaringClass(), new_value);
+ // Compiled code can't use transactional mode.
+ field->Set32<false>(field->GetDeclaringClass(), new_value);
return 0; // success
}
FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
field = FindFieldFromCode<StaticPrimitiveWrite, true>(field_idx, referrer, self, sizeof(int32_t));
if (LIKELY(field != NULL)) {
- field->Set32(field->GetDeclaringClass(), new_value);
+ // Compiled code can't use transactional mode.
+ field->Set32<false>(field->GetDeclaringClass(), new_value);
return 0; // success
}
return -1; // failure
@@ -172,13 +174,15 @@ extern "C" int artSet64StaticFromCode(uint32_t field_idx, mirror::ArtMethod* ref
mirror::ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite,
sizeof(int64_t));
if (LIKELY(field != NULL)) {
- field->Set64(field->GetDeclaringClass(), new_value);
+ // Compiled code can't use transactional mode.
+ field->Set64<false>(field->GetDeclaringClass(), new_value);
return 0; // success
}
FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
field = FindFieldFromCode<StaticPrimitiveWrite, true>(field_idx, referrer, self, sizeof(int64_t));
if (LIKELY(field != NULL)) {
- field->Set64(field->GetDeclaringClass(), new_value);
+ // Compiled code can't use transactional mode.
+ field->Set64<false>(field->GetDeclaringClass(), new_value);
return 0; // success
}
return -1; // failure
@@ -192,7 +196,8 @@ extern "C" int artSetObjStaticFromCode(uint32_t field_idx, mirror::Object* new_v
sizeof(mirror::HeapReference<mirror::Object>));
if (LIKELY(field != NULL)) {
if (LIKELY(!FieldHelper(field).IsPrimitiveType())) {
- field->SetObj(field->GetDeclaringClass(), new_value);
+ // Compiled code can't use transactional mode.
+ field->SetObj<false>(field->GetDeclaringClass(), new_value);
return 0; // success
}
}
@@ -200,7 +205,8 @@ extern "C" int artSetObjStaticFromCode(uint32_t field_idx, mirror::Object* new_v
field = FindFieldFromCode<StaticObjectWrite, true>(field_idx, referrer, self,
sizeof(mirror::HeapReference<mirror::Object>));
if (LIKELY(field != NULL)) {
- field->SetObj(field->GetDeclaringClass(), new_value);
+ // Compiled code can't use transactional mode.
+ field->SetObj<false>(field->GetDeclaringClass(), new_value);
return 0; // success
}
return -1; // failure
@@ -213,7 +219,8 @@ extern "C" int artSet32InstanceFromCode(uint32_t field_idx, mirror::Object* obj,
mirror::ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite,
sizeof(int32_t));
if (LIKELY(field != NULL && obj != NULL)) {
- field->Set32(obj, new_value);
+ // Compiled code can't use transactional mode.
+ field->Set32<false>(obj, new_value);
return 0; // success
}
FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
@@ -224,7 +231,8 @@ extern "C" int artSet32InstanceFromCode(uint32_t field_idx, mirror::Object* obj,
ThrowLocation throw_location = self->GetCurrentLocationForThrow();
ThrowNullPointerExceptionForFieldAccess(throw_location, field, false);
} else {
- field->Set32(obj, new_value);
+ // Compiled code can't use transactional mode.
+ field->Set32<false>(obj, new_value);
return 0; // success
}
}
@@ -240,7 +248,8 @@ extern "C" int artSet64InstanceFromCode(uint32_t field_idx, mirror::Object* obj,
mirror::ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite,
sizeof(int64_t));
if (LIKELY(field != NULL && obj != NULL)) {
- field->Set64(obj, new_value);
+ // Compiled code can't use transactional mode.
+ field->Set64<false>(obj, new_value);
return 0; // success
}
*sp = callee_save;
@@ -252,7 +261,8 @@ extern "C" int artSet64InstanceFromCode(uint32_t field_idx, mirror::Object* obj,
ThrowLocation throw_location = self->GetCurrentLocationForThrow();
ThrowNullPointerExceptionForFieldAccess(throw_location, field, false);
} else {
- field->Set64(obj, new_value);
+ // Compiled code can't use transactional mode.
+ field->Set64<false>(obj, new_value);
return 0; // success
}
}
@@ -267,7 +277,8 @@ extern "C" int artSetObjInstanceFromCode(uint32_t field_idx, mirror::Object* obj
mirror::ArtField* field = FindFieldFast(field_idx, referrer, InstanceObjectWrite,
sizeof(mirror::HeapReference<mirror::Object>));
if (LIKELY(field != NULL && obj != NULL)) {
- field->SetObj(obj, new_value);
+ // Compiled code can't use transactional mode.
+ field->SetObj<false>(obj, new_value);
return 0; // success
}
FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
@@ -278,7 +289,8 @@ extern "C" int artSetObjInstanceFromCode(uint32_t field_idx, mirror::Object* obj
ThrowLocation throw_location = self->GetCurrentLocationForThrow();
ThrowNullPointerExceptionForFieldAccess(throw_location, field, false);
} else {
- field->SetObj(obj, new_value);
+ // Compiled code can't use transactional mode.
+ field->SetObj<false>(obj, new_value);
return 0; // success
}
}
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
index f9486c3..012dabb 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -558,7 +558,7 @@ extern "C" const void* artQuickResolutionTrampoline(mirror::ArtMethod* called,
// We came here because of sharpening. Ensure the dex cache is up-to-date on the method index
// of the sharpened method.
if (called->GetDexCacheResolvedMethods() == caller->GetDexCacheResolvedMethods()) {
- caller->GetDexCacheResolvedMethods()->Set(called->GetDexMethodIndex(), called);
+ caller->GetDexCacheResolvedMethods()->Set<false>(called->GetDexMethodIndex(), called);
} else {
// Calling from one dex file to another, need to compute the method index appropriate to
// the caller's dex file. Since we get here only if the original called was a runtime
@@ -567,7 +567,7 @@ extern "C" const void* artQuickResolutionTrampoline(mirror::ArtMethod* called,
uint32_t method_index =
MethodHelper(called).FindDexMethodIndexInOtherDexFile(*dex_file, dex_method_idx);
if (method_index != DexFile::kDexNoIndex) {
- caller->GetDexCacheResolvedMethods()->Set(method_index, called);
+ caller->GetDexCacheResolvedMethods()->Set<false>(method_index, called);
}
}
}