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

Unified Diff: runtime/vm/object.cc

Issue 10827288: - Support for patching of class methods and fields. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 4 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
Index: runtime/vm/object.cc
===================================================================
--- runtime/vm/object.cc (revision 10615)
+++ runtime/vm/object.cc (working copy)
@@ -74,6 +74,7 @@
RawClass* Object::type_arguments_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
RawClass* Object::instantiated_type_arguments_class_ =
reinterpret_cast<RawClass*>(RAW_NULL);
+RawClass* Object::patch_class_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
RawClass* Object::function_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
RawClass* Object::field_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
RawClass* Object::literal_token_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
@@ -288,6 +289,9 @@
cls = Class::New<InstantiatedTypeArguments>();
instantiated_type_arguments_class_ = cls.raw();
+ cls = Class::New<PatchClass>();
+ patch_class_class_ = cls.raw();
+
cls = Class::New<Function>();
function_class_ = cls.raw();
@@ -1230,7 +1234,7 @@
intptr_t len = value.Length();
for (intptr_t i = 0; i < len; i++) {
func ^= value.At(i);
- ASSERT(func.owner() == raw());
+ ASSERT(func.Owner() == raw());
}
#endif
StorePointer(&raw_ptr()->functions_, value.raw());
@@ -1320,7 +1324,7 @@
const Function& signature_fun = Function::Handle(signature_function());
if (!signature_fun.is_static() &&
!signature_fun.HasInstantiatedSignature()) {
- cls = signature_fun.owner();
+ cls = signature_fun.Owner();
}
}
intptr_t num_type_args = NumTypeParameters();
@@ -1480,6 +1484,57 @@
}
+void Class::ApplyPatch(const Class& with) const {
+ ASSERT(!is_finalized());
+ const Script& patch_script = Script::Handle(with.script());
+ const String& str = String::Handle(patch_script.Source());
+ OS::PrintErr("patch_script: %s\n", str.ToCString());
Ivan Posva 2012/08/14 01:21:49 Debug print removed...
+ const PatchClass& patch = PatchClass::Handle(
+ PatchClass::New(*this, patch_script));
+
+ const Array& orig_functions = Array::Handle(functions());
+ intptr_t orig_len = orig_functions.Length();
+
+ const Array& patch_functions = Array::Handle(with.functions());
+ intptr_t patch_len = patch_functions.Length();
+
+ // TODO(iposva): Verify that only patching existing methods and adding only
+ // new private methods.
+ Function& func = Function::Handle();
+ const Array& new_functions = Array::Handle(Array::New(patch_len + orig_len));
siva 2012/08/15 00:16:04 I think you should add a comment here that current
Ivan Posva 2012/08/15 06:50:39 I attempted to address the second part of your sug
+ for (intptr_t i = 0; i < patch_len; i++) {
+ func ^= patch_functions.At(i);
+ func.set_owner(patch);
+ new_functions.SetAt(i, func);
+ }
+ for (intptr_t i = 0; i < orig_len; i++) {
+ func ^= orig_functions.At(i);
+ new_functions.SetAt(patch_len + i, func);
+ }
+ SetFunctions(new_functions);
+
+ const Array& orig_fields = Array::Handle(fields());
+ orig_len = orig_fields.Length();
+
+ const Array& patch_fields = Array::Handle(with.fields());
+ patch_len = patch_fields.Length();
siva 2012/08/15 00:16:04 why not call the array handle variables orig_list,
Ivan Posva 2012/08/15 06:50:39 ditto
+
+ // TODO(iposva): Verify that no duplicate fields are entered.
+ Field& field = Field::Handle();
+ const Array& new_fields = Array::Handle(Array::New(patch_len + orig_len));
+ for (intptr_t i = 0; i < patch_len; i++) {
+ field ^= patch_fields.At(i);
+ field.set_owner(*this);
+ new_fields.SetAt(i, field);
+ }
+ for (intptr_t i = 0; i < orig_len; i++) {
+ field ^= orig_fields.At(i);
+ new_fields.SetAt(patch_len + i, field);
+ }
+ SetFields(new_fields);
+}
+
+
void Class::SetFields(const Array& value) const {
ASSERT(!value.IsNull());
#if defined(DEBUG)
@@ -1557,7 +1612,7 @@
const Function& signature_function,
const Script& script) {
ASSERT(!signature_function.IsNull());
- const Class& owner_class = Class::Handle(signature_function.owner());
+ const Class& owner_class = Class::Handle(signature_function.Owner());
ASSERT(!owner_class.IsNull());
TypeArguments& type_parameters = TypeArguments::Handle();
// A signature class extends class Instance and is parameterized in the same
@@ -3502,6 +3557,45 @@
}
+const char* PatchClass::ToCString() const {
+ const char* kFormat = "PatchClass for %s";
+ const Class& cls = Class::Handle(patched_class());
+ const char* cls_name = cls.ToCString();
+ intptr_t len = OS::SNPrint(NULL, 0, kFormat, cls_name) + 1;
+ char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
+ OS::SNPrint(chars, len, kFormat, cls_name);
+ return chars;
+}
+
+
+RawPatchClass* PatchClass::New(const Class& patched_class,
+ const Script& script) {
+ const PatchClass& result = PatchClass::Handle(PatchClass::New());
+ result.set_patched_class(patched_class);
+ result.set_script(script);
+ return result.raw();
+}
+
+
+RawPatchClass* PatchClass::New() {
+ ASSERT(Object::patch_class_class() != Class::null());
+ RawObject* raw = Object::Allocate(PatchClass::kClassId,
+ PatchClass::InstanceSize(),
+ Heap::kOld);
+ return reinterpret_cast<RawPatchClass*>(raw);
+}
+
+
+void PatchClass::set_patched_class(const Class& value) const {
+ StorePointer(&raw_ptr()->patched_class_, value.raw());
+}
+
+
+void PatchClass::set_script(const Script& value) const {
+ StorePointer(&raw_ptr()->script_, value.raw());
+}
+
+
void Function::SetCode(const Code& value) const {
StorePointer(&raw_ptr()->code_, value.raw());
ASSERT(Function::Handle(value.function()).IsNull() ||
@@ -3569,7 +3663,7 @@
}
-void Function::set_owner(const Class& value) const {
+void Function::set_owner(const Object& value) const {
ASSERT(!value.IsNull());
StorePointer(&raw_ptr()->owner_, value.raw());
}
@@ -3813,7 +3907,7 @@
const Function& parent = Function::Handle(function.parent_function());
intptr_t written = 0;
if (parent.IsNull()) {
- const Class& function_class = Class::Handle(function.owner());
+ const Class& function_class = Class::Handle(function.Owner());
ASSERT(!function_class.IsNull());
const char* class_name = String::Handle(function_class.Name()).ToCString();
ASSERT(class_name != NULL);
@@ -4053,7 +4147,7 @@
intptr_t token_pos) {
ASSERT(name.IsOneByteString());
ASSERT(!parent.IsNull());
- const Class& parent_class = Class::Handle(parent.owner());
+ const Class& parent_class = Class::Handle(parent.Owner());
ASSERT(!parent_class.IsNull());
const Function& result = Function::Handle(
Function::New(name,
@@ -4115,15 +4209,15 @@
// Lookup or create a new signature class for the closure function in the
// library of the owner class.
- const Class& owner_class = Class::Handle(owner());
- ASSERT(!owner_class.IsNull() && (owner() == closure_function.owner()));
+ const Class& owner_class = Class::Handle(Owner());
+ ASSERT(!owner_class.IsNull() && (Owner() == closure_function.Owner()));
const Library& library = Library::Handle(owner_class.library());
ASSERT(!library.IsNull());
const String& signature = String::Handle(closure_function.Signature());
Class& signature_class = Class::ZoneHandle(
library.LookupLocalClass(signature));
if (signature_class.IsNull()) {
- const Script& script = Script::Handle(owner_class.script());
+ const Script& script = Script::Handle(this->script());
signature_class = Class::NewSignatureClass(signature,
closure_function,
script);
@@ -4163,7 +4257,7 @@
String::Handle(Symbols::New(" extends "));
const String& kLAngleBracket = String::Handle(Symbols::New("<"));
const String& kRAngleBracket = String::Handle(Symbols::New(">"));
- const Class& function_class = Class::Handle(owner());
+ const Class& function_class = Class::Handle(Owner());
ASSERT(!function_class.IsNull());
const TypeArguments& type_parameters = TypeArguments::Handle(
function_class.type_parameters());
@@ -4254,6 +4348,26 @@
}
+RawClass* Function::Owner() const {
+ const Object& obj = Object::Handle(raw_ptr()->owner_);
hausner 2012/08/14 18:25:06 It would be nice if you could avoid this extra han
Ivan Posva 2012/08/15 06:50:39 I have seen 0% impact by this change on performanc
+ if (obj.IsClass()) {
+ return Class::Cast(obj).raw();
+ }
+ ASSERT(obj.IsPatchClass());
+ return PatchClass::Cast(obj).patched_class();
+}
+
+
+RawScript* Function::script() const {
+ const Object& obj = Object::Handle(raw_ptr()->owner_);
+ if (obj.IsClass()) {
+ return Class::Cast(obj).script();
+ }
+ ASSERT(obj.IsPatchClass());
+ return PatchClass::Cast(obj).script();
+}
+
+
bool Function::HasOptimizedCode() const {
return HasCode() && Code::Handle(raw_ptr()->code_).is_optimized();
}
@@ -4268,7 +4382,7 @@
RawString* Function::QualifiedUserVisibleName() const {
String& tmp = String::Handle();
String& suffix = String::Handle();
- const Class& cls = Class::Handle(owner());
+ const Class& cls = Class::Handle(Owner());
if (IsClosureFunction()) {
if (IsLocalFunction()) {
@@ -5499,8 +5613,6 @@
const GrowableObjectArray& scripts =
GrowableObjectArray::Handle(GrowableObjectArray::New(8));
Object& entry = Object::Handle();
- Function& func = Function::Handle();
- Field& field = Field::Handle();
Class& cls = Class::Handle();
Script& owner_script = Script::Handle();
DictionaryIterator it(*this);
@@ -5508,17 +5620,15 @@
while (it.HasNext()) {
entry = it.GetNext();
if (entry.IsClass()) {
- cls ^= entry.raw();
+ owner_script = Class::Cast(entry).script();
} else if (entry.IsFunction()) {
- func ^= entry.raw();
- cls = func.owner();
+ owner_script = Function::Cast(entry).script();
} else if (entry.IsField()) {
- field ^= entry.raw();
- cls = field.owner();
+ cls = Field::Cast(entry).owner();
+ owner_script = cls.script();
} else {
continue;
}
- owner_script = cls.script();
if (owner_script.IsNull()) {
continue;
}
@@ -5778,7 +5888,7 @@
lib ^= cls.library();
} else if (obj.IsFunction()) {
func ^= obj.raw();
- cls ^= func.owner();
+ cls ^= func.Owner();
lib ^= cls.library();
} else if (obj.IsField()) {
field ^= obj.raw();
@@ -7642,7 +7752,7 @@
if (NumberOfChecks() == 0) return false;
Class& cls = Class::Handle();
for (intptr_t i = 0; i < NumberOfChecks(); i++) {
- cls = Function::Handle(GetTargetAt(i)).owner();
+ cls = Function::Handle(GetTargetAt(i)).Owner();
if (cls.id() != owner_cid) {
return false;
}
@@ -7655,7 +7765,7 @@
if (NumberOfChecks() == 0) return false;
Class& cls = Class::Handle();
for (intptr_t i = 0; i < NumberOfChecks(); i++) {
- cls = Function::Handle(GetTargetAt(i)).owner();
+ cls = Function::Handle(GetTargetAt(i)).Owner();
const intptr_t cid = cls.id();
if ((cid != kSmiCid) &&
(cid != kMintCid) &&
@@ -10938,7 +11048,6 @@
const char* Stacktrace::ToCString() const {
Function& function = Function::Handle();
Code& code = Code::Handle();
- Class& owner = Class::Handle();
Script& script = Script::Handle();
String& function_name = String::Handle();
String& url = String::Handle();
@@ -10953,8 +11062,7 @@
code = CodeAtFrame(i);
uword pc = code.EntryPoint() + Smi::Value(PcOffsetAtFrame(i));
intptr_t token_pos = code.GetTokenIndexOfPC(pc);
- owner = function.owner();
- script = owner.script();
+ script = function.script();
function_name = function.QualifiedUserVisibleName();
url = script.url();
intptr_t line = -1;
« no previous file with comments | « runtime/vm/object.h ('k') | runtime/vm/object_test.cc » ('j') | runtime/vm/parser.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698