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

Side by Side Diff: test/cctest/test-api.cc

Issue 260017: Implemented really weak handles. (Closed)
Patch Set: Fix typo. Created 11 years, 2 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 unified diff | Download patch
« src/global-handles.cc ('K') | « src/global-handles.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2007-2009 the V8 project authors. All rights reserved. 1 // Copyright 2007-2009 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 14 matching lines...) Expand all
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 #include <stdlib.h> 28 #include <stdlib.h>
29 29
30 #include "v8.h" 30 #include "v8.h"
31 31
32 #include "api.h" 32 #include "api.h"
33 #include "compilation-cache.h" 33 #include "compilation-cache.h"
34 #include "execution.h" 34 #include "execution.h"
35 #include "platform.h"
35 #include "snapshot.h" 36 #include "snapshot.h"
36 #include "platform.h"
37 #include "top.h" 37 #include "top.h"
38 #include "cctest.h" 38 #include "cctest.h"
39 39
40 static bool IsNaN(double x) { 40 static bool IsNaN(double x) {
41 #ifdef WIN32 41 #ifdef WIN32
42 return _isnan(x); 42 return _isnan(x);
43 #else 43 #else
44 return isnan(x); 44 return isnan(x);
45 #endif 45 #endif
46 } 46 }
(...skipping 2861 matching lines...) Expand 10 before | Expand all | Expand 10 after
2908 2908
2909 THREADED_TEST(ErrorWithMissingScriptInfo) { 2909 THREADED_TEST(ErrorWithMissingScriptInfo) {
2910 v8::HandleScope scope; 2910 v8::HandleScope scope;
2911 LocalContext context; 2911 LocalContext context;
2912 v8::V8::AddMessageListener(MissingScriptInfoMessageListener); 2912 v8::V8::AddMessageListener(MissingScriptInfoMessageListener);
2913 Script::Compile(v8_str("throw Error()"))->Run(); 2913 Script::Compile(v8_str("throw Error()"))->Run();
2914 v8::V8::RemoveMessageListeners(MissingScriptInfoMessageListener); 2914 v8::V8::RemoveMessageListeners(MissingScriptInfoMessageListener);
2915 } 2915 }
2916 2916
2917 2917
2918 int global_index = 0; 2918 static void WeakFactoryCallback(v8::Persistent<v8::Value> object, void* data);
2919 2919
2920 class Snorkel { 2920 class WeakFactory {
2921 public: 2921 public:
2922 Snorkel() { index_ = global_index++; } 2922 enum Mode {
2923 int index_; 2923 FACTORY_WEAK,
2924 FACTORY_REALLY_WEAK
2925 };
2926
2927 explicit WeakFactory(Mode mode)
2928 : mode_(mode),
2929 objects_(8),
2930 template_(v8::Persistent<v8::FunctionTemplate>::New(
2931 v8::FunctionTemplate::New())),
2932 instance_template_(v8::Persistent<v8::ObjectTemplate>::New(
2933 template_->InstanceTemplate())) { }
2934
2935 ~WeakFactory() {
2936 for (int i = 0; i < objects_.length(); ++i) {
2937 objects_[i].Dispose();
2938 }
2939 }
2940
2941 v8::Persistent<v8::Object> CreateObject() {
2942 v8::Persistent<v8::Object> object =
2943 v8::Persistent<v8::Object>::New(instance_template_->NewInstance());
2944 if (mode_ == FACTORY_WEAK) {
2945 object.MakeWeak(this, &WeakFactoryCallback);
2946 } else if (mode_ == FACTORY_REALLY_WEAK) {
2947 object.MakeReallyWeak(this, &WeakFactoryCallback);
2948 } else {
2949 UNREACHABLE();
2950 }
2951 objects_.Add(object);
2952 return object;
2953 }
2954
2955 void Return(v8::Persistent<v8::Value> object) {
2956 for (int i = 0; i < objects_.length(); ++i) {
2957 if (objects_[i] == object) {
2958 object.Dispose();
2959 objects_.Remove(i);
2960 return;
2961 }
2962 }
2963 CHECK(false);
Christian Plesner Hansen 2009/10/06 13:47:21 UNREACHABLE()?
2964 }
2965
2966 int NumLive() const { return objects_.length(); }
2967
2968 int NumInHeap() const {
2969 int counter = 0;
2970 i::HeapIterator iter;
2971 while (iter.has_next()) {
2972 i::HeapObject* object = iter.next();
2973 if (object->IsInstanceOf(*v8::Utils::OpenHandle(*template_))) {
2974 ++counter;
2975 }
2976 }
2977 return counter;
2978 }
2979
2980 private:
2981 const Mode mode_;
Christian Plesner Hansen 2009/10/06 13:47:21 Why const?
2982 i::List<v8::Persistent<v8::Value> > objects_;
2983 v8::Persistent<v8::FunctionTemplate> template_;
2984 v8::Persistent<v8::ObjectTemplate> instance_template_;
2924 }; 2985 };
2925 2986
2926 class Whammy { 2987 static void WeakFactoryCallback(v8::Persistent<v8::Value> object, void* data) {
2927 public: 2988 WeakFactory* factory = reinterpret_cast<WeakFactory*>(data);
2928 Whammy() { 2989 factory->Return(object);
2929 cursor_ = 0;
2930 }
2931 ~Whammy() {
2932 script_.Dispose();
2933 }
2934 v8::Handle<Script> getScript() {
2935 if (script_.IsEmpty())
2936 script_ = v8::Persistent<Script>::New(v8_compile("({}).blammo"));
2937 return Local<Script>(*script_);
2938 }
2939
2940 public:
2941 static const int kObjectCount = 256;
2942 int cursor_;
2943 v8::Persistent<v8::Object> objects_[kObjectCount];
2944 v8::Persistent<Script> script_;
2945 };
2946
2947 static void HandleWeakReference(v8::Persistent<v8::Value> obj, void* data) {
2948 Snorkel* snorkel = reinterpret_cast<Snorkel*>(data);
2949 delete snorkel;
2950 obj.ClearWeak();
2951 } 2990 }
2952 2991
2953 v8::Handle<Value> WhammyPropertyGetter(Local<String> name, 2992 static v8::Handle<v8::Value> WeakFactoryCreateObject(
2954 const AccessorInfo& info) { 2993 const v8::Arguments& args) {
2955 Whammy* whammy = 2994 WeakFactory* factory =
2956 static_cast<Whammy*>(v8::Handle<v8::External>::Cast(info.Data())->Value()); 2995 reinterpret_cast<WeakFactory*>(v8::External::Unwrap(args.Data()));
2996 return factory->CreateObject();
2997 }
2957 2998
2958 v8::Persistent<v8::Object> prev = whammy->objects_[whammy->cursor_]; 2999 static const char* const kTestWeakCode =
2959 3000 "var last = null;"
2960 v8::Handle<v8::Object> obj = v8::Object::New(); 3001 "(function() {"
2961 v8::Persistent<v8::Object> global = v8::Persistent<v8::Object>::New(obj); 3002 " for (var i = 0; i < 10000; i++) {"
2962 if (!prev.IsEmpty()) { 3003 " var obj = createObject();"
2963 prev->Set(v8_str("next"), obj); 3004 " obj.next = last;"
2964 prev.MakeWeak(new Snorkel(), &HandleWeakReference); 3005 " last = obj;"
2965 whammy->objects_[whammy->cursor_].Clear(); 3006 " }"
2966 } 3007 "})();";
2967 whammy->objects_[whammy->cursor_] = global;
2968 whammy->cursor_ = (whammy->cursor_ + 1) % Whammy::kObjectCount;
2969 return whammy->getScript()->Run();
2970 }
2971 3008
2972 THREADED_TEST(WeakReference) { 3009 THREADED_TEST(WeakReference) {
2973 v8::HandleScope handle_scope; 3010 v8::HandleScope handle_scope;
2974 v8::Handle<v8::ObjectTemplate> templ= v8::ObjectTemplate::New(); 3011 WeakFactory* factory = new WeakFactory(WeakFactory::FACTORY_WEAK);
2975 templ->SetNamedPropertyHandler(WhammyPropertyGetter, 3012
2976 0, 0, 0, 0,
2977 v8::External::New(new Whammy()));
2978 const char* extension_list[] = { "v8/gc" }; 3013 const char* extension_list[] = { "v8/gc" };
2979 v8::ExtensionConfiguration extensions(1, extension_list); 3014 v8::ExtensionConfiguration extensions(1, extension_list);
2980 v8::Persistent<Context> context = Context::New(&extensions); 3015 v8::Persistent<Context> context = Context::New(&extensions);
2981 Context::Scope context_scope(context); 3016 Context::Scope context_scope(context);
2982 3017
2983 v8::Handle<v8::Object> interceptor = templ->NewInstance(); 3018 v8::Handle<v8::FunctionTemplate> function_templ = v8::FunctionTemplate::New(
2984 context->Global()->Set(v8_str("whammy"), interceptor); 3019 &WeakFactoryCreateObject, v8::External::Wrap(factory));
2985 const char* code = 3020 context->Global()->Set(v8_str("createObject"), function_templ->GetFunction());
2986 "var last;" 3021
2987 "for (var i = 0; i < 10000; i++) {" 3022 // Create objects held by a variable.
2988 " var obj = whammy.length;" 3023 CompileRun(kTestWeakCode);
2989 " if (last) last.next = obj;" 3024 CHECK_EQ(10000, factory->NumLive());
2990 " last = obj;" 3025 CHECK_EQ(10000, factory->NumInHeap());
2991 "}" 3026
2992 "gc();" 3027 // Make sure GC doesn't collect them.
2993 "4"; 3028 CompileRun("gc(); gc();");
2994 v8::Handle<Value> result = CompileRun(code); 3029 CHECK_EQ(10000, factory->NumLive());
2995 CHECK_EQ(4.0, result->NumberValue()); 3030 CHECK_EQ(10000, factory->NumInHeap());
3031
3032 // Make sure GC realizes they are no longer reachable and invokes
3033 // weak callbacks after the variable is reset.
3034 CompileRun("last = null; gc();");
3035 CHECK_EQ(0, factory->NumLive());
3036 CHECK_EQ(10000, factory->NumInHeap());
3037
3038 // Next GC after callbacks should collect the objects.
3039 CompileRun("gc();");
3040 CHECK_EQ(0, factory->NumLive());
3041 CHECK_EQ(0, factory->NumInHeap());
2996 3042
2997 context.Dispose(); 3043 context.Dispose();
2998 } 3044 }
3045
3046 THREADED_TEST(ReallyWeakReference) {
3047 v8::HandleScope handle_scope;
3048 WeakFactory* factory = new WeakFactory(WeakFactory::FACTORY_REALLY_WEAK);
3049
3050 const char* extension_list[] = { "v8/gc" };
3051 v8::ExtensionConfiguration extensions(1, extension_list);
3052 v8::Persistent<Context> context = Context::New(&extensions);
3053 Context::Scope context_scope(context);
3054
3055 v8::Handle<v8::FunctionTemplate> function_templ = v8::FunctionTemplate::New(
3056 &WeakFactoryCreateObject, v8::External::Wrap(factory));
3057 context->Global()->Set(v8_str("createObject"), function_templ->GetFunction());
3058
3059 // See the comments above in WeakReference test.
3060
3061 CompileRun(kTestWeakCode);
3062 CHECK_EQ(10000, factory->NumLive());
3063 CHECK_EQ(10000, factory->NumInHeap());
3064
3065 CompileRun("gc(); gc();");
3066 CHECK_EQ(10000, factory->NumLive());
3067 CHECK_EQ(10000, factory->NumInHeap());
3068
3069 // Unlike above objects should be immediately collected when they
3070 // are unreachable.
3071 CompileRun("last = null; gc();");
3072 CHECK_EQ(0, factory->NumLive());
3073 CHECK_EQ(0, factory->NumInHeap());
3074
3075 context.Dispose();
3076 }
2999 3077
3000 3078
3001 v8::Handle<Function> args_fun; 3079 v8::Handle<Function> args_fun;
3002 3080
3003 3081
3004 static v8::Handle<Value> ArgumentsTestCallback(const v8::Arguments& args) { 3082 static v8::Handle<Value> ArgumentsTestCallback(const v8::Arguments& args) {
3005 ApiTestFuzzer::Fuzz(); 3083 ApiTestFuzzer::Fuzz();
3006 CHECK_EQ(args_fun, args.Callee()); 3084 CHECK_EQ(args_fun, args.Callee());
3007 CHECK_EQ(3, args.Length()); 3085 CHECK_EQ(3, args.Length());
3008 CHECK_EQ(v8::Integer::New(1), args[0]); 3086 CHECK_EQ(v8::Integer::New(1), args[0]);
(...skipping 4981 matching lines...) Expand 10 before | Expand all | Expand 10 after
7990 env->Global()->Set(v8_str("get_stack_limit"), fun); 8068 env->Global()->Set(v8_str("get_stack_limit"), fun);
7991 CompileRun("get_stack_limit();"); 8069 CompileRun("get_stack_limit();");
7992 8070
7993 CHECK(stack_limit == set_limit); 8071 CHECK(stack_limit == set_limit);
7994 } 8072 }
7995 { 8073 {
7996 v8::Locker locker; 8074 v8::Locker locker;
7997 CHECK(stack_limit == set_limit); 8075 CHECK(stack_limit == set_limit);
7998 } 8076 }
7999 } 8077 }
OLDNEW
« src/global-handles.cc ('K') | « src/global-handles.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698