Revision: 2636 Author: [email protected] Date: Thu Aug 6 06:35:21 2009 Log: API: added function to find instance of template in prototype chain.
Also inlined Object::IsInstanceOf. This new function is intended to be used to speed up DOM bindings. Review URL: http://codereview.chromium.org/165044 http://code.google.com/p/v8/source/detail?r=2636 Modified: /branches/bleeding_edge/include/v8.h /branches/bleeding_edge/src/api.cc /branches/bleeding_edge/src/objects-inl.h /branches/bleeding_edge/src/objects.cc /branches/bleeding_edge/src/objects.h /branches/bleeding_edge/test/cctest/test-api.cc ======================================= --- /branches/bleeding_edge/include/v8.h Wed Aug 5 00:59:46 2009 +++ /branches/bleeding_edge/include/v8.h Thu Aug 6 06:35:21 2009 @@ -1098,6 +1098,12 @@ */ Local<Value> GetPrototype(); + /** + * Finds an instance of the given function template in the prototype + * chain. + */ + Local<Object> FindInstanceInPrototypeChain(Handle<FunctionTemplate> tmpl); + /** * Call builtin Object.prototype.toString on this object. * This is different from Value::ToString() that may call ======================================= --- /branches/bleeding_edge/src/api.cc Tue Aug 4 07:14:01 2009 +++ /branches/bleeding_edge/src/api.cc Thu Aug 6 06:35:21 2009 @@ -1926,6 +1926,22 @@ i::Handle<i::Object> result = i::GetPrototype(self); return Utils::ToLocal(result); } + + +Local<Object> v8::Object::FindInstanceInPrototypeChain( + v8::Handle<FunctionTemplate> tmpl) { + ON_BAILOUT("v8::Object::FindInstanceInPrototypeChain()", + return Local<v8::Object>()); + ENTER_V8; + i::JSObject* object = *Utils::OpenHandle(this); + i::FunctionTemplateInfo* tmpl_info = *Utils::OpenHandle(*tmpl); + while (!object->IsInstanceOf(tmpl_info)) { + i::Object* prototype = object->GetPrototype(); + if (!prototype->IsJSObject()) return Local<Object>(); + object = i::JSObject::cast(prototype); + } + return Utils::ToLocal(i::Handle<i::JSObject>(object)); +} Local<Array> v8::Object::GetPropertyNames() { ======================================= --- /branches/bleeding_edge/src/objects-inl.h Wed Jul 29 05:34:21 2009 +++ /branches/bleeding_edge/src/objects-inl.h Thu Aug 6 06:35:21 2009 @@ -98,6 +98,25 @@ void holder::set_##name(bool value) { \ set_##field(BooleanBit::set(field(), offset, value)); \ } + + +bool Object::IsInstanceOf(FunctionTemplateInfo* expected) { + // There is a constraint on the object; check. + if (!this->IsJSObject()) return false; + // Fetch the constructor function of the object. + Object* cons_obj = JSObject::cast(this)->map()->constructor(); + if (!cons_obj->IsJSFunction()) return false; + JSFunction* fun = JSFunction::cast(cons_obj); + // Iterate through the chain of inheriting function templates to + // see if the required one occurs. + for (Object* type = fun->shared()->function_data(); + type->IsFunctionTemplateInfo(); + type = FunctionTemplateInfo::cast(type)->parent_template()) { + if (type == expected) return true; + } + // Didn't find the required type in the inheritance chain. + return false; +} bool Object::IsSmi() { ======================================= --- /branches/bleeding_edge/src/objects.cc Thu Jul 30 02:13:48 2009 +++ /branches/bleeding_edge/src/objects.cc Thu Aug 6 06:35:21 2009 @@ -50,24 +50,6 @@ const int kGetterIndex = 0; const int kSetterIndex = 1; -bool Object::IsInstanceOf(FunctionTemplateInfo* expected) { - // There is a constraint on the object; check - if (!this->IsJSObject()) return false; - // Fetch the constructor function of the object - Object* cons_obj = JSObject::cast(this)->map()->constructor(); - if (!cons_obj->IsJSFunction()) return false; - JSFunction* fun = JSFunction::cast(cons_obj); - // Iterate through the chain of inheriting function templates to - // see if the required one occurs. - for (Object* type = fun->shared()->function_data(); - type->IsFunctionTemplateInfo(); - type = FunctionTemplateInfo::cast(type)->parent_template()) { - if (type == expected) return true; - } - // Didn't find the required type in the inheritance chain. - return false; -} - static Object* CreateJSValue(JSFunction* constructor, Object* value) { Object* result = Heap::AllocateJSObject(constructor); ======================================= --- /branches/bleeding_edge/src/objects.h Thu Aug 6 03:22:38 2009 +++ /branches/bleeding_edge/src/objects.h Thu Aug 6 06:35:21 2009 @@ -801,7 +801,7 @@ // Returns true if this object is an instance of the specified // function template. - bool IsInstanceOf(FunctionTemplateInfo* type); + inline bool IsInstanceOf(FunctionTemplateInfo* type); inline bool IsStruct(); #define DECLARE_STRUCT_PREDICATE(NAME, Name, name) inline bool Is##Name(); ======================================= --- /branches/bleeding_edge/test/cctest/test-api.cc Tue Jul 28 11:11:12 2009 +++ /branches/bleeding_edge/test/cctest/test-api.cc Thu Aug 6 06:35:21 2009 @@ -631,6 +631,53 @@ CHECK_EQ(v8_str("[object funky]"), result); } } + + +THREADED_TEST(FindInstanceInPrototypeChain) { + v8::HandleScope scope; + LocalContext env; + + Local<v8::FunctionTemplate> base = v8::FunctionTemplate::New(); + Local<v8::FunctionTemplate> derived = v8::FunctionTemplate::New(); + Local<v8::FunctionTemplate> other = v8::FunctionTemplate::New(); + derived->Inherit(base); + + Local<v8::Function> base_function = base->GetFunction(); + Local<v8::Function> derived_function = derived->GetFunction(); + Local<v8::Function> other_function = other->GetFunction(); + + Local<v8::Object> base_instance = base_function->NewInstance(); + Local<v8::Object> derived_instance = derived_function->NewInstance(); + Local<v8::Object> derived_instance2 = derived_function->NewInstance(); + Local<v8::Object> other_instance = other_function->NewInstance(); + derived_instance2->Set(v8_str("__proto__"), derived_instance); + other_instance->Set(v8_str("__proto__"), derived_instance2); + + // base_instance is only an instance of base. + CHECK_EQ(base_instance, + base_instance->FindInstanceInPrototypeChain(base)); + CHECK(base_instance->FindInstanceInPrototypeChain(derived).IsEmpty()); + CHECK(base_instance->FindInstanceInPrototypeChain(other).IsEmpty()); + + // derived_instance is an instance of base and derived. + CHECK_EQ(derived_instance, + derived_instance->FindInstanceInPrototypeChain(base)); + CHECK_EQ(derived_instance, + derived_instance->FindInstanceInPrototypeChain(derived)); + CHECK(derived_instance->FindInstanceInPrototypeChain(other).IsEmpty()); + + // other_instance is an instance of other and its immediate + // prototype derived_instance2 is an instance of base and derived. + // Note, derived_instance is an instance of base and derived too, + // but it comes after derived_instance2 in the prototype chain of + // other_instance. + CHECK_EQ(derived_instance2, + other_instance->FindInstanceInPrototypeChain(base)); + CHECK_EQ(derived_instance2, + other_instance->FindInstanceInPrototypeChain(derived)); + CHECK_EQ(other_instance, + other_instance->FindInstanceInPrototypeChain(other)); +} static v8::Handle<Value> handle_property(Local<String> name, --~--~---------~--~----~------------~-------~--~----~ v8-dev mailing list [email protected] http://groups.google.com/group/v8-dev -~----------~----~----~----~------~----~------~--~---
