Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "include/dart_api.h" | 5 #include "include/dart_api.h" |
| 6 | 6 |
| 7 #include "vm/assert.h" | 7 #include "vm/assert.h" |
| 8 #include "vm/dart_api_impl.h" | 8 #include "vm/dart_api_impl.h" |
| 9 #include "vm/dart_api_state.h" | 9 #include "vm/dart_api_state.h" |
| 10 #include "vm/thread.h" | 10 #include "vm/thread.h" |
| (...skipping 2940 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2951 UNIT_TEST_CASE(RunLoop_ExceptionChild) { | 2951 UNIT_TEST_CASE(RunLoop_ExceptionChild) { |
| 2952 RunLoopTest(true, false); | 2952 RunLoopTest(true, false); |
| 2953 } | 2953 } |
| 2954 | 2954 |
| 2955 | 2955 |
| 2956 UNIT_TEST_CASE(RunLoop_ExceptionParent) { | 2956 UNIT_TEST_CASE(RunLoop_ExceptionParent) { |
| 2957 RunLoopTest(false, true); | 2957 RunLoopTest(false, true); |
| 2958 } | 2958 } |
| 2959 | 2959 |
| 2960 | 2960 |
| 2961 // Utility functions and variables for test case IsolateInterrupt starts here. | |
| 2961 static Monitor* sync = NULL; | 2962 static Monitor* sync = NULL; |
| 2962 static Dart_Isolate shared_isolate = NULL; | 2963 static Dart_Isolate shared_isolate = NULL; |
| 2964 static bool main_entered = false; | |
| 2965 | |
| 2966 | |
| 2967 void MarkMainEntered(Dart_NativeArguments args) { | |
| 2968 Dart_EnterScope(); // Start a Dart API scope for invoking API functions. | |
| 2969 // Indicate that main has been entered. | |
| 2970 { | |
| 2971 MonitorLocker ml(sync); | |
| 2972 main_entered = true; | |
| 2973 ml.Notify(); | |
| 2974 } | |
| 2975 Dart_SetReturnValue(args, Dart_Null()); | |
| 2976 Dart_ExitScope(); | |
| 2977 } | |
| 2978 | |
| 2979 | |
| 2980 static Dart_NativeFunction IsolateInterruptTestNativeLookup( | |
| 2981 Dart_Handle name, int argument_count) { | |
| 2982 return reinterpret_cast<Dart_NativeFunction>(&MarkMainEntered); | |
| 2983 } | |
| 2984 | |
| 2985 | |
| 2963 void BusyLoop_start(uword unused) { | 2986 void BusyLoop_start(uword unused) { |
| 2964 // TODO(turnidge): Get rid of call to 'function' after interrupts | 2987 // TODO(turnidge): Get rid of call to 'function' after interrupts |
| 2965 // are checked on backward branches. | 2988 // are checked on backward branches. |
| 2966 const char* kScriptChars = | 2989 const char* kScriptChars = |
| 2990 "class Native {\n" | |
| 2991 " static void markMainEntered() native 'MarkMainEntered';\n" | |
| 2992 "}\n" | |
| 2967 "void function([foo='hi']) {\n" | 2993 "void function([foo='hi']) {\n" |
| 2968 "}\n" | 2994 "}\n" |
| 2969 "\n" | 2995 "\n" |
| 2970 "void main() {\n" | 2996 "void main() {\n" |
| 2997 " Native.markMainEntered();\n" | |
| 2971 " while (true) {\n" // Infinite loop. | 2998 " while (true) {\n" // Infinite loop. |
| 2972 " function();\n" | 2999 " function();\n" |
| 2973 " }\n" | 3000 " }\n" |
| 2974 "}\n"; | 3001 "}\n"; |
| 2975 | 3002 |
| 2976 | 3003 |
| 2977 // Tell the other thread that shared_isolate is created. | 3004 // Tell the other thread that shared_isolate is created. |
| 2978 Dart_Handle lib; | 3005 Dart_Handle lib; |
| 2979 { | 3006 { |
| 2980 sync->Enter(); | 3007 sync->Enter(); |
| 2981 char* error = NULL; | 3008 char* error = NULL; |
| 2982 shared_isolate = Dart_CreateIsolate(NULL, NULL, &error); | 3009 shared_isolate = Dart_CreateIsolate(NULL, NULL, &error); |
| 2983 EXPECT(shared_isolate != NULL); | 3010 EXPECT(shared_isolate != NULL); |
| 2984 Dart_EnterScope(); | 3011 Dart_EnterScope(); |
| 2985 Dart_Handle url = Dart_NewString(TestCase::url()); | 3012 Dart_Handle url = Dart_NewString(TestCase::url()); |
| 2986 Dart_Handle source = Dart_NewString(kScriptChars); | 3013 Dart_Handle source = Dart_NewString(kScriptChars); |
| 2987 lib = Dart_LoadScript(url, source, TestCase::library_handler); | 3014 lib = Dart_LoadScript(url, source, TestCase::library_handler); |
| 2988 EXPECT_VALID(lib); | 3015 EXPECT_VALID(lib); |
| 3016 Dart_Handle result = Dart_SetNativeResolver( | |
| 3017 lib, &IsolateInterruptTestNativeLookup); | |
| 3018 DART_CHECK_VALID(result); | |
| 2989 | 3019 |
| 2990 sync->Notify(); | 3020 sync->Notify(); |
| 2991 sync->Exit(); | 3021 sync->Exit(); |
| 2992 } | 3022 } |
| 2993 | 3023 |
| 2994 Dart_Handle result = Dart_InvokeStatic(lib, | 3024 Dart_Handle result = Dart_InvokeStatic(lib, |
| 2995 Dart_NewString(""), | 3025 Dart_NewString(""), |
| 2996 Dart_NewString("main"), | 3026 Dart_NewString("main"), |
| 2997 0, | 3027 0, |
| 2998 NULL); | 3028 NULL); |
| 2999 EXPECT(Dart_IsError(result)); | 3029 EXPECT(Dart_IsError(result)); |
| 3000 EXPECT(Dart_ErrorHasException(result)); | 3030 EXPECT(Dart_ErrorHasException(result)); |
| 3001 EXPECT_SUBSTRING("Unhandled exception:\nfoo\n", | 3031 EXPECT_SUBSTRING("Unhandled exception:\nfoo\n", |
| 3002 Dart_GetError(result)); | 3032 Dart_GetError(result)); |
| 3003 | 3033 |
| 3004 // Tell the other thread that we are done. | |
| 3005 { | |
| 3006 MonitorLocker ml(sync); | |
| 3007 shared_isolate = NULL; | |
| 3008 ml.Notify(); | |
| 3009 } | |
| 3010 | |
| 3011 Dart_ExitScope(); | 3034 Dart_ExitScope(); |
| 3012 Dart_ShutdownIsolate(); | 3035 Dart_ShutdownIsolate(); |
| 3036 | |
| 3037 // Tell the other thread that we are done (don't use MonitorLocker | |
| 3038 // as there is no current isolate any more). | |
| 3039 sync->Enter(); | |
| 3040 shared_isolate = NULL; | |
| 3041 sync->Notify(); | |
| 3042 sync->Exit(); | |
| 3013 } | 3043 } |
| 3014 | 3044 |
| 3015 | 3045 |
| 3016 // This callback handles isolate interrupts for the IsolateInterrupt | 3046 // This callback handles isolate interrupts for the IsolateInterrupt |
| 3017 // test. It ignores the first two interrupts and throws an exception | 3047 // test. It ignores the first two interrupts and throws an exception |
| 3018 // on the third interrupt. | 3048 // on the third interrupt. |
| 3019 static int interrupt_count = 0; | 3049 static int interrupt_count = 0; |
| 3020 static bool IsolateInterruptTestCallback() { | 3050 static bool IsolateInterruptTestCallback() { |
| 3021 interrupt_count++; | 3051 OS::Print(" ========== Interrupt callback called #%d\n", interrupt_count + 1); |
| 3022 OS::Print(" =========== Interrupt callback called #%d\n", interrupt_count); | 3052 { |
| 3053 MonitorLocker ml(sync); | |
| 3054 interrupt_count++; | |
| 3055 ml.Notify(); | |
| 3056 } | |
| 3023 if (interrupt_count >= 3) { | 3057 if (interrupt_count >= 3) { |
| 3024 Dart_EnterScope(); | 3058 Dart_EnterScope(); |
| 3025 Dart_Handle lib = Dart_LookupLibrary(Dart_NewString(TestCase::url())); | 3059 Dart_Handle lib = Dart_LookupLibrary(Dart_NewString(TestCase::url())); |
| 3026 EXPECT_VALID(lib); | 3060 EXPECT_VALID(lib); |
| 3027 Dart_Handle exc = Dart_NewString("foo"); | 3061 Dart_Handle exc = Dart_NewString("foo"); |
| 3028 EXPECT_VALID(exc); | 3062 EXPECT_VALID(exc); |
| 3029 Dart_Handle result = Dart_ThrowException(exc); | 3063 Dart_Handle result = Dart_ThrowException(exc); |
| 3030 EXPECT_VALID(result); | 3064 EXPECT_VALID(result); |
| 3031 UNREACHABLE(); // Dart_ThrowException only returns if it gets an error. | 3065 UNREACHABLE(); // Dart_ThrowException only returns if it gets an error. |
| 3032 return false; | 3066 return false; |
| 3033 } | 3067 } |
| 3034 return true; | 3068 return true; |
| 3035 } | 3069 } |
| 3036 | 3070 |
| 3037 | 3071 |
| 3038 TEST_CASE(IsolateInterrupt) { | 3072 TEST_CASE(IsolateInterrupt) { |
| 3039 Dart_IsolateInterruptCallback saved = Isolate::InterruptCallback(); | 3073 Dart_IsolateInterruptCallback saved = Isolate::InterruptCallback(); |
| 3040 Isolate::SetInterruptCallback(IsolateInterruptTestCallback); | 3074 Isolate::SetInterruptCallback(IsolateInterruptTestCallback); |
| 3041 | 3075 |
| 3042 sync = new Monitor(); | 3076 sync = new Monitor(); |
| 3043 Thread* thread = new Thread(BusyLoop_start, 0); | 3077 Thread* thread = new Thread(BusyLoop_start, 0); |
| 3044 EXPECT(thread != NULL); | 3078 EXPECT(thread != NULL); |
| 3045 | 3079 |
| 3046 { | 3080 { |
| 3047 MonitorLocker ml(sync); | 3081 MonitorLocker ml(sync); |
| 3048 // Wait for the other isolate to start. | 3082 // Wait for the other isolate to enter main. |
| 3049 while (shared_isolate == NULL) { | 3083 while (!main_entered) { |
| 3050 ml.Wait(); | 3084 ml.Wait(); |
| 3051 } | 3085 } |
| 3052 } | 3086 } |
| 3053 | 3087 |
| 3054 // Send three interrupts to the other isolate. The first two allow | 3088 // Send three interrupts to the other isolate. The first two allow |
| 3055 // execution to continue. The third causes an exception in the | 3089 // execution to continue. The third causes an exception in the |
| 3056 // isolate. | 3090 // isolate. |
| 3057 Dart_InterruptIsolate(shared_isolate); | 3091 for (int i = 0; i < 3; i++) { |
|
Ivan Posva
2011/12/21 08:31:16
I would prefer if we spaced the interrupts out a b
| |
| 3058 OS::Sleep(5); | 3092 Dart_InterruptIsolate(shared_isolate); |
| 3059 Dart_InterruptIsolate(shared_isolate); | 3093 { |
| 3060 OS::Sleep(5); | 3094 MonitorLocker ml(sync); |
| 3061 Dart_InterruptIsolate(shared_isolate); | 3095 // Wait for interrupt_count to be increased. |
| 3096 while (interrupt_count == i) { | |
| 3097 ml.Wait(); | |
| 3098 } | |
| 3099 OS::Print(" ========== Interrupt processed #%d\n", interrupt_count); | |
| 3100 } | |
| 3101 } | |
| 3062 | 3102 |
| 3063 { | 3103 { |
| 3064 MonitorLocker ml(sync); | 3104 MonitorLocker ml(sync); |
| 3065 // Wait for our isolate to finish. | 3105 // Wait for our isolate to finish. |
| 3066 while (shared_isolate != NULL) { | 3106 while (shared_isolate != NULL) { |
| 3067 ml.Wait(); | 3107 ml.Wait(); |
| 3068 } | 3108 } |
| 3069 } | 3109 } |
| 3070 | 3110 |
| 3071 // We should have received 3 interrupts. | 3111 // We should have received 3 interrupts. |
| 3072 EXPECT_EQ(3, interrupt_count); | 3112 EXPECT_EQ(3, interrupt_count); |
| 3073 | 3113 |
| 3074 // Give the spawned thread enough time to properly exit. | 3114 // Give the spawned thread enough time to properly exit. |
| 3075 OS::Sleep(20); | |
| 3076 Isolate::SetInterruptCallback(saved); | 3115 Isolate::SetInterruptCallback(saved); |
| 3077 } | 3116 } |
| 3078 | 3117 |
| 3079 #endif // TARGET_ARCH_IA32. | 3118 #endif // TARGET_ARCH_IA32. |
| 3080 | 3119 |
| 3081 } // namespace dart | 3120 } // namespace dart |
| OLD | NEW |