| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 "vm/isolate.h" |
| 5 #include "include/dart_api.h" | 6 #include "include/dart_api.h" |
| 6 #include "platform/assert.h" | 7 #include "platform/assert.h" |
| 7 #include "vm/globals.h" | 8 #include "vm/globals.h" |
| 8 #include "vm/isolate.h" | |
| 9 #include "vm/lockers.h" | 9 #include "vm/lockers.h" |
| 10 #include "vm/thread_barrier.h" | 10 #include "vm/thread_barrier.h" |
| 11 #include "vm/thread_pool.h" | 11 #include "vm/thread_pool.h" |
| 12 #include "vm/unit_test.h" | 12 #include "vm/unit_test.h" |
| 13 | 13 |
| 14 namespace dart { | 14 namespace dart { |
| 15 | 15 |
| 16 VM_UNIT_TEST_CASE(IsolateCurrent) { | 16 VM_UNIT_TEST_CASE(IsolateCurrent) { |
| 17 Dart_Isolate isolate = Dart_CreateIsolate( | 17 Dart_Isolate isolate = Dart_CreateIsolate( |
| 18 NULL, NULL, bin::core_isolate_snapshot_data, | 18 NULL, NULL, bin::core_isolate_snapshot_data, |
| 19 bin::core_isolate_snapshot_instructions, NULL, NULL, NULL); | 19 bin::core_isolate_snapshot_instructions, NULL, NULL, NULL); |
| 20 EXPECT_EQ(isolate, Dart_CurrentIsolate()); | 20 EXPECT_EQ(isolate, Dart_CurrentIsolate()); |
| 21 Dart_ShutdownIsolate(); | 21 Dart_ShutdownIsolate(); |
| 22 EXPECT_EQ(reinterpret_cast<Dart_Isolate>(NULL), Dart_CurrentIsolate()); | 22 EXPECT_EQ(reinterpret_cast<Dart_Isolate>(NULL), Dart_CurrentIsolate()); |
| 23 } | 23 } |
| 24 | 24 |
| 25 | |
| 26 // Test to ensure that an exception is thrown if no isolate creation | 25 // Test to ensure that an exception is thrown if no isolate creation |
| 27 // callback has been set by the embedder when an isolate is spawned. | 26 // callback has been set by the embedder when an isolate is spawned. |
| 28 TEST_CASE(IsolateSpawn) { | 27 TEST_CASE(IsolateSpawn) { |
| 29 const char* kScriptChars = | 28 const char* kScriptChars = |
| 30 "import 'dart:isolate';\n" | 29 "import 'dart:isolate';\n" |
| 31 // Ignores printed lines. | 30 // Ignores printed lines. |
| 32 "var _nullPrintClosure = (String line) {};\n" | 31 "var _nullPrintClosure = (String line) {};\n" |
| 33 "void entry(message) {}\n" | 32 "void entry(message) {}\n" |
| 34 "int testMain() {\n" | 33 "int testMain() {\n" |
| 35 " Isolate.spawn(entry, null);\n" | 34 " Isolate.spawn(entry, null);\n" |
| (...skipping 28 matching lines...) Expand all Loading... |
| 64 isolate_lib, NewString("_getIsolateScheduleImmediateClosure"), 0, NULL); | 63 isolate_lib, NewString("_getIsolateScheduleImmediateClosure"), 0, NULL); |
| 65 Dart_Handle args[1]; | 64 Dart_Handle args[1]; |
| 66 args[0] = schedule_immediate_closure; | 65 args[0] = schedule_immediate_closure; |
| 67 url = NewString("dart:async"); | 66 url = NewString("dart:async"); |
| 68 DART_CHECK_VALID(url); | 67 DART_CHECK_VALID(url); |
| 69 Dart_Handle async_lib = Dart_LookupLibrary(url); | 68 Dart_Handle async_lib = Dart_LookupLibrary(url); |
| 70 DART_CHECK_VALID(async_lib); | 69 DART_CHECK_VALID(async_lib); |
| 71 DART_CHECK_VALID(Dart_Invoke( | 70 DART_CHECK_VALID(Dart_Invoke( |
| 72 async_lib, NewString("_setScheduleImmediateClosure"), 1, args)); | 71 async_lib, NewString("_setScheduleImmediateClosure"), 1, args)); |
| 73 | 72 |
| 74 | |
| 75 result = Dart_Invoke(test_lib, NewString("testMain"), 0, NULL); | 73 result = Dart_Invoke(test_lib, NewString("testMain"), 0, NULL); |
| 76 EXPECT_VALID(result); | 74 EXPECT_VALID(result); |
| 77 // Run until all ports to isolate are closed. | 75 // Run until all ports to isolate are closed. |
| 78 result = Dart_RunLoop(); | 76 result = Dart_RunLoop(); |
| 79 EXPECT_ERROR(result, "Unsupported operation: Isolate.spawn"); | 77 EXPECT_ERROR(result, "Unsupported operation: Isolate.spawn"); |
| 80 EXPECT(Dart_ErrorHasException(result)); | 78 EXPECT(Dart_ErrorHasException(result)); |
| 81 Dart_Handle exception_result = Dart_ErrorGetException(result); | 79 Dart_Handle exception_result = Dart_ErrorGetException(result); |
| 82 EXPECT_VALID(exception_result); | 80 EXPECT_VALID(exception_result); |
| 83 } | 81 } |
| 84 | 82 |
| 85 | |
| 86 class InterruptChecker : public ThreadPool::Task { | 83 class InterruptChecker : public ThreadPool::Task { |
| 87 public: | 84 public: |
| 88 static const intptr_t kTaskCount; | 85 static const intptr_t kTaskCount; |
| 89 static const intptr_t kIterations; | 86 static const intptr_t kIterations; |
| 90 | 87 |
| 91 InterruptChecker(Thread* thread, ThreadBarrier* barrier) | 88 InterruptChecker(Thread* thread, ThreadBarrier* barrier) |
| 92 : thread_(thread), barrier_(barrier) {} | 89 : thread_(thread), barrier_(barrier) {} |
| 93 | 90 |
| 94 virtual void Run() { | 91 virtual void Run() { |
| 95 Thread::EnterIsolateAsHelper(thread_->isolate(), Thread::kUnknownTask); | 92 Thread::EnterIsolateAsHelper(thread_->isolate(), Thread::kUnknownTask); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 109 } | 106 } |
| 110 Thread::ExitIsolateAsHelper(); | 107 Thread::ExitIsolateAsHelper(); |
| 111 barrier_->Exit(); | 108 barrier_->Exit(); |
| 112 } | 109 } |
| 113 | 110 |
| 114 private: | 111 private: |
| 115 Thread* thread_; | 112 Thread* thread_; |
| 116 ThreadBarrier* barrier_; | 113 ThreadBarrier* barrier_; |
| 117 }; | 114 }; |
| 118 | 115 |
| 119 | |
| 120 const intptr_t InterruptChecker::kTaskCount = 5; | 116 const intptr_t InterruptChecker::kTaskCount = 5; |
| 121 const intptr_t InterruptChecker::kIterations = 10; | 117 const intptr_t InterruptChecker::kIterations = 10; |
| 122 | 118 |
| 123 // Test and document usage of Isolate::HasInterruptsScheduled. | 119 // Test and document usage of Isolate::HasInterruptsScheduled. |
| 124 // | 120 // |
| 125 // Go through a number of rounds of scheduling interrupts and waiting until all | 121 // Go through a number of rounds of scheduling interrupts and waiting until all |
| 126 // unsynchronized busy-waiting tasks observe it (in the current implementation, | 122 // unsynchronized busy-waiting tasks observe it (in the current implementation, |
| 127 // the exact latency depends on cache coherence). Synchronization is then used | 123 // the exact latency depends on cache coherence). Synchronization is then used |
| 128 // to ensure that the response to the interrupt, i.e., starting a new round, | 124 // to ensure that the response to the interrupt, i.e., starting a new round, |
| 129 // happens *after* the interrupt is observed. Without this synchronization, the | 125 // happens *after* the interrupt is observed. Without this synchronization, the |
| (...skipping 14 matching lines...) Expand all Loading... |
| 144 thread->ScheduleInterrupts(Thread::kVMInterrupt); | 140 thread->ScheduleInterrupts(Thread::kVMInterrupt); |
| 145 // Wait for all tasks to observe the interrupt. | 141 // Wait for all tasks to observe the interrupt. |
| 146 barrier.Sync(); | 142 barrier.Sync(); |
| 147 // Continue with next round. | 143 // Continue with next round. |
| 148 uword interrupts = thread->GetAndClearInterrupts(); | 144 uword interrupts = thread->GetAndClearInterrupts(); |
| 149 EXPECT((interrupts & Thread::kVMInterrupt) != 0); | 145 EXPECT((interrupts & Thread::kVMInterrupt) != 0); |
| 150 } | 146 } |
| 151 barrier.Exit(); | 147 barrier.Exit(); |
| 152 } | 148 } |
| 153 | 149 |
| 154 | |
| 155 class IsolateTestHelper { | 150 class IsolateTestHelper { |
| 156 public: | 151 public: |
| 157 static uword GetStackLimit(Thread* thread) { return thread->stack_limit_; } | 152 static uword GetStackLimit(Thread* thread) { return thread->stack_limit_; } |
| 158 static uword GetSavedStackLimit(Thread* thread) { | 153 static uword GetSavedStackLimit(Thread* thread) { |
| 159 return thread->saved_stack_limit_; | 154 return thread->saved_stack_limit_; |
| 160 } | 155 } |
| 161 static uword GetDeferredInterruptsMask(Thread* thread) { | 156 static uword GetDeferredInterruptsMask(Thread* thread) { |
| 162 return thread->deferred_interrupts_mask_; | 157 return thread->deferred_interrupts_mask_; |
| 163 } | 158 } |
| 164 static uword GetDeferredInterrupts(Thread* thread) { | 159 static uword GetDeferredInterrupts(Thread* thread) { |
| 165 return thread->deferred_interrupts_; | 160 return thread->deferred_interrupts_; |
| 166 } | 161 } |
| 167 }; | 162 }; |
| 168 | 163 |
| 169 | |
| 170 TEST_CASE(NoOOBMessageScope) { | 164 TEST_CASE(NoOOBMessageScope) { |
| 171 // EXPECT_EQ is picky about type agreement for its arguments. | 165 // EXPECT_EQ is picky about type agreement for its arguments. |
| 172 const uword kZero = 0; | 166 const uword kZero = 0; |
| 173 const uword kMessageInterrupt = Thread::kMessageInterrupt; | 167 const uword kMessageInterrupt = Thread::kMessageInterrupt; |
| 174 const uword kVMInterrupt = Thread::kVMInterrupt; | 168 const uword kVMInterrupt = Thread::kVMInterrupt; |
| 175 uword stack_limit; | 169 uword stack_limit; |
| 176 uword interrupt_bits; | 170 uword interrupt_bits; |
| 177 | 171 |
| 178 // Initially no interrupts are scheduled or deferred. | 172 // Initially no interrupts are scheduled or deferred. |
| 179 EXPECT_EQ(IsolateTestHelper::GetStackLimit(thread), | 173 EXPECT_EQ(IsolateTestHelper::GetStackLimit(thread), |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 241 // Restore, then clear interrupts. The world is as it was. | 235 // Restore, then clear interrupts. The world is as it was. |
| 242 interrupt_bits = thread->GetAndClearInterrupts(); | 236 interrupt_bits = thread->GetAndClearInterrupts(); |
| 243 EXPECT_EQ(kMessageInterrupt, interrupt_bits); | 237 EXPECT_EQ(kMessageInterrupt, interrupt_bits); |
| 244 EXPECT_EQ(IsolateTestHelper::GetStackLimit(thread), | 238 EXPECT_EQ(IsolateTestHelper::GetStackLimit(thread), |
| 245 IsolateTestHelper::GetSavedStackLimit(thread)); | 239 IsolateTestHelper::GetSavedStackLimit(thread)); |
| 246 EXPECT_EQ(kZero, IsolateTestHelper::GetDeferredInterruptsMask(thread)); | 240 EXPECT_EQ(kZero, IsolateTestHelper::GetDeferredInterruptsMask(thread)); |
| 247 EXPECT_EQ(kZero, IsolateTestHelper::GetDeferredInterrupts(thread)); | 241 EXPECT_EQ(kZero, IsolateTestHelper::GetDeferredInterrupts(thread)); |
| 248 } | 242 } |
| 249 | 243 |
| 250 } // namespace dart | 244 } // namespace dart |
| OLD | NEW |