Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 } |
| OLD | NEW |