Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(795)

Unified Diff: runtime/vm/object.cc

Issue 1850653003: Provide ability to patch external functions in a class that has already been finalized. The follow… (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: code-review Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/object.h ('k') | runtime/vm/parser.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/object.cc
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 894452d9d8129ad33a01af9b4d1ec9e7675022a8..9afe3fc37ceb3d49ad4d77fb5437a277ac0761c4 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -2779,6 +2779,81 @@ void Class::SetTraceAllocation(bool trace_allocation) const {
}
+bool Class::ValidatePostFinalizePatch(const Class& orig_class,
+ Error* error) const {
+ ASSERT(error != NULL);
+ // Not allowed to add new fields in a post finalization patch.
+ if (fields() != Object::empty_array().raw()) {
+ *error = LanguageError::NewFormatted(
+ *error, // No previous error.
+ Script::Handle(script()),
+ token_pos(),
+ Report::AtLocation,
+ Report::kError,
+ Heap::kNew,
+ "new fields are not allowed for this patch");
+ return false;
+ }
+ // There seem to be no functions, the patch is pointless.
+ if (functions() == Object::empty_array().raw()) {
+ *error = LanguageError::NewFormatted(
+ *error, // No previous error.
+ Script::Handle(script()),
+ token_pos(),
+ Report::AtLocation,
+ Report::kError,
+ Heap::kNew,
+ "no functions to patch");
+ return false;
+ }
+ // Iterate over all functions that will be patched and make sure
+ // the original function was declared 'external' and has not executed
+ // so far i.e no code has been generated for it.
+ Thread* thread = Thread::Current();
+ ASSERT(thread->IsMutatorThread());
+ Zone* zone = thread->zone();
+ const Array& funcs = Array::Handle(zone, functions());
+ Function& func = Function::Handle(zone);
+ Function& orig_func = Function::Handle(zone);
+ String& name = String::Handle(zone);
+ for (intptr_t i = 0; i < funcs.Length(); i++) {
+ func ^= funcs.At(i);
+ name ^= func.name();
+ orig_func ^= orig_class.LookupFunctionAllowPrivate(name);
+ if (!orig_func.IsNull()) {
+ if (!orig_func.is_external() || orig_func.HasCode()) {
+ // We can only patch external functions in a post finalized class.
+ *error = LanguageError::NewFormatted(
+ *error, // No previous error.
+ Script::Handle(script()),
+ token_pos(),
+ Report::AtLocation,
+ Report::kError,
+ Heap::kNew,
+ !orig_func.is_external() ?
+ "'%s' is not external and therefore cannot be patched" :
+ "'%s' has already executed and therefore cannot be patched",
+ name.ToCString());
+ return false;
+ }
+ } else if (!Library::IsPrivate(name)) {
+ // We can only have new private functions that are added.
+ *error = LanguageError::NewFormatted(
+ *error, // No previous error.
+ Script::Handle(script()),
+ token_pos(),
+ Report::AtLocation,
+ Report::kError,
+ Heap::kNew,
+ "'%s' is not private and therefore cannot be patched",
+ name.ToCString());
+ return false;
+ }
+ }
+ return true;
+}
+
+
void Class::set_cha_codes(const Array& cache) const {
StorePointer(&raw_ptr()->cha_codes_, cache.raw());
}
@@ -3422,6 +3497,14 @@ void Class::set_is_finalized() const {
}
+void Class::SetRefinalizeAfterPatch() const {
+ ASSERT(!IsTopLevel());
+ set_state_bits(ClassFinalizedBits::update(RawClass::kRefinalizeAfterPatch,
+ raw_ptr()->state_bits_));
+ set_state_bits(TypeFinalizedBit::update(false, raw_ptr()->state_bits_));
+}
+
+
void Class::ResetFinalization() const {
ASSERT(IsTopLevel());
set_state_bits(ClassFinalizedBits::update(RawClass::kAllocated,
@@ -5832,6 +5915,7 @@ void Function::SetIsNativeAutoSetupScope(bool value) const {
bool Function::CanBeInlined() const {
Thread* thread = Thread::Current();
return is_inlinable() &&
+ !is_external() &&
!is_generated_body() &&
(!FLAG_support_debugger ||
!thread->isolate()->debugger()->HasBreakpoint(*this, thread->zone()));
« no previous file with comments | « runtime/vm/object.h ('k') | runtime/vm/parser.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698