| 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()));
|
|
|