Chromium Code Reviews| 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; |