Reland "[VM] Dart_Initialize no longer crashes after Dart_Cleanup"
This is a reland of 519ee905f9
Original change's description:
> [VM] Dart_Initialize no longer crashes after Dart_Cleanup
>
> Change-Id: I3cfdab9553aad045f024b6f9aec0b40b08234007
> Reviewed-on: https://dart-review.googlesource.com/75786
> Reviewed-by: Ryan Macnak <rmacnak@google.com>
> Commit-Queue: Ben Konyi <bkonyi@google.com>
Change-Id: Icdd901bf1ab0b675cc5f1497061a2b7b8a05d956
Reviewed-on: https://dart-review.googlesource.com/76561
Commit-Queue: Ben Konyi <bkonyi@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
This commit is contained in:
committed by
commit-bot@chromium.org
parent
e31f9fc55f
commit
3c4c62d79a
@@ -150,8 +150,15 @@ static Dart_Isolate CreateIsolateAndSetup(const char* script_uri,
|
||||
isolate = Dart_CreateIsolate(
|
||||
DART_KERNEL_ISOLATE_NAME, main, isolate_snapshot_data,
|
||||
isolate_snapshot_instructions, NULL, NULL, flags, isolate_data, error);
|
||||
if (*error != NULL) {
|
||||
free(*error);
|
||||
*error = NULL;
|
||||
}
|
||||
}
|
||||
if (isolate == NULL) {
|
||||
delete isolate_data;
|
||||
isolate_data = NULL;
|
||||
|
||||
bin::dfe.Init();
|
||||
bin::dfe.LoadKernelService(&kernel_service_buffer,
|
||||
&kernel_service_buffer_size);
|
||||
@@ -286,6 +293,10 @@ static int Main(int argc, const char** argv) {
|
||||
ASSERT(error == NULL);
|
||||
}
|
||||
|
||||
TesterState::vm_snapshot_data = dart::bin::vm_snapshot_data;
|
||||
TesterState::create_callback = CreateIsolateAndSetup;
|
||||
TesterState::cleanup_callback = CleanupIsolate;
|
||||
|
||||
error = Dart::InitOnce(
|
||||
dart::bin::vm_snapshot_data, dart::bin::vm_snapshot_instructions,
|
||||
CreateIsolateAndSetup /* create */, NULL /* shutdown */,
|
||||
@@ -304,9 +315,10 @@ static int Main(int argc, const char** argv) {
|
||||
error = Dart::Cleanup();
|
||||
ASSERT(error == NULL);
|
||||
|
||||
TestCaseBase::RunAllRaw();
|
||||
|
||||
bin::EventHandler::Stop();
|
||||
|
||||
TestCaseBase::RunAllRaw();
|
||||
// Print a warning message if no tests or benchmarks were matched.
|
||||
if (run_matches == 0) {
|
||||
bin::Log::PrintErr("No tests matched: %s\n", run_filter);
|
||||
|
||||
@@ -146,7 +146,6 @@ dart/data_uri_import_test/wrongmime: Crash
|
||||
[ $arch == x64 && ($compiler == dartk || $compiler == dartkb) && $system == windows && $strong ]
|
||||
cc/Profiler_BasicSourcePosition: Fail # http://dartbug.com/33224
|
||||
cc/Profiler_CodeTicks: Fail # dartbug.com/33337
|
||||
|
||||
[ $arch == ia32 && $compiler != dartk && $compiler != dartkp && $compiler != dartkb && $system == windows && $runtime == vm && $mode == debug ]
|
||||
cc/BitTestImmediate: Crash # dartbug.com/34252
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ bool CodeObservers::AreActive() {
|
||||
return false;
|
||||
}
|
||||
|
||||
void CodeObservers::DeleteAll() {
|
||||
void CodeObservers::Cleanup() {
|
||||
for (intptr_t i = 0; i < observers_length_; i++) {
|
||||
delete observers_[i];
|
||||
}
|
||||
@@ -57,8 +57,9 @@ void CodeObservers::DeleteAll() {
|
||||
}
|
||||
|
||||
void CodeObservers::InitOnce() {
|
||||
ASSERT(mutex_ == NULL);
|
||||
mutex_ = new Mutex();
|
||||
if (mutex_ == NULL) {
|
||||
mutex_ = new Mutex();
|
||||
}
|
||||
ASSERT(mutex_ != NULL);
|
||||
OS::RegisterCodeObservers();
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ class CodeObservers : public AllStatic {
|
||||
// Returns true if there is at least one active code observer.
|
||||
static bool AreActive();
|
||||
|
||||
static void DeleteAll();
|
||||
static void Cleanup();
|
||||
|
||||
static Mutex* mutex() { return mutex_; }
|
||||
|
||||
|
||||
@@ -195,6 +195,7 @@ TEST_CASE(EvalExpression) {
|
||||
val = Instance::Cast(obj).EvaluateCompiledExpression(
|
||||
receiver_cls, kernel_bytes, kernel_length, Array::empty_array(),
|
||||
Array::empty_array(), TypeArguments::null_type_arguments());
|
||||
free(const_cast<uint8_t*>(kernel_bytes));
|
||||
}
|
||||
EXPECT(!val.IsNull());
|
||||
EXPECT(!val.IsError());
|
||||
|
||||
+15
-4
@@ -176,7 +176,7 @@ char* Dart::InitOnce(const uint8_t* vm_isolate_snapshot,
|
||||
Api::InitOnce();
|
||||
NativeSymbolResolver::InitOnce();
|
||||
NOT_IN_PRODUCT(Profiler::InitOnce());
|
||||
SemiSpace::InitOnce();
|
||||
SemiSpace::Init();
|
||||
NOT_IN_PRODUCT(Metric::InitOnce());
|
||||
StoreBuffer::InitOnce();
|
||||
MarkingStack::InitOnce();
|
||||
@@ -454,6 +454,7 @@ const char* Dart::Cleanup() {
|
||||
WaitForIsolateShutdown();
|
||||
|
||||
IdleNotifier::Stop();
|
||||
|
||||
// Shutdown the thread pool. On return, all thread pool threads have exited.
|
||||
if (FLAG_trace_shutdown) {
|
||||
OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Deleting thread pool\n",
|
||||
@@ -462,6 +463,10 @@ const char* Dart::Cleanup() {
|
||||
delete thread_pool_;
|
||||
thread_pool_ = NULL;
|
||||
|
||||
Api::Cleanup();
|
||||
delete predefined_handles_;
|
||||
predefined_handles_ = NULL;
|
||||
|
||||
// Disable creation of any new OSThread structures which means no more new
|
||||
// threads can do an EnterIsolate. This must come after isolate shutdown
|
||||
// because new threads may need to be spawned to shutdown the isolates.
|
||||
@@ -485,12 +490,18 @@ const char* Dart::Cleanup() {
|
||||
ShutdownIsolate();
|
||||
vm_isolate_ = NULL;
|
||||
ASSERT(Isolate::IsolateListLength() == 0);
|
||||
PortMap::Cleanup();
|
||||
IdleNotifier::Cleanup();
|
||||
|
||||
TargetCPUFeatures::Cleanup();
|
||||
MarkingStack::ShutDown();
|
||||
StoreBuffer::ShutDown();
|
||||
|
||||
MarkingStack::ShutDown();
|
||||
Object::Cleanup();
|
||||
SemiSpace::Cleanup();
|
||||
#if !defined(DART_PRECOMPILED_RUNTIME)
|
||||
// Stubs are generated when not precompiled, clean them up.
|
||||
StubCode::Cleanup();
|
||||
#endif
|
||||
// Delete the current thread's TLS and set it's TLS to null.
|
||||
// If it is the last thread then the destructor would call
|
||||
// OSThread::Cleanup.
|
||||
@@ -506,7 +517,7 @@ const char* Dart::Cleanup() {
|
||||
OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Deleting code observers\n",
|
||||
UptimeMillis());
|
||||
}
|
||||
NOT_IN_PRODUCT(CodeObservers::DeleteAll());
|
||||
NOT_IN_PRODUCT(CodeObservers::Cleanup());
|
||||
if (FLAG_support_timeline) {
|
||||
if (FLAG_trace_shutdown) {
|
||||
OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Shutting down timeline\n",
|
||||
|
||||
@@ -479,8 +479,9 @@ ApiLocalScope* Api::TopScope(Thread* thread) {
|
||||
}
|
||||
|
||||
void Api::InitOnce() {
|
||||
ASSERT(api_native_key_ == kUnsetThreadLocalKey);
|
||||
api_native_key_ = OSThread::CreateThreadLocal();
|
||||
if (api_native_key_ == kUnsetThreadLocalKey) {
|
||||
api_native_key_ = OSThread::CreateThreadLocal();
|
||||
}
|
||||
ASSERT(api_native_key_ != kUnsetThreadLocalKey);
|
||||
}
|
||||
|
||||
@@ -511,6 +512,13 @@ void Api::InitHandles() {
|
||||
empty_string_handle_ = InitNewReadOnlyApiHandle(Symbols::Empty().raw());
|
||||
}
|
||||
|
||||
void Api::Cleanup() {
|
||||
true_handle_ = NULL;
|
||||
false_handle_ = NULL;
|
||||
null_handle_ = NULL;
|
||||
empty_string_handle_ = NULL;
|
||||
}
|
||||
|
||||
bool Api::StringGetPeerHelper(NativeArguments* arguments,
|
||||
int arg_index,
|
||||
void** peer) {
|
||||
|
||||
@@ -244,6 +244,9 @@ class Api : AllStatic {
|
||||
// Allocates handles for objects in the VM isolate.
|
||||
static void InitHandles();
|
||||
|
||||
// Cleanup
|
||||
static void Cleanup();
|
||||
|
||||
// Helper function to get the peer value of an external string object.
|
||||
static bool StringGetPeerHelper(NativeArguments* args,
|
||||
int arg_index,
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "vm/dart_api_impl.h"
|
||||
#include "bin/builtin.h"
|
||||
#include "bin/dartutils.h"
|
||||
#include "include/dart_api.h"
|
||||
#include "include/dart_native_api.h"
|
||||
#include "include/dart_tools_api.h"
|
||||
@@ -12,6 +13,7 @@
|
||||
#include "platform/utils.h"
|
||||
#include "vm/class_finalizer.h"
|
||||
#include "vm/compiler/jit/compiler.h"
|
||||
#include "vm/dart.h"
|
||||
#include "vm/dart_api_state.h"
|
||||
#include "vm/debugger_api_impl_test.h"
|
||||
#include "vm/heap/verifier.h"
|
||||
@@ -26,6 +28,35 @@ DECLARE_FLAG(bool, use_dart_frontend);
|
||||
|
||||
#ifndef PRODUCT
|
||||
|
||||
UNIT_TEST_CASE(DartAPI_DartInitializeAfterCleanup) {
|
||||
Dart_InitializeParams params;
|
||||
memset(¶ms, 0, sizeof(Dart_InitializeParams));
|
||||
params.version = DART_INITIALIZE_PARAMS_CURRENT_VERSION;
|
||||
params.vm_snapshot_data = TesterState::vm_snapshot_data;
|
||||
params.create = TesterState::create_callback;
|
||||
params.shutdown = TesterState::shutdown_callback;
|
||||
params.cleanup = TesterState::cleanup_callback;
|
||||
params.start_kernel_isolate = true;
|
||||
|
||||
// Reinitialize and ensure we can execute Dart code.
|
||||
EXPECT(Dart_Initialize(¶ms) == NULL);
|
||||
{
|
||||
TestIsolateScope scope;
|
||||
const char* kScriptChars =
|
||||
"int testMain() {\n"
|
||||
" return 42;\n"
|
||||
"}\n";
|
||||
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
|
||||
EXPECT_VALID(lib);
|
||||
Dart_Handle result = Dart_Invoke(lib, NewString("testMain"), 0, NULL);
|
||||
EXPECT_VALID(result);
|
||||
int64_t value = 0;
|
||||
EXPECT_VALID(Dart_IntegerToInt64(result, &value));
|
||||
EXPECT_EQ(42, value);
|
||||
}
|
||||
EXPECT(Dart_Cleanup() == NULL);
|
||||
}
|
||||
|
||||
TEST_CASE(DartAPI_ErrorHandleBasics) {
|
||||
const char* kScriptChars =
|
||||
"void testMain() {\n"
|
||||
@@ -57,7 +88,6 @@ TEST_CASE(DartAPI_ErrorHandleBasics) {
|
||||
EXPECT(Dart_IsError(Dart_ErrorGetException(instance)));
|
||||
EXPECT(Dart_IsError(Dart_ErrorGetException(error)));
|
||||
EXPECT_VALID(Dart_ErrorGetException(exception));
|
||||
|
||||
EXPECT(Dart_IsError(Dart_ErrorGetStackTrace(instance)));
|
||||
EXPECT(Dart_IsError(Dart_ErrorGetStackTrace(error)));
|
||||
EXPECT_VALID(Dart_ErrorGetStackTrace(exception));
|
||||
@@ -3539,6 +3569,7 @@ static Dart_Handle LoadScript(const char* url_str, const char* source) {
|
||||
if (error != NULL) {
|
||||
return Dart_NewApiError(error);
|
||||
}
|
||||
TestCaseBase::AddToKernelBuffers(kernel_buffer);
|
||||
return Dart_LoadScriptFromKernel(kernel_buffer, kernel_buffer_size);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -268,14 +268,17 @@ DART_EXPORT Dart_Handle Dart_EvaluateStaticExpr(Dart_Handle lib_handle,
|
||||
|
||||
const uint8_t* kernel_bytes = compilation_result.kernel;
|
||||
intptr_t kernel_length = compilation_result.kernel_size;
|
||||
return Api::NewHandle(T, lib.EvaluateCompiledExpression(
|
||||
kernel_bytes, kernel_length,
|
||||
/* type_definitions= */
|
||||
Array::empty_array(),
|
||||
/* param_values= */
|
||||
Array::empty_array(),
|
||||
/* type_param_values= */
|
||||
TypeArguments::null_type_arguments()));
|
||||
Dart_Handle result = Api::NewHandle(
|
||||
T,
|
||||
lib.EvaluateCompiledExpression(kernel_bytes, kernel_length,
|
||||
/* type_definitions= */
|
||||
Array::empty_array(),
|
||||
/* param_values= */
|
||||
Array::empty_array(),
|
||||
/* type_param_values= */
|
||||
TypeArguments::null_type_arguments()));
|
||||
free(const_cast<uint8_t*>(kernel_bytes));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,13 +29,15 @@ Mutex* BlockStack<BlockSize>::global_mutex_ = NULL;
|
||||
template <int BlockSize>
|
||||
void BlockStack<BlockSize>::InitOnce() {
|
||||
global_empty_ = new List();
|
||||
global_mutex_ = new Mutex();
|
||||
if (global_mutex_ == NULL) {
|
||||
global_mutex_ = new Mutex();
|
||||
}
|
||||
}
|
||||
|
||||
template <int BlockSize>
|
||||
void BlockStack<BlockSize>::ShutDown() {
|
||||
delete global_empty_;
|
||||
delete global_mutex_;
|
||||
global_empty_ = NULL;
|
||||
}
|
||||
|
||||
template <int BlockSize>
|
||||
|
||||
@@ -289,12 +289,19 @@ SemiSpace::~SemiSpace() {
|
||||
Mutex* SemiSpace::mutex_ = NULL;
|
||||
SemiSpace* SemiSpace::cache_ = NULL;
|
||||
|
||||
void SemiSpace::InitOnce() {
|
||||
ASSERT(mutex_ == NULL);
|
||||
mutex_ = new Mutex();
|
||||
void SemiSpace::Init() {
|
||||
if (mutex_ == NULL) {
|
||||
mutex_ = new Mutex();
|
||||
}
|
||||
ASSERT(mutex_ != NULL);
|
||||
}
|
||||
|
||||
void SemiSpace::Cleanup() {
|
||||
MutexLocker locker(mutex_);
|
||||
delete cache_;
|
||||
cache_ = NULL;
|
||||
}
|
||||
|
||||
SemiSpace* SemiSpace::New(intptr_t size_in_words, const char* name) {
|
||||
{
|
||||
MutexLocker locker(mutex_);
|
||||
|
||||
@@ -28,7 +28,8 @@ class ScavengerVisitor;
|
||||
// Wrapper around VirtualMemory that adds caching and handles the empty case.
|
||||
class SemiSpace {
|
||||
public:
|
||||
static void InitOnce();
|
||||
static void Init();
|
||||
static void Cleanup();
|
||||
|
||||
// Get a space of the given size. Returns NULL on out of memory. If size is 0,
|
||||
// returns an empty space: pointer(), start() and end() all return NULL.
|
||||
|
||||
@@ -1041,7 +1041,9 @@ Isolate::~Isolate() {
|
||||
|
||||
void Isolate::InitOnce() {
|
||||
create_callback_ = NULL;
|
||||
isolates_list_monitor_ = new Monitor();
|
||||
if (isolates_list_monitor_ == NULL) {
|
||||
isolates_list_monitor_ = new Monitor();
|
||||
}
|
||||
ASSERT(isolates_list_monitor_ != NULL);
|
||||
EnableIsolateCreation();
|
||||
}
|
||||
|
||||
@@ -639,6 +639,9 @@ void IsolateReloadContext::Reload(bool force_reload,
|
||||
const String& error_str = String::Handle(String::New(retval.error));
|
||||
free(retval.error);
|
||||
const ApiError& error = ApiError::Handle(ApiError::New(error_str));
|
||||
if (retval.kernel != NULL) {
|
||||
free(const_cast<uint8_t*>(retval.kernel));
|
||||
}
|
||||
AddReasonForCancelling(new Aborted(zone_, error));
|
||||
ReportReasonsForCancelling();
|
||||
CommonFinalizeTail();
|
||||
|
||||
@@ -136,6 +136,7 @@ TEST_CASE(IsolateReload_KernelIncrementalCompile) {
|
||||
|
||||
lib = TestCase::ReloadTestKernel(kernel_buffer, kernel_buffer_size);
|
||||
EXPECT_VALID(lib);
|
||||
free(const_cast<uint8_t*>(kernel_buffer));
|
||||
}
|
||||
result = Dart_Invoke(lib, NewString("main"), 0, NULL);
|
||||
result = Dart_IntegerToInt64(result, &value);
|
||||
@@ -197,6 +198,7 @@ TEST_CASE(IsolateReload_KernelIncrementalCompileAppAndLib) {
|
||||
|
||||
lib = TestCase::ReloadTestKernel(kernel_buffer, kernel_buffer_size);
|
||||
EXPECT_VALID(lib);
|
||||
free(const_cast<uint8_t*>(kernel_buffer));
|
||||
}
|
||||
result = Dart_Invoke(lib, NewString("main"), 0, NULL);
|
||||
result = Dart_IntegerToInt64(result, &value);
|
||||
@@ -274,6 +276,7 @@ TEST_CASE(IsolateReload_KernelIncrementalCompileGenerics) {
|
||||
|
||||
lib = TestCase::ReloadTestKernel(kernel_buffer, kernel_buffer_size);
|
||||
EXPECT_VALID(lib);
|
||||
free(const_cast<uint8_t*>(kernel_buffer));
|
||||
}
|
||||
result = Dart_Invoke(lib, NewString("main"), 0, NULL);
|
||||
result = Dart_IntegerToInt64(result, &value);
|
||||
|
||||
@@ -221,6 +221,8 @@ class RunKernelTask : public ThreadPool::Task {
|
||||
};
|
||||
|
||||
void KernelIsolate::Run() {
|
||||
MonitorLocker ml(monitor_);
|
||||
initializing_ = true;
|
||||
// Grab the isolate create callback here to avoid race conditions with tests
|
||||
// that change this after Dart_Initialize returns.
|
||||
create_callback_ = Isolate::CreateCallback();
|
||||
|
||||
@@ -40,7 +40,10 @@ class TestMessageHandler : public MessageHandler {
|
||||
end_called_(false),
|
||||
results_(NULL) {}
|
||||
|
||||
~TestMessageHandler() { delete[] port_buffer_; }
|
||||
~TestMessageHandler() {
|
||||
PortMap::ClosePorts(this);
|
||||
delete[] port_buffer_;
|
||||
}
|
||||
|
||||
void MessageNotify(Message::Priority priority) { notify_count_++; }
|
||||
|
||||
@@ -233,7 +236,6 @@ VM_UNIT_TEST_CASE(MessageHandler_HandleNextMessage) {
|
||||
EXPECT_EQ(port2, ports[0]);
|
||||
EXPECT_EQ(port3, ports[1]);
|
||||
EXPECT_EQ(port1, ports[2]);
|
||||
PortMap::ClosePorts(&handler);
|
||||
}
|
||||
|
||||
VM_UNIT_TEST_CASE(MessageHandler_HandleNextMessage_ProcessOOBAfterError) {
|
||||
@@ -394,7 +396,6 @@ VM_UNIT_TEST_CASE(MessageHandler_Run) {
|
||||
}
|
||||
handler_peer.decrement_live_ports();
|
||||
EXPECT(!handler.HasLivePorts());
|
||||
PortMap::ClosePorts(&handler);
|
||||
delete[] ports;
|
||||
}
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ void Metric::Init(const char* name, const char* description, Unit unit) {
|
||||
RegisterWithVM();
|
||||
}
|
||||
|
||||
Metric::~Metric() {
|
||||
void Metric::CleanupInstance() {
|
||||
// Only deregister metrics which had been registered. Metrics without a name
|
||||
// are from shallow copy isolates.
|
||||
if (name_ != NULL) {
|
||||
@@ -66,6 +66,10 @@ Metric::~Metric() {
|
||||
}
|
||||
}
|
||||
|
||||
Metric::~Metric() {
|
||||
CleanupInstance();
|
||||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
static const char* UnitString(intptr_t unit) {
|
||||
switch (unit) {
|
||||
@@ -321,6 +325,10 @@ void Metric::Cleanup() {
|
||||
}
|
||||
OS::PrintErr("\n");
|
||||
}
|
||||
#define VM_METRIC_CLEANUP(type, variable, name, unit) \
|
||||
vm_metric_##variable##_.CleanupInstance();
|
||||
VM_METRIC_LIST(VM_METRIC_CLEANUP);
|
||||
#undef VM_METRIC_CLEANUP
|
||||
}
|
||||
|
||||
MaxMetric::MaxMetric() : Metric() {
|
||||
|
||||
@@ -57,6 +57,8 @@ class Metric {
|
||||
// Initialize and register a metric for the VM.
|
||||
void Init(const char* name, const char* description, Unit unit);
|
||||
|
||||
void CleanupInstance();
|
||||
|
||||
virtual ~Metric();
|
||||
|
||||
#ifndef PRODUCT
|
||||
|
||||
@@ -950,6 +950,46 @@ void Object::FinishInitOnce(Isolate* isolate) {
|
||||
void_type_->SetTypeTestingStub(instr);
|
||||
}
|
||||
|
||||
void Object::Cleanup() {
|
||||
null_ = reinterpret_cast<RawObject*>(RAW_NULL);
|
||||
class_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
|
||||
dynamic_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
|
||||
void_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
|
||||
unresolved_class_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
|
||||
type_arguments_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
|
||||
patch_class_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
|
||||
function_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
|
||||
closure_data_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
|
||||
signature_data_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
|
||||
redirection_data_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
|
||||
field_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
|
||||
literal_token_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
|
||||
token_stream_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
|
||||
script_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
|
||||
library_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
|
||||
namespace_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
|
||||
kernel_program_info_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
|
||||
code_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
|
||||
instructions_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
|
||||
object_pool_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
|
||||
pc_descriptors_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
|
||||
code_source_map_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
|
||||
stackmap_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
|
||||
var_descriptors_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
|
||||
exception_handlers_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
|
||||
context_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
|
||||
context_scope_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
|
||||
singletargetcache_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
|
||||
unlinkedcall_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
|
||||
icdata_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
|
||||
megamorphic_cache_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
|
||||
subtypetestcache_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
|
||||
api_error_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
|
||||
language_error_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
|
||||
unhandled_exception_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
|
||||
unwind_error_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
|
||||
}
|
||||
|
||||
// An object visitor which will mark all visited objects. This is used to
|
||||
// premark all objects in the vm_isolate_ heap. Also precalculates hash
|
||||
// codes so that we can get the identity hash code of objects in the read-
|
||||
@@ -12482,6 +12522,10 @@ static RawObject* EvaluateCompiledExpressionHelper(
|
||||
kernel::KernelLoader loader(kernel_pgm);
|
||||
const Object& result = Object::Handle(
|
||||
loader.LoadExpressionEvaluationFunction(library_url, klass));
|
||||
|
||||
delete kernel_pgm;
|
||||
kernel_pgm = NULL;
|
||||
|
||||
if (result.IsError()) return result.raw();
|
||||
|
||||
const Function& callee = Function::Cast(result);
|
||||
|
||||
@@ -465,6 +465,8 @@ class Object {
|
||||
static void FinalizeVMIsolate(Isolate* isolate);
|
||||
static void FinalizeReadOnlyObject(RawObject* object);
|
||||
|
||||
static void Cleanup();
|
||||
|
||||
// Initialize a new isolate either from a Kernel IR, from source, or from a
|
||||
// snapshot.
|
||||
static RawError* Init(Isolate* isolate,
|
||||
|
||||
@@ -357,12 +357,6 @@ void OS::PrintErr(const char* format, ...) {
|
||||
}
|
||||
|
||||
void OS::InitOnce() {
|
||||
// TODO(5411554): For now we check that initonce is called only once,
|
||||
// Once there is more formal mechanism to call InitOnce we can move
|
||||
// this check there.
|
||||
static bool init_once_called = false;
|
||||
ASSERT(init_once_called == false);
|
||||
init_once_called = true;
|
||||
}
|
||||
|
||||
void OS::Shutdown() {}
|
||||
|
||||
@@ -254,12 +254,6 @@ void OS::PrintErr(const char* format, ...) {
|
||||
}
|
||||
|
||||
void OS::InitOnce() {
|
||||
// TODO(5411554): For now we check that initonce is called only once,
|
||||
// Once there is more formal mechanism to call InitOnce we can move
|
||||
// this check there.
|
||||
static bool init_once_called = false;
|
||||
ASSERT(init_once_called == false);
|
||||
init_once_called = true;
|
||||
auto environment_services = std::make_shared<component::Services>();
|
||||
auto env_service_root = component::subtle::CreateStaticServiceRootHandle();
|
||||
environment_services->Bind(std::move(env_service_root));
|
||||
|
||||
@@ -655,14 +655,7 @@ void OS::PrintErr(const char* format, ...) {
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void OS::InitOnce() {
|
||||
// TODO(5411554): For now we check that initonce is called only once,
|
||||
// Once there is more formal mechanism to call InitOnce we can move
|
||||
// this check there.
|
||||
static bool init_once_called = false;
|
||||
ASSERT(init_once_called == false);
|
||||
init_once_called = true;
|
||||
}
|
||||
void OS::InitOnce() {}
|
||||
|
||||
void OS::Shutdown() {}
|
||||
|
||||
|
||||
@@ -303,13 +303,6 @@ void OS::PrintErr(const char* format, ...) {
|
||||
}
|
||||
|
||||
void OS::InitOnce() {
|
||||
// TODO(5411554): For now we check that initonce is called only once,
|
||||
// Once there is more formal mechanism to call InitOnce we can move
|
||||
// this check there.
|
||||
static bool init_once_called = false;
|
||||
ASSERT(init_once_called == false);
|
||||
init_once_called = true;
|
||||
|
||||
// See https://github.com/dart-lang/sdk/issues/29539
|
||||
// This is a workaround for a macos bug, we eagerly call localtime_r so that
|
||||
// libnotify is initialized early before any fork happens.
|
||||
|
||||
@@ -138,13 +138,15 @@ static void DeleteThread(void* thread) {
|
||||
|
||||
void OSThread::InitOnce() {
|
||||
// Allocate the global OSThread lock.
|
||||
ASSERT(thread_list_lock_ == NULL);
|
||||
thread_list_lock_ = new Mutex();
|
||||
if (thread_list_lock_ == NULL) {
|
||||
thread_list_lock_ = new Mutex();
|
||||
}
|
||||
ASSERT(thread_list_lock_ != NULL);
|
||||
|
||||
// Create the thread local key.
|
||||
ASSERT(thread_key_ == kUnsetThreadLocalKey);
|
||||
thread_key_ = CreateThreadLocal(DeleteThread);
|
||||
if (thread_key_ == kUnsetThreadLocalKey) {
|
||||
thread_key_ = CreateThreadLocal(DeleteThread);
|
||||
}
|
||||
ASSERT(thread_key_ != kUnsetThreadLocalKey);
|
||||
|
||||
// Enable creation of OSThread structures in the VM.
|
||||
|
||||
@@ -313,11 +313,10 @@ void OS::PrintErr(const char* format, ...) {
|
||||
}
|
||||
|
||||
void OS::InitOnce() {
|
||||
// TODO(5411554): For now we check that initonce is called only once,
|
||||
// Once there is more formal mechanism to call InitOnce we can move
|
||||
// this check there.
|
||||
static bool init_once_called = false;
|
||||
ASSERT(init_once_called == false);
|
||||
if (init_once_called) {
|
||||
return;
|
||||
}
|
||||
init_once_called = true;
|
||||
// Do not pop up a message box when abort is called.
|
||||
_set_abort_behavior(0, _WRITE_ABORT_MSG);
|
||||
|
||||
+27
-4
@@ -277,19 +277,42 @@ Isolate* PortMap::GetIsolate(Dart_Port id) {
|
||||
}
|
||||
|
||||
void PortMap::InitOnce() {
|
||||
mutex_ = new Mutex();
|
||||
if (mutex_ == NULL) {
|
||||
mutex_ = new Mutex();
|
||||
}
|
||||
ASSERT(mutex_ != NULL);
|
||||
prng_ = new Random();
|
||||
|
||||
static const intptr_t kInitialCapacity = 8;
|
||||
// TODO(iposva): Verify whether we want to keep exponentially growing.
|
||||
ASSERT(Utils::IsPowerOfTwo(kInitialCapacity));
|
||||
map_ = new Entry[kInitialCapacity];
|
||||
memset(map_, 0, kInitialCapacity * sizeof(Entry));
|
||||
capacity_ = kInitialCapacity;
|
||||
if (map_ == NULL) {
|
||||
// TODO(bkonyi): don't keep map_ after Dart_Cleanup.
|
||||
map_ = new Entry[kInitialCapacity];
|
||||
capacity_ = kInitialCapacity;
|
||||
}
|
||||
memset(map_, 0, capacity_ * sizeof(Entry));
|
||||
used_ = 0;
|
||||
deleted_ = 0;
|
||||
}
|
||||
|
||||
void PortMap::Cleanup() {
|
||||
ASSERT(map_ != NULL);
|
||||
ASSERT(prng_ != NULL);
|
||||
for (intptr_t i = 0; i < capacity_; ++i) {
|
||||
auto handler = map_[i].handler;
|
||||
if (handler != NULL && handler != deleted_entry_) {
|
||||
ClosePorts(handler);
|
||||
delete handler;
|
||||
}
|
||||
}
|
||||
delete prng_;
|
||||
prng_ = NULL;
|
||||
// TODO(bkonyi): find out why deleting map_ sometimes causes crashes.
|
||||
// delete[] map_;
|
||||
// map_ = NULL;
|
||||
}
|
||||
|
||||
void PortMap::PrintPortsForMessageHandler(MessageHandler* handler,
|
||||
JSONStream* stream) {
|
||||
#ifndef PRODUCT
|
||||
|
||||
@@ -55,6 +55,7 @@ class PortMap : public AllStatic {
|
||||
static Isolate* GetIsolate(Dart_Port id);
|
||||
|
||||
static void InitOnce();
|
||||
static void Cleanup();
|
||||
|
||||
static void PrintPortsForMessageHandler(MessageHandler* handler,
|
||||
JSONStream* stream);
|
||||
|
||||
@@ -30,7 +30,10 @@ class ServiceTestMessageHandler : public MessageHandler {
|
||||
public:
|
||||
ServiceTestMessageHandler() : _msg(NULL) {}
|
||||
|
||||
~ServiceTestMessageHandler() { free(_msg); }
|
||||
~ServiceTestMessageHandler() {
|
||||
PortMap::ClosePorts(this);
|
||||
free(_msg);
|
||||
}
|
||||
|
||||
MessageStatus HandleMessage(Message* message) {
|
||||
if (_msg != NULL) {
|
||||
|
||||
@@ -47,6 +47,11 @@ void StubCode::InitOnce() {
|
||||
// Stubs will be loaded from the snapshot.
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
void StubCode::Cleanup() {
|
||||
// Stubs will be loaded from the snapshot.
|
||||
UNREACHABLE();
|
||||
}
|
||||
#else
|
||||
|
||||
#define STUB_CODE_GENERATE(name) \
|
||||
@@ -61,6 +66,16 @@ void StubCode::InitOnce() {
|
||||
|
||||
#undef STUB_CODE_GENERATE
|
||||
|
||||
#define STUB_CODE_CLEANUP(name) \
|
||||
delete entries_[k##name##Index]; \
|
||||
entries_[k##name##Index] = NULL;
|
||||
|
||||
void StubCode::Cleanup() {
|
||||
VM_STUB_CODE_LIST(STUB_CODE_CLEANUP);
|
||||
}
|
||||
|
||||
#undef STUB_CODE_CLEANUP
|
||||
|
||||
RawCode* StubCode::Generate(const char* name,
|
||||
void (*GenerateStub)(Assembler* assembler)) {
|
||||
ObjectPoolWrapper object_pool_wrapper;
|
||||
|
||||
@@ -150,6 +150,7 @@ class StubCode : public AllStatic {
|
||||
// only once and the stub code resides in the vm_isolate heap.
|
||||
static void InitOnce();
|
||||
|
||||
static void Cleanup();
|
||||
static void VisitObjectPointers(ObjectPointerVisitor* visitor);
|
||||
|
||||
// Returns true if stub code has been initialized.
|
||||
|
||||
@@ -37,6 +37,11 @@ namespace dart {
|
||||
const uint8_t* platform_strong_dill = kPlatformStrongDill;
|
||||
const intptr_t platform_strong_dill_size = kPlatformStrongDillSize;
|
||||
|
||||
const uint8_t* TesterState::vm_snapshot_data = NULL;
|
||||
Dart_IsolateCreateCallback TesterState::create_callback = NULL;
|
||||
Dart_IsolateShutdownCallback TesterState::shutdown_callback = NULL;
|
||||
Dart_IsolateCleanupCallback TesterState::cleanup_callback = NULL;
|
||||
|
||||
DEFINE_FLAG(bool,
|
||||
use_dart_frontend,
|
||||
true,
|
||||
@@ -44,8 +49,14 @@ DEFINE_FLAG(bool,
|
||||
|
||||
DECLARE_FLAG(bool, strong);
|
||||
|
||||
void KernelBufferList::AddBufferToList(const uint8_t* kernel_buffer) {
|
||||
next_ = new KernelBufferList(kernel_buffer_, next_);
|
||||
kernel_buffer_ = kernel_buffer;
|
||||
}
|
||||
|
||||
TestCaseBase* TestCaseBase::first_ = NULL;
|
||||
TestCaseBase* TestCaseBase::tail_ = NULL;
|
||||
KernelBufferList* TestCaseBase::current_kernel_buffers_ = NULL;
|
||||
|
||||
TestCaseBase::TestCaseBase(const char* name)
|
||||
: raw_test_(false), next_(NULL), name_(name) {
|
||||
@@ -62,6 +73,7 @@ void TestCaseBase::RunAllRaw() {
|
||||
while (test != NULL) {
|
||||
if (test->raw_test_) {
|
||||
test->RunTest();
|
||||
CleanupState();
|
||||
}
|
||||
test = test->next_;
|
||||
}
|
||||
@@ -72,11 +84,28 @@ void TestCaseBase::RunAll() {
|
||||
while (test != NULL) {
|
||||
if (!test->raw_test_) {
|
||||
test->RunTest();
|
||||
CleanupState();
|
||||
}
|
||||
test = test->next_;
|
||||
}
|
||||
}
|
||||
|
||||
void TestCaseBase::CleanupState() {
|
||||
if (current_kernel_buffers_ != NULL) {
|
||||
delete current_kernel_buffers_;
|
||||
current_kernel_buffers_ = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void TestCaseBase::AddToKernelBuffers(const uint8_t* kernel_buffer) {
|
||||
ASSERT(kernel_buffer != NULL);
|
||||
if (current_kernel_buffers_ == NULL) {
|
||||
current_kernel_buffers_ = new KernelBufferList(kernel_buffer);
|
||||
} else {
|
||||
current_kernel_buffers_->AddBufferToList(kernel_buffer);
|
||||
}
|
||||
}
|
||||
|
||||
Dart_Isolate TestCase::CreateIsolate(const uint8_t* data_buffer,
|
||||
intptr_t len,
|
||||
const uint8_t* instr_buffer,
|
||||
@@ -323,10 +352,18 @@ char* TestCase::ValidateCompilationResult(
|
||||
char* result =
|
||||
OS::SCreate(zone, "Compilation failed %s", compilation_result.error);
|
||||
free(compilation_result.error);
|
||||
if (compilation_result.kernel != NULL) {
|
||||
free(const_cast<uint8_t*>(compilation_result.kernel));
|
||||
}
|
||||
*kernel_buffer = NULL;
|
||||
*kernel_buffer_size = 0;
|
||||
return result;
|
||||
}
|
||||
*kernel_buffer = compilation_result.kernel;
|
||||
*kernel_buffer_size = compilation_result.kernel_size;
|
||||
if (compilation_result.error != NULL) {
|
||||
free(compilation_result.error);
|
||||
}
|
||||
if (kernel_buffer == NULL) {
|
||||
return OS::SCreate(zone, "front end generated a NULL kernel file");
|
||||
}
|
||||
@@ -525,6 +562,9 @@ Dart_Handle TestCase::LoadTestLibrary(const char* lib_uri,
|
||||
Dart_LoadLibraryFromKernel(kernel_buffer, kernel_buffer_size);
|
||||
EXPECT_VALID(lib);
|
||||
|
||||
// Ensure kernel buffer isn't leaked after test is run.
|
||||
AddToKernelBuffers(kernel_buffer);
|
||||
|
||||
// TODO(32618): Kernel doesn't correctly represent the root library.
|
||||
lib = Dart_LookupLibrary(Dart_NewStringFromCString(sourcefiles[0].uri));
|
||||
DART_CHECK_VALID(lib);
|
||||
@@ -567,6 +607,9 @@ Dart_Handle TestCase::LoadTestScriptWithDFE(int sourcefiles_count,
|
||||
Dart_LoadLibraryFromKernel(kernel_buffer, kernel_buffer_size);
|
||||
DART_CHECK_VALID(lib);
|
||||
|
||||
// Ensure kernel buffer isn't leaked after test is run.
|
||||
AddToKernelBuffers(kernel_buffer);
|
||||
|
||||
// BOGUS: Kernel doesn't correctly represent the root library.
|
||||
lib = Dart_LookupLibrary(Dart_NewStringFromCString(
|
||||
entry_script_uri != NULL ? entry_script_uri : sourcefiles[0].uri));
|
||||
@@ -658,6 +701,9 @@ Dart_Handle TestCase::ReloadTestScript(const char* script) {
|
||||
if (compilation_result.status != Dart_KernelCompilationStatus_Ok) {
|
||||
Dart_Handle result = Dart_NewApiError(compilation_result.error);
|
||||
free(compilation_result.error);
|
||||
if (compilation_result.kernel != NULL) {
|
||||
free(const_cast<uint8_t*>(compilation_result.kernel));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -277,6 +277,36 @@ extern const uint8_t* platform_strong_dill;
|
||||
extern const intptr_t platform_dill_size;
|
||||
extern const intptr_t platform_strong_dill_size;
|
||||
|
||||
class TesterState : public AllStatic {
|
||||
public:
|
||||
static const uint8_t* vm_snapshot_data;
|
||||
static Dart_IsolateCreateCallback create_callback;
|
||||
static Dart_IsolateShutdownCallback shutdown_callback;
|
||||
static Dart_IsolateCleanupCallback cleanup_callback;
|
||||
};
|
||||
|
||||
class KernelBufferList {
|
||||
public:
|
||||
explicit KernelBufferList(const uint8_t* kernel_buffer)
|
||||
: kernel_buffer_(kernel_buffer), next_(NULL) {}
|
||||
|
||||
KernelBufferList(const uint8_t* kernel_buffer, KernelBufferList* next)
|
||||
: kernel_buffer_(kernel_buffer), next_(next) {}
|
||||
|
||||
~KernelBufferList() {
|
||||
free(const_cast<uint8_t*>(kernel_buffer_));
|
||||
if (next_ != NULL) {
|
||||
delete next_;
|
||||
}
|
||||
}
|
||||
|
||||
void AddBufferToList(const uint8_t* kernel_buffer);
|
||||
|
||||
private:
|
||||
const uint8_t* kernel_buffer_;
|
||||
KernelBufferList* next_;
|
||||
};
|
||||
|
||||
class TestCaseBase {
|
||||
public:
|
||||
explicit TestCaseBase(const char* name);
|
||||
@@ -289,8 +319,11 @@ class TestCaseBase {
|
||||
|
||||
static void RunAll();
|
||||
static void RunAllRaw();
|
||||
static void CleanupState();
|
||||
static void AddToKernelBuffers(const uint8_t* kernel_buffer);
|
||||
|
||||
protected:
|
||||
static KernelBufferList* current_kernel_buffers_;
|
||||
bool raw_test_;
|
||||
|
||||
private:
|
||||
|
||||
Reference in New Issue
Block a user