[vm] Assert handles are only allocated when the thread is preventing safepoints.

Threads in the native or blocked states don't prevent safepoints, so they may run concurrently with a safepoint operation like GC. It is not safe for handles to be allocated while the GC is visiting them, so these threads must not allocate handles. Assert only threads in the VM or generated states, which prevent safepoints until they check in, may allocate handles. (Generated code does not allocate handles, but leaf runtime entries remain in the generated state.)

Bug: https://github.com/dart-lang/sdk/issues/34883
Change-Id: I1a211778f7ef96b53a2405f0ee9dde7871b122b6
Reviewed-on: https://dart-review.googlesource.com/c/81540
Commit-Queue: Ryan Macnak <rmacnak@google.com>
Reviewed-by: Siva Annamalai <asiva@google.com>
Reviewed-by: Vyacheslav Egorov <vegorov@google.com>
This commit is contained in:
Ryan Macnak 2018-10-31 19:51:52 +00:00 committed by commit-bot@chromium.org
parent a074bcf93c
commit 7514ce941e
42 changed files with 709 additions and 838 deletions

View file

@ -255,14 +255,9 @@ static const char* CanonicalizeUri(Thread* thread,
const char* result = NULL;
Zone* zone = thread->zone();
Isolate* isolate = thread->isolate();
Dart_LibraryTagHandler handler = isolate->library_tag_handler();
if (handler != NULL) {
TransitionVMToNative transition(thread);
Dart_EnterScope();
Dart_Handle handle =
handler(Dart_kCanonicalizeUrl, Api::NewHandle(thread, library.raw()),
Api::NewHandle(thread, uri.raw()));
const Object& obj = Object::Handle(Api::UnwrapHandle(handle));
if (isolate->HasTagHandler()) {
const Object& obj = Object::Handle(
isolate->CallTagHandler(Dart_kCanonicalizeUrl, library, uri));
if (obj.IsString()) {
result = String2UTF8(String::Cast(obj));
} else if (obj.IsError()) {
@ -276,7 +271,6 @@ static const char* CanonicalizeUri(Thread* thread,
"library tag handler returned wrong type",
uri.ToCString());
}
Dart_ExitScope();
} else {
*error = zone->PrintToString(
"Unable to canonicalize uri '%s': no library tag handler found.",

View file

@ -650,8 +650,7 @@ static void ThrowLanguageError(const char* message) {
DEFINE_NATIVE_ENTRY(IsolateMirror_loadUri, 1) {
GET_NON_NULL_NATIVE_ARGUMENT(String, uri, arguments->NativeArgAt(0));
Dart_LibraryTagHandler handler = isolate->library_tag_handler();
if (handler == NULL) {
if (!isolate->HasTagHandler()) {
ThrowLanguageError("no library handler registered");
}
@ -663,16 +662,12 @@ DEFINE_NATIVE_ENTRY(IsolateMirror_loadUri, 1) {
canonical_uri = uri.raw();
} else {
isolate->BlockClassFinalization();
Object& result = Object::Handle(zone);
{
TransitionVMToNative transition(thread);
Api::Scope api_scope(thread);
Dart_Handle retval = handler(
Dart_kCanonicalizeUrl,
Api::NewHandle(thread, isolate->object_store()->root_library()),
Api::NewHandle(thread, uri.raw()));
result = Api::UnwrapHandle(retval);
}
const Object& result = Object::Handle(
zone,
isolate->CallTagHandler(
Dart_kCanonicalizeUrl,
Library::Handle(zone, isolate->object_store()->root_library()),
uri));
isolate->UnblockClassFinalization();
if (result.IsError()) {
if (result.IsLanguageError()) {
@ -695,16 +690,11 @@ DEFINE_NATIVE_ENTRY(IsolateMirror_loadUri, 1) {
// Request the embedder to load the library.
isolate->BlockClassFinalization();
Object& result = Object::Handle(zone);
{
TransitionVMToNative transition(thread);
Api::Scope api_scope(thread);
Dart_Handle retval =
handler(Dart_kImportTag,
Api::NewHandle(thread, isolate->object_store()->root_library()),
Api::NewHandle(thread, canonical_uri.raw()));
result = Api::UnwrapHandle(retval);
}
Object& result = Object::Handle(
zone, isolate->CallTagHandler(
Dart_kImportTag,
Library::Handle(zone, isolate->object_store()->root_library()),
canonical_uri));
isolate->UnblockClassFinalization();
if (result.IsError()) {
if (result.IsLanguageError()) {

View file

@ -365,49 +365,51 @@ DEFINE_NATIVE_ENTRY(VMService_DecodeAssets, 1) {
return Object::null();
}
GET_NON_NULL_NATIVE_ARGUMENT(TypedData, data, arguments->NativeArgAt(0));
TransitionVMToNative transition(thread);
Api::Scope scope(thread);
Dart_Handle data_handle = Api::NewHandle(thread, data.raw());
Dart_Handle result_list;
{
TransitionVMToNative transition(thread);
Dart_TypedData_Type typ;
void* bytes;
intptr_t length;
Dart_Handle err =
Dart_TypedDataAcquireData(data_handle, &typ, &bytes, &length);
ASSERT(!Dart_IsError(err));
Dart_TypedData_Type typ;
void* bytes;
intptr_t length;
Dart_Handle err =
Dart_TypedDataAcquireData(data_handle, &typ, &bytes, &length);
ASSERT(!Dart_IsError(err));
TarArchive archive(reinterpret_cast<uint8_t*>(bytes), length);
archive.Read();
TarArchive archive(reinterpret_cast<uint8_t*>(bytes), length);
archive.Read();
err = Dart_TypedDataReleaseData(data_handle);
ASSERT(!Dart_IsError(err));
err = Dart_TypedDataReleaseData(data_handle);
ASSERT(!Dart_IsError(err));
intptr_t archive_size = archive.Length();
intptr_t archive_size = archive.Length();
Dart_Handle result_list = Dart_NewList(2 * archive_size);
ASSERT(!Dart_IsError(result_list));
result_list = Dart_NewList(2 * archive_size);
ASSERT(!Dart_IsError(result_list));
intptr_t idx = 0;
while (archive.HasMore()) {
char* filename = archive.NextFilename();
intptr_t filename_length = strlen(filename);
uint8_t* contents = archive.NextContent();
intptr_t contents_length = archive.NextContentLength();
intptr_t idx = 0;
while (archive.HasMore()) {
char* filename = archive.NextFilename();
intptr_t filename_length = strlen(filename);
uint8_t* contents = archive.NextContent();
intptr_t contents_length = archive.NextContentLength();
Dart_Handle dart_filename = Dart_NewExternalLatin1String(
reinterpret_cast<uint8_t*>(filename), filename_length, filename,
filename_length, FilenameFinalizer);
ASSERT(!Dart_IsError(dart_filename));
Dart_Handle dart_filename = Dart_NewExternalLatin1String(
reinterpret_cast<uint8_t*>(filename), filename_length, filename,
filename_length, FilenameFinalizer);
ASSERT(!Dart_IsError(dart_filename));
Dart_Handle dart_contents = Dart_NewExternalTypedDataWithFinalizer(
Dart_TypedData_kUint8, contents, contents_length, contents,
contents_length, ContentsFinalizer);
ASSERT(!Dart_IsError(dart_contents));
Dart_Handle dart_contents = Dart_NewExternalTypedDataWithFinalizer(
Dart_TypedData_kUint8, contents, contents_length, contents,
contents_length, ContentsFinalizer);
ASSERT(!Dart_IsError(dart_contents));
Dart_ListSetAt(result_list, idx, dart_filename);
Dart_ListSetAt(result_list, (idx + 1), dart_contents);
idx += 2;
Dart_ListSetAt(result_list, idx, dart_filename);
Dart_ListSetAt(result_list, (idx + 1), dart_contents);
idx += 2;
}
}
return Api::UnwrapArrayHandle(thread->zone(), result_list).raw();
#else

View file

@ -99,6 +99,8 @@ BENCHMARK(CorelibCompileAll) {
bin::Builtin::SetNativeResolver(bin::Builtin::kIOLibrary);
bin::Builtin::SetNativeResolver(bin::Builtin::kCLILibrary);
TransitionNativeToVM transition(thread);
StackZone zone(thread);
HANDLESCOPE(thread);
Timer timer(true, "Compile all of Core lib benchmark");
timer.Start();
const Error& error =
@ -423,24 +425,27 @@ BENCHMARK(Dart2JSCompileAll) {
// Measure frame lookup during stack traversal.
//
static void StackFrame_accessFrame(Dart_NativeArguments args) {
const int kNumIterations = 100;
Code& code = Code::Handle();
Timer timer(true, "LookupDartCode benchmark");
timer.Start();
for (int i = 0; i < kNumIterations; i++) {
StackFrameIterator frames(ValidationPolicy::kDontValidateFrames,
Thread::Current(),
StackFrameIterator::kNoCrossThreadIteration);
StackFrame* frame = frames.NextFrame();
while (frame != NULL) {
if (frame->IsStubFrame()) {
code = frame->LookupDartCode();
EXPECT(code.function() == Function::null());
} else if (frame->IsDartFrame()) {
code = frame->LookupDartCode();
EXPECT(code.function() != Function::null());
{
Thread* thread = Thread::Current();
TransitionNativeToVM transition(thread);
const int kNumIterations = 100;
Code& code = Code::Handle(thread->zone());
for (int i = 0; i < kNumIterations; i++) {
StackFrameIterator frames(ValidationPolicy::kDontValidateFrames, thread,
StackFrameIterator::kNoCrossThreadIteration);
StackFrame* frame = frames.NextFrame();
while (frame != NULL) {
if (frame->IsStubFrame()) {
code = frame->LookupDartCode();
EXPECT(code.function() == Function::null());
} else if (frame->IsDartFrame()) {
code = frame->LookupDartCode();
EXPECT(code.function() != Function::null());
}
frame = frames.NextFrame();
}
frame = frames.NextFrame();
}
}
timer.Stop();
@ -532,9 +537,13 @@ BENCHMARK_SIZE(CoreSnapshotSize) {
// Need to load the script into the dart: core library due to
// the import of dart:_internal.
TestCase::LoadCoreTestScript(kScriptChars, NULL);
Api::CheckAndFinalizePendingClasses(thread);
TransitionNativeToVM transition(thread);
StackZone zone(thread);
HANDLESCOPE(thread);
Api::CheckAndFinalizePendingClasses(thread);
// Write snapshot with object content.
FullSnapshotWriter writer(Snapshot::kFull, &vm_snapshot_data_buffer,
&isolate_snapshot_data_buffer, &malloc_allocator,
@ -569,9 +578,13 @@ BENCHMARK_SIZE(StandaloneSnapshotSize) {
// Need to load the script into the dart: core library due to
// the import of dart:_internal.
TestCase::LoadCoreTestScript(kScriptChars, NULL);
Api::CheckAndFinalizePendingClasses(thread);
TransitionNativeToVM transition(thread);
StackZone zone(thread);
HANDLESCOPE(thread);
Api::CheckAndFinalizePendingClasses(thread);
// Write snapshot with object content.
FullSnapshotWriter writer(Snapshot::kFull, &vm_snapshot_data_buffer,
&isolate_snapshot_data_buffer, &malloc_allocator,
@ -611,7 +624,12 @@ BENCHMARK(EnterExitIsolate) {
"\n";
const intptr_t kLoopCount = 1000000;
TestCase::LoadTestScript(kScriptChars, NULL);
Api::CheckAndFinalizePendingClasses(thread);
{
TransitionNativeToVM transition(thread);
StackZone zone(thread);
HANDLESCOPE(thread);
Api::CheckAndFinalizePendingClasses(thread);
}
Dart_Isolate isolate = Dart_CurrentIsolate();
Timer timer(true, "Enter and Exit isolate");
timer.Start();
@ -626,6 +644,8 @@ BENCHMARK(EnterExitIsolate) {
BENCHMARK(SerializeNull) {
TransitionNativeToVM transition(thread);
StackZone zone(thread);
HANDLESCOPE(thread);
const Object& null_object = Object::Handle();
const intptr_t kLoopCount = 1000000;
Timer timer(true, "Serialize Null");
@ -648,6 +668,8 @@ BENCHMARK(SerializeNull) {
BENCHMARK(SerializeSmi) {
TransitionNativeToVM transition(thread);
StackZone zone(thread);
HANDLESCOPE(thread);
const Integer& smi_object = Integer::Handle(Smi::New(42));
const intptr_t kLoopCount = 1000000;
Timer timer(true, "Serialize Smi");
@ -670,6 +692,8 @@ BENCHMARK(SerializeSmi) {
BENCHMARK(SimpleMessage) {
TransitionNativeToVM transition(thread);
StackZone zone(thread);
HANDLESCOPE(thread);
const Array& array_object = Array::Handle(Array::New(2));
array_object.SetAt(0, Integer::Handle(Smi::New(42)));
array_object.SetAt(1, Object::Handle());
@ -704,6 +728,8 @@ BENCHMARK(LargeMap) {
Dart_Handle h_result = Dart_Invoke(h_lib, NewString("makeMap"), 0, NULL);
EXPECT_VALID(h_result);
TransitionNativeToVM transition(thread);
StackZone zone(thread);
HANDLESCOPE(thread);
Instance& map = Instance::Handle();
map ^= Api::UnwrapHandle(h_result);
const intptr_t kLoopCount = 100;

View file

@ -43,8 +43,6 @@ extern const uint8_t* core_isolate_snapshot_instructions;
BenchmarkIsolateScope __isolate__(benchmark); \
Thread* __thread__ = Thread::Current(); \
ASSERT(__thread__->isolate() == benchmark->isolate()); \
StackZone __zone__(__thread__); \
HandleScope __hs__(__thread__); \
Dart_BenchmarkHelper##name(benchmark, __thread__); \
MallocHooks::set_stack_trace_collection_enabled( \
__stack_trace_collection_enabled__); \

View file

@ -34,7 +34,9 @@ static struct NativeEntries {
Dart_NativeFunction BootstrapNatives::Lookup(Dart_Handle name,
int argument_count,
bool* auto_setup_scope) {
const Object& obj = Object::Handle(Api::UnwrapHandle(name));
Thread* thread = Thread::Current();
TransitionNativeToVM transition(thread);
const Object& obj = Object::Handle(thread->zone(), Api::UnwrapHandle(name));
if (!obj.IsString()) {
return NULL;
}

View file

@ -7,7 +7,7 @@
namespace dart {
TEST_CASE(InstructionTests) {
ISOLATE_UNIT_TEST_CASE(InstructionTests) {
TargetEntryInstr* target_instr =
new TargetEntryInstr(1, kInvalidTryIndex, DeoptId::kNone);
EXPECT(target_instr->IsBlockEntry());
@ -19,7 +19,7 @@ TEST_CASE(InstructionTests) {
EXPECT(context->GetBlock() == target_instr);
}
TEST_CASE(OptimizationTests) {
ISOLATE_UNIT_TEST_CASE(OptimizationTests) {
JoinEntryInstr* join =
new JoinEntryInstr(1, kInvalidTryIndex, DeoptId::kNone);

View file

@ -110,7 +110,7 @@ ISOLATE_UNIT_TEST_CASE(CompileFunctionOnHelperThread) {
BackgroundCompiler::Stop(isolate);
}
TEST_CASE(RegenerateAllocStubs) {
ISOLATE_UNIT_TEST_CASE(RegenerateAllocStubs) {
const char* kScriptChars =
"class A {\n"
"}\n"
@ -120,29 +120,39 @@ TEST_CASE(RegenerateAllocStubs) {
" return unOpt();\n"
"}\n";
Class& cls = Class::Handle();
TransitionVMToNative transition(thread);
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
EXPECT_VALID(result);
RawLibrary* raw_library = Library::RawCast(Api::UnwrapHandle(lib));
Library& lib_handle = Library::ZoneHandle(raw_library);
Class& cls = Class::Handle(
lib_handle.LookupClass(String::Handle(Symbols::New(thread, "A"))));
EXPECT(!cls.IsNull());
Zone* zone = thread->zone();
const Code& stub =
Code::Handle(zone, StubCode::GetAllocationStubForClass(cls));
Class& owner = Class::Handle();
owner ^= stub.owner();
owner.DisableAllocationStub();
{
TransitionNativeToVM transition(thread);
Library& lib_handle =
Library::Handle(Library::RawCast(Api::UnwrapHandle(lib)));
cls = lib_handle.LookupClass(String::Handle(Symbols::New(thread, "A")));
EXPECT(!cls.IsNull());
}
{
TransitionNativeToVM transition(thread);
cls.DisableAllocationStub();
}
result = Dart_Invoke(lib, NewString("main"), 0, NULL);
EXPECT_VALID(result);
owner.DisableAllocationStub();
{
TransitionNativeToVM transition(thread);
cls.DisableAllocationStub();
}
result = Dart_Invoke(lib, NewString("main"), 0, NULL);
EXPECT_VALID(result);
owner.DisableAllocationStub();
{
TransitionNativeToVM transition(thread);
cls.DisableAllocationStub();
}
result = Dart_Invoke(lib, NewString("main"), 0, NULL);
EXPECT_VALID(result);
}
@ -178,14 +188,11 @@ TEST_CASE(EvalExpression) {
RawLibrary* raw_library = Library::RawCast(Api::UnwrapHandle(lib));
Library& lib_handle = Library::ZoneHandle(raw_library);
Dart_KernelCompilationResult compilation_result;
{
TransitionVMToNative transition(thread);
compilation_result = KernelIsolate::CompileExpressionToKernel(
expr_text.ToCString(), Array::empty_array(), Array::empty_array(),
String::Handle(lib_handle.url()).ToCString(), "A",
/* is_static= */ false);
}
Dart_KernelCompilationResult compilation_result =
KernelIsolate::CompileExpressionToKernel(
expr_text.ToCString(), Array::empty_array(), Array::empty_array(),
String::Handle(lib_handle.url()).ToCString(), "A",
/* is_static= */ false);
EXPECT_EQ(Dart_KernelCompilationStatus_Ok, compilation_result.status);
const uint8_t* kernel_bytes = compilation_result.kernel;

View file

@ -796,11 +796,12 @@ const char* Dart::FeaturesString(Isolate* isolate,
void Dart::RunShutdownCallback() {
Thread* thread = Thread::Current();
ASSERT(thread->execution_state() == Thread::kThreadInNative);
ASSERT(thread->execution_state() == Thread::kThreadInVM);
Isolate* isolate = thread->isolate();
void* callback_data = isolate->init_callback_data();
Dart_IsolateShutdownCallback callback = Isolate::ShutdownCallback();
if (callback != NULL) {
TransitionVMToNative transition(thread);
(callback)(callback_data);
}
}

View file

@ -347,6 +347,7 @@ Dart_Handle Api::NewHandle(Thread* thread, RawObject* raw) {
if (raw == Bool::False().raw()) {
return False();
}
ASSERT(thread->execution_state() == Thread::kThreadInVM);
return InitNewHandle(thread, raw);
}
@ -417,11 +418,11 @@ Dart_Isolate Api::CastIsolate(Isolate* isolate) {
Dart_Handle Api::NewError(const char* format, ...) {
Thread* T = Thread::Current();
CHECK_API_SCOPE(T);
HANDLESCOPE(T);
CHECK_CALLBACK_STATE(T);
// Ensure we transition safepoint state to VM if we are not already in
// that state.
TransitionToVM transition(T);
HANDLESCOPE(T);
va_list args;
va_start(args, format);
@ -868,9 +869,10 @@ Dart_HandleFromPersistent(Dart_PersistentHandle object) {
Thread* thread = Thread::Current();
Isolate* isolate = thread->isolate();
CHECK_ISOLATE(isolate);
NoSafepointScope no_safepoint_scope;
ApiState* state = isolate->api_state();
ASSERT(state != NULL);
TransitionNativeToVM transition(thread);
NoSafepointScope no_safepoint_scope;
PersistentHandle* ref = PersistentHandle::Cast(object);
return Api::NewHandle(thread, ref->raw());
}
@ -880,9 +882,10 @@ Dart_HandleFromWeakPersistent(Dart_WeakPersistentHandle object) {
Thread* thread = Thread::Current();
Isolate* isolate = thread->isolate();
CHECK_ISOLATE(isolate);
NoSafepointScope no_safepoint_scope;
ApiState* state = isolate->api_state();
ASSERT(state != NULL);
TransitionNativeToVM transition(thread);
NoSafepointScope no_safepoint_scope;
FinalizablePersistentHandle* weak_ref =
FinalizablePersistentHandle::Cast(object);
return Api::NewHandle(thread, weak_ref->raw());
@ -1125,7 +1128,7 @@ static Dart_Isolate CreateIsolate(const char* script_uri,
// We enter an API scope here as InitializeIsolate could compile some
// bootstrap library files which call out to a tag handler that may create
// Api Handles when an error is encountered.
Dart_EnterScope();
T->EnterApiScope();
const Error& error_obj = Error::Handle(
Z,
Dart::InitializeIsolate(snapshot_data, snapshot_instructions,
@ -1138,7 +1141,7 @@ static Dart_Isolate CreateIsolate(const char* script_uri,
}
#endif // defined(DART_NO_SNAPSHOT) && !defined(PRODUCT).
// We exit the API scope entered above.
Dart_ExitScope();
T->ExitApiScope();
// A Thread structure has been associated to the thread, we do the
// safepoint transition explicitly here instead of using the
// TransitionXXX scope objects as the reverse transition happens
@ -1154,7 +1157,7 @@ static Dart_Isolate CreateIsolate(const char* script_uri,
*error = strdup(error_obj.ToErrorCString());
}
// We exit the API scope entered above.
Dart_ExitScope();
T->ExitApiScope();
}
Dart::ShutdownIsolate();
return reinterpret_cast<Dart_Isolate>(NULL);
@ -1197,6 +1200,15 @@ DART_EXPORT void Dart_ShutdownIsolate() {
Thread* T = Thread::Current();
Isolate* I = T->isolate();
CHECK_ISOLATE(I);
// The Thread structure is disassociated from the isolate, we do the
// safepoint transition explicitly here instead of using the TransitionXXX
// scope objects as the original transition happened outside this scope in
// Dart_EnterIsolate/Dart_CreateIsolate.
ASSERT(T->execution_state() == Thread::kThreadInNative);
T->ExitSafepoint();
T->set_execution_state(Thread::kThreadInVM);
I->WaitForOutstandingSpawns();
// Release any remaining API scopes.
@ -1212,12 +1224,6 @@ DART_EXPORT void Dart_ShutdownIsolate() {
StackZone zone(T);
HandleScope handle_scope(T);
Dart::RunShutdownCallback();
// The Thread structure is disassociated from the isolate, we do the
// safepoint transition explicitly here instead of using the TransitionXXX
// scope objects as the original transition happened outside this scope in
// Dart_EnterIsolate/Dart_CreateIsolate.
T->ExitSafepoint();
T->set_execution_state(Thread::kThreadInVM);
}
Dart::ShutdownIsolate();
}
@ -1419,6 +1425,7 @@ DART_EXPORT Dart_Handle Dart_GetStickyError() {
CHECK_ISOLATE(I);
NoSafepointScope no_safepoint_scope;
if (I->sticky_error() != Error::null()) {
TransitionNativeToVM transition(T);
Dart_Handle error = Api::NewHandle(T, I->sticky_error());
return error;
}
@ -1591,7 +1598,9 @@ DART_EXPORT Dart_Handle Dart_RunLoop() {
}
::Dart_EnterIsolate(Api::CastIsolate(I));
if (I->sticky_error() != Object::null()) {
Dart_Handle error = Api::NewHandle(Thread::Current(), I->sticky_error());
Thread* T = Thread::Current();
TransitionNativeToVM transition(T);
Dart_Handle error = Api::NewHandle(T, I->sticky_error());
I->clear_sticky_error();
return error;
}
@ -1763,34 +1772,15 @@ DART_EXPORT void Dart_EnterScope() {
Thread* thread = Thread::Current();
Isolate* isolate = thread->isolate();
CHECK_ISOLATE(isolate);
NoSafepointScope no_safepoint_scope;
ApiLocalScope* new_scope = thread->api_reusable_scope();
if (new_scope == NULL) {
new_scope = new ApiLocalScope(thread->api_top_scope(),
thread->top_exit_frame_info());
ASSERT(new_scope != NULL);
} else {
new_scope->Reinit(thread, thread->api_top_scope(),
thread->top_exit_frame_info());
thread->set_api_reusable_scope(NULL);
}
thread->set_api_top_scope(new_scope); // New scope is now the top scope.
TransitionNativeToVM transition(thread);
thread->EnterApiScope();
}
DART_EXPORT void Dart_ExitScope() {
Thread* T = Thread::Current();
CHECK_API_SCOPE(T);
NoSafepointScope no_safepoint_scope;
ApiLocalScope* scope = T->api_top_scope();
ApiLocalScope* reusable_scope = T->api_reusable_scope();
T->set_api_top_scope(scope->previous()); // Reset top scope to previous.
if (reusable_scope == NULL) {
scope->Reset(T); // Reset the old scope which we just exited.
T->set_api_reusable_scope(scope);
} else {
ASSERT(reusable_scope != scope);
delete scope;
}
Thread* thread = Thread::Current();
CHECK_API_SCOPE(thread);
TransitionNativeToVM transition(thread);
thread->ExitApiScope();
}
DART_EXPORT uint8_t* Dart_ScopeAllocate(intptr_t size) {
@ -2146,11 +2136,6 @@ DART_EXPORT Dart_Handle Dart_NewInteger(int64_t value) {
Isolate* isolate = thread->isolate();
CHECK_ISOLATE(isolate);
API_TIMELINE_DURATION(thread);
if (Smi::IsValid(value)) {
NOHANDLESCOPE(thread);
return Api::NewHandle(thread, Smi::New(static_cast<intptr_t>(value)));
}
// Slow path for Mints.
DARTSCOPE(thread);
CHECK_CALLBACK_STATE(thread);
return Api::NewHandle(thread, Integer::New(value));
@ -3691,6 +3676,7 @@ DART_EXPORT Dart_Handle Dart_GetDataFromByteBuffer(Dart_Handle object) {
Zone* zone = thread->zone();
Isolate* isolate = thread->isolate();
CHECK_ISOLATE(isolate);
TransitionNativeToVM transition(thread);
intptr_t class_id = Api::ClassId(object);
if (class_id != kByteBufferCid) {
RETURN_TYPE_ERROR(zone, object, 'ByteBuffer');
@ -4503,6 +4489,7 @@ DART_EXPORT Dart_Handle Dart_GetNativeArguments(
const Dart_NativeArgument_Descriptor* argument_descriptors,
Dart_NativeArgument_Value* arg_values) {
NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
TransitionNativeToVM transition(arguments->thread());
ASSERT(arguments->thread()->isolate() == Isolate::Current());
if (arg_values == NULL) {
RETURN_NULL_ERROR(arg_values);
@ -4636,6 +4623,7 @@ DART_EXPORT Dart_Handle Dart_GetNativeArgument(Dart_NativeArguments args,
"%s: argument 'index' out of range. Expected 0..%d but saw %d.",
CURRENT_FUNC, arguments->NativeArgCount() - 1, index);
}
TransitionNativeToVM transition(arguments->thread());
return Api::NewHandle(arguments->thread(), arguments->NativeArgAt(index));
}
@ -4682,6 +4670,7 @@ DART_EXPORT Dart_Handle Dart_GetNativeStringArgument(Dart_NativeArguments args,
int arg_index,
void** peer) {
NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
TransitionNativeToVM transition(arguments->thread());
Dart_Handle result = Api::Null();
if (!GetNativeStringArgument(arguments, arg_index, &result, peer)) {
return Api::NewError(
@ -4752,6 +4741,7 @@ DART_EXPORT void Dart_SetReturnValue(Dart_NativeArguments args,
!Api::IsError(retval)) {
// Print the current stack trace to make the problematic caller
// easier to find.
TransitionNativeToVM transition(arguments->thread());
const StackTrace& stacktrace = GetCurrentStackTrace(0);
OS::PrintErr("=== Current Trace:\n%s===\n", stacktrace.ToCString());
@ -4831,25 +4821,28 @@ RawString* Api::GetEnvironmentValue(Thread* thread, const String& name) {
RawString* Api::CallEnvironmentCallback(Thread* thread, const String& name) {
Isolate* isolate = thread->isolate();
Dart_EnvironmentCallback callback = isolate->environment_callback();
String& result = String::Handle(thread->zone());
if (callback != NULL) {
TransitionVMToNative transition(thread);
Scope api_scope(thread);
Dart_Handle response = callback(Api::NewHandle(thread, name.raw()));
if (::Dart_IsString(response)) {
result ^= Api::UnwrapHandle(response);
} else if (::Dart_IsError(response)) {
const Object& error =
Object::Handle(thread->zone(), Api::UnwrapHandle(response));
Dart_Handle api_name = Api::NewHandle(thread, name.raw());
Dart_Handle api_response;
{
TransitionVMToNative transition(thread);
api_response = callback(api_name);
}
const Object& response =
Object::Handle(thread->zone(), Api::UnwrapHandle(api_response));
if (response.IsString()) {
return String::Cast(response).raw();
} else if (response.IsError()) {
Exceptions::ThrowArgumentError(
String::Handle(String::New(Error::Cast(error).ToErrorCString())));
} else if (!::Dart_IsNull(response)) {
String::Handle(String::New(Error::Cast(response).ToErrorCString())));
} else if (!response.IsNull()) {
// At this point everything except null are invalid environment values.
Exceptions::ThrowArgumentError(
String::Handle(String::New("Illegal environment value")));
}
}
return result.raw();
return String::null();
}
DART_EXPORT Dart_Handle
@ -5014,6 +5007,7 @@ DART_EXPORT Dart_Handle Dart_RootLibrary() {
Thread* thread = Thread::Current();
Isolate* isolate = thread->isolate();
CHECK_ISOLATE(isolate);
TransitionNativeToVM transition(thread);
return Api::NewHandle(thread, isolate->object_store()->root_library());
}

View file

@ -134,9 +134,9 @@ class Api : AllStatic {
class Scope : public StackResource {
public:
explicit Scope(Thread* thread) : StackResource(thread) {
Dart_EnterScope();
thread->EnterApiScope();
}
~Scope() { Dart_ExitScope(); }
~Scope() { thread()->ExitApiScope(); }
private:
DISALLOW_COPY_AND_ASSIGN(Scope);

View file

@ -671,7 +671,11 @@ TEST_CASE(DartAPI_PropagateError) {
}
TEST_CASE(DartAPI_Error) {
Dart_Handle error = Api::NewError("An %s", "error");
Dart_Handle error;
{
TransitionNativeToVM transition(thread);
error = Api::NewError("An %s", "error");
}
EXPECT(Dart_IsError(error));
EXPECT_STREQ("An error", Dart_GetError(error));
}
@ -728,7 +732,6 @@ TEST_CASE(DartAPI_IdentityEquals) {
// Non-instance objects.
{
CHECK_API_SCOPE(thread);
HANDLESCOPE(thread);
Dart_Handle lib1 = Dart_LookupLibrary(dart_core);
Dart_Handle lib2 = Dart_LookupLibrary(dart_mirrors);
@ -780,15 +783,21 @@ TEST_CASE(DartAPI_InstanceGetType) {
Dart_Handle type = Dart_InstanceGetType(Dart_Null());
EXPECT_VALID(type);
EXPECT(Dart_IsType(type));
const Type& null_type_obj = Api::UnwrapTypeHandle(zone, type);
EXPECT(null_type_obj.raw() == Type::NullType());
{
TransitionNativeToVM transition(thread);
const Type& null_type_obj = Api::UnwrapTypeHandle(zone, type);
EXPECT(null_type_obj.raw() == Type::NullType());
}
Dart_Handle instance = Dart_True();
type = Dart_InstanceGetType(instance);
EXPECT_VALID(type);
EXPECT(Dart_IsType(type));
const Type& bool_type_obj = Api::UnwrapTypeHandle(zone, type);
EXPECT(bool_type_obj.raw() == Type::BoolType());
{
TransitionNativeToVM transition(thread);
const Type& bool_type_obj = Api::UnwrapTypeHandle(zone, type);
EXPECT(bool_type_obj.raw() == Type::BoolType());
}
// Errors propagate.
Dart_Handle error = Dart_NewApiError("MyError");
@ -1470,6 +1479,7 @@ TEST_CASE(DartAPI_ExternalStringPretenure) {
EXPECT_VALID(small16);
{
CHECK_API_SCOPE(thread);
TransitionNativeToVM transition(thread);
HANDLESCOPE(thread);
String& handle = String::Handle();
handle ^= Api::UnwrapHandle(big8);
@ -1500,6 +1510,7 @@ TEST_CASE(DartAPI_ExternalTypedDataPretenure) {
EXPECT_VALID(small);
{
CHECK_API_SCOPE(thread);
TransitionNativeToVM transition(thread);
HANDLESCOPE(thread);
ExternalTypedData& handle = ExternalTypedData::Handle();
handle ^= Api::UnwrapHandle(big);
@ -2703,12 +2714,10 @@ VM_UNIT_TEST_CASE(DartAPI_EnterExitScope) {
Dart_EnterScope();
{
EXPECT(thread->api_top_scope() != NULL);
TransitionNativeToVM transition(thread);
HANDLESCOPE(thread);
String& str1 = String::Handle();
{
TransitionNativeToVM transition(thread);
str1 = String::New("Test String");
}
str1 = String::New("Test String");
Dart_Handle ref = Api::NewHandle(thread, str1.raw());
String& str2 = String::Handle();
str2 ^= Api::UnwrapHandle(ref);
@ -2733,7 +2742,6 @@ VM_UNIT_TEST_CASE(DartAPI_PersistentHandles) {
Dart_EnterScope();
{
CHECK_API_SCOPE(thread);
HANDLESCOPE(thread);
Dart_Handle ref1 = Dart_NewStringFromCString(kTestString1);
for (int i = 0; i < 1000; i++) {
handles[i] = Dart_NewPersistentHandle(ref1);
@ -2757,6 +2765,7 @@ VM_UNIT_TEST_CASE(DartAPI_PersistentHandles) {
}
Dart_ExitScope();
{
TransitionNativeToVM transition(thread);
StackZone zone(thread);
HANDLESCOPE(thread);
for (int i = 0; i < 500; i++) {
@ -2796,7 +2805,6 @@ VM_UNIT_TEST_CASE(DartAPI_NewPersistentHandle_FromPersistentHandle) {
EXPECT(state != NULL);
Thread* thread = Thread::Current();
CHECK_API_SCOPE(thread);
HANDLESCOPE(thread);
// Start with a known persistent handle.
Dart_PersistentHandle obj1 = Dart_NewPersistentHandle(Dart_True());
@ -2824,25 +2832,33 @@ VM_UNIT_TEST_CASE(DartAPI_AssignToPersistentHandle) {
Thread* T = Thread::Current();
CHECK_API_SCOPE(T);
HANDLESCOPE(T);
Isolate* isolate = T->isolate();
EXPECT(isolate != NULL);
ApiState* state = isolate->api_state();
EXPECT(state != NULL);
String& str = String::Handle();
// Start with a known persistent handle.
Dart_Handle ref1 = Dart_NewStringFromCString(kTestString1);
Dart_PersistentHandle obj = Dart_NewPersistentHandle(ref1);
EXPECT(state->IsValidPersistentHandle(obj));
str ^= PersistentHandle::Cast(obj)->raw();
EXPECT(str.Equals(kTestString1));
{
TransitionNativeToVM transition(T);
HANDLESCOPE(T);
String& str = String::Handle();
str ^= PersistentHandle::Cast(obj)->raw();
EXPECT(str.Equals(kTestString1));
}
// Now create another local handle and assign it to the persistent handle.
Dart_Handle ref2 = Dart_NewStringFromCString(kTestString2);
Dart_SetPersistentHandle(obj, ref2);
str ^= PersistentHandle::Cast(obj)->raw();
EXPECT(str.Equals(kTestString2));
{
TransitionNativeToVM transition(T);
HANDLESCOPE(T);
String& str = String::Handle();
str ^= PersistentHandle::Cast(obj)->raw();
EXPECT(str.Equals(kTestString2));
}
// Now assign Null to the persistent handle and check.
Dart_SetPersistentHandle(obj, Dart_Null());
@ -3168,6 +3184,7 @@ TEST_CASE(DartAPI_WeakPersistentHandleExternalAllocationSizeNewspaceGC) {
// external size charged to old space.
{
CHECK_API_SCOPE(thread);
TransitionNativeToVM transition(thread);
HANDLESCOPE(thread);
String& handle = String::Handle(thread->zone());
handle ^= Api::UnwrapHandle(obj);
@ -3273,7 +3290,6 @@ TEST_CASE(DartAPI_ImplicitReferencesOldSpace) {
Dart_EnterScope();
{
CHECK_API_SCOPE(thread);
HANDLESCOPE(thread);
Dart_Handle local = AllocateOldString("strongly reachable");
strong = Dart_NewPersistentHandle(local);
@ -3337,7 +3353,6 @@ TEST_CASE(DartAPI_ImplicitReferencesNewSpace) {
Dart_EnterScope();
{
CHECK_API_SCOPE(thread);
HANDLESCOPE(thread);
Dart_Handle local = AllocateOldString("strongly reachable");
strong = Dart_NewPersistentHandle(local);
@ -3405,43 +3420,54 @@ VM_UNIT_TEST_CASE(DartAPI_LocalHandles) {
Dart_Handle handles[300];
{
StackZone zone(thread);
TransitionNativeToVM transition1(thread);
HANDLESCOPE(thread);
Smi& val = Smi::Handle();
TransitionVMToNative transition2(thread);
// Start a new scope and allocate some local handles.
Dart_EnterScope();
for (int i = 0; i < 100; i++) {
handles[i] = Api::NewHandle(thread, Smi::New(i));
}
EXPECT_EQ(100, thread->CountLocalHandles());
for (int i = 0; i < 100; i++) {
val ^= Api::UnwrapHandle(handles[i]);
EXPECT_EQ(i, val.Value());
{
TransitionNativeToVM transition3(thread);
for (int i = 0; i < 100; i++) {
handles[i] = Api::NewHandle(thread, Smi::New(i));
}
EXPECT_EQ(100, thread->CountLocalHandles());
for (int i = 0; i < 100; i++) {
val ^= Api::UnwrapHandle(handles[i]);
EXPECT_EQ(i, val.Value());
}
}
// Start another scope and allocate some more local handles.
{
Dart_EnterScope();
for (int i = 100; i < 200; i++) {
handles[i] = Api::NewHandle(thread, Smi::New(i));
}
EXPECT_EQ(200, thread->CountLocalHandles());
for (int i = 100; i < 200; i++) {
val ^= Api::UnwrapHandle(handles[i]);
EXPECT_EQ(i, val.Value());
{
TransitionNativeToVM transition3(thread);
for (int i = 100; i < 200; i++) {
handles[i] = Api::NewHandle(thread, Smi::New(i));
}
EXPECT_EQ(200, thread->CountLocalHandles());
for (int i = 100; i < 200; i++) {
val ^= Api::UnwrapHandle(handles[i]);
EXPECT_EQ(i, val.Value());
}
}
// Start another scope and allocate some more local handles.
{
Dart_EnterScope();
for (int i = 200; i < 300; i++) {
handles[i] = Api::NewHandle(thread, Smi::New(i));
{
TransitionNativeToVM transition3(thread);
for (int i = 200; i < 300; i++) {
handles[i] = Api::NewHandle(thread, Smi::New(i));
}
EXPECT_EQ(300, thread->CountLocalHandles());
for (int i = 200; i < 300; i++) {
val ^= Api::UnwrapHandle(handles[i]);
EXPECT_EQ(i, val.Value());
}
EXPECT_EQ(300, thread->CountLocalHandles());
}
EXPECT_EQ(300, thread->CountLocalHandles());
for (int i = 200; i < 300; i++) {
val ^= Api::UnwrapHandle(handles[i]);
EXPECT_EQ(i, val.Value());
}
EXPECT_EQ(300, thread->CountLocalHandles());
VERIFY_ON_TRANSITION;
Dart_ExitScope();
}
@ -4231,6 +4257,7 @@ TEST_CASE(DartAPI_InjectNativeFields3) {
result = Dart_Invoke(lib, NewString("testMain"), 0, NULL);
EXPECT_VALID(result);
CHECK_API_SCOPE(thread);
TransitionNativeToVM transition(thread);
HANDLESCOPE(thread);
Instance& obj = Instance::Handle();
obj ^= Api::UnwrapHandle(result);
@ -4312,6 +4339,7 @@ static Dart_NativeFunction TestNativeFieldsAccess_lookup(Dart_Handle name,
bool* auto_scope) {
ASSERT(auto_scope != NULL);
*auto_scope = true;
TransitionNativeToVM transition(Thread::Current());
const Object& obj = Object::Handle(Api::UnwrapHandle(name));
if (!obj.IsString()) {
return NULL;
@ -4504,7 +4532,6 @@ TEST_CASE(DartAPI_NegativeNativeFieldAccess) {
"}\n";
Dart_Handle result;
CHECK_API_SCOPE(thread);
HANDLESCOPE(thread);
// Create a test library and Load up a test script in it.
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
@ -5351,7 +5378,6 @@ TEST_CASE(DartAPI_InvokeClosure) {
"}\n";
Dart_Handle result;
CHECK_API_SCOPE(thread);
HANDLESCOPE(thread);
// Create a test library and Load up a test script in it.
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
@ -5556,6 +5582,7 @@ static void NativeArgumentAccess(Dart_NativeArguments args) {
static Dart_NativeFunction native_args_lookup(Dart_Handle name,
int argument_count,
bool* auto_scope_setup) {
TransitionNativeToVM transition(Thread::Current());
const Object& obj = Object::Handle(Api::UnwrapHandle(name));
if (!obj.IsString()) {
return NULL;
@ -6151,10 +6178,10 @@ TEST_CASE(DartAPI_Multiroot_Valid) {
/* multiroot_filepaths= */ "/bar,/baz",
/* multiroot_scheme= */ "foo");
EXPECT_VALID(lib);
Library& lib_obj = Library::Handle();
lib_obj ^= Api::UnwrapHandle(lib);
{
TransitionNativeToVM transition(thread);
Library& lib_obj = Library::Handle();
lib_obj ^= Api::UnwrapHandle(lib);
EXPECT_STREQ("foo:///main.dart", String::Handle(lib_obj.url()).ToCString());
const Array& lib_scripts = Array::Handle(lib_obj.LoadedScripts());
Script& script = Script::Handle();
@ -6719,6 +6746,7 @@ static Dart_NativeFunction MyNativeClosureResolver(Dart_Handle name,
bool* auto_setup_scope) {
ASSERT(auto_setup_scope != NULL);
*auto_setup_scope = false;
TransitionNativeToVM transition(Thread::Current());
const Object& obj = Object::Handle(Api::UnwrapHandle(name));
if (!obj.IsString()) {
return NULL;
@ -6858,6 +6886,7 @@ static Dart_NativeFunction MyStaticNativeClosureResolver(
bool* auto_setup_scope) {
ASSERT(auto_setup_scope != NULL);
*auto_setup_scope = false;
TransitionNativeToVM transition(Thread::Current());
const Object& obj = Object::Handle(Api::UnwrapHandle(name));
if (!obj.IsString()) {
return NULL;
@ -7064,7 +7093,6 @@ TEST_CASE(DartAPI_CollectOneNewSpacePeer) {
Dart_EnterScope();
{
CHECK_API_SCOPE(thread);
HANDLESCOPE(thread);
Dart_Handle str = NewString("a string");
EXPECT_VALID(str);
EXPECT(Dart_IsString(str));
@ -7142,7 +7170,6 @@ TEST_CASE(DartAPI_CollectTwoNewSpacePeers) {
Dart_EnterScope();
{
CHECK_API_SCOPE(thread);
HANDLESCOPE(thread);
Dart_Handle s1 = NewString("s1");
EXPECT_VALID(s1);
EXPECT(Dart_IsString(s1));
@ -7234,6 +7261,7 @@ TEST_CASE(DartAPI_OnePromotedPeer) {
}
{
CHECK_API_SCOPE(thread);
TransitionNativeToVM transition(thread);
HANDLESCOPE(thread);
String& handle = String::Handle();
handle ^= Api::UnwrapHandle(str);
@ -7290,7 +7318,6 @@ TEST_CASE(DartAPI_CollectOneOldSpacePeer) {
{
Thread* T = Thread::Current();
CHECK_API_SCOPE(T);
HANDLESCOPE(T);
Dart_Handle str = AllocateOldString("str");
EXPECT_VALID(str);
EXPECT(Dart_IsString(str));
@ -7372,7 +7399,6 @@ TEST_CASE(DartAPI_CollectTwoOldSpacePeers) {
{
Thread* T = Thread::Current();
CHECK_API_SCOPE(T);
HANDLESCOPE(T);
Dart_Handle s1 = AllocateOldString("s1");
EXPECT_VALID(s1);
EXPECT(Dart_IsString(s1));

View file

@ -219,16 +219,20 @@ Dart_ActivationFrameInfo(Dart_ActivationFrame activation_frame,
DART_EXPORT Dart_Handle Dart_SetBreakpoint(Dart_Handle script_url_in,
intptr_t line_number) {
DARTSCOPE(Thread::Current());
Isolate* I = T->isolate();
CHECK_DEBUGGER(I);
UNWRAP_AND_CHECK_PARAM(String, script_url, script_url_in);
Breakpoint* bpt;
{
DARTSCOPE(Thread::Current());
Isolate* I = T->isolate();
CHECK_DEBUGGER(I);
UNWRAP_AND_CHECK_PARAM(String, script_url, script_url_in);
Debugger* debugger = I->debugger();
Breakpoint* bpt = debugger->SetBreakpointAtLine(script_url, line_number);
if (bpt == NULL) {
return Api::NewError("%s: could not set breakpoint at line %" Pd " in '%s'",
CURRENT_FUNC, line_number, script_url.ToCString());
Debugger* debugger = I->debugger();
bpt = debugger->SetBreakpointAtLine(script_url, line_number);
if (bpt == NULL) {
return Api::NewError("%s: could not set breakpoint at line %" Pd
" in '%s'",
CURRENT_FUNC, line_number, script_url.ToCString());
}
}
return Dart_NewInteger(bpt->id());
}
@ -250,17 +254,14 @@ DART_EXPORT Dart_Handle Dart_EvaluateStaticExpr(Dart_Handle lib_handle,
if (!KernelIsolate::IsRunning()) {
UNREACHABLE();
} else {
Dart_KernelCompilationResult compilation_result;
{
TransitionVMToNative transition(T);
compilation_result = KernelIsolate::CompileExpressionToKernel(
expr.ToCString(),
/* definitions= */ Array::empty_array(),
/* type_defintions= */ Array::empty_array(),
String::Handle(lib.url()).ToCString(),
/* klass= */ nullptr,
/* is_static= */ false);
}
Dart_KernelCompilationResult compilation_result =
KernelIsolate::CompileExpressionToKernel(
expr.ToCString(),
/* definitions= */ Array::empty_array(),
/* type_defintions= */ Array::empty_array(),
String::Handle(lib.url()).ToCString(),
/* klass= */ nullptr,
/* is_static= */ false);
if (compilation_result.status != Dart_KernelCompilationStatus_Ok) {
return Api::NewError("Failed to compile expression.");
}

View file

@ -13,6 +13,7 @@ namespace dart {
#define REGISTER_FUNCTION(name, count) {"" #name, FUNCTION_NAME(name), count},
void FUNCTION_NAME(Unhandled_equals)(Dart_NativeArguments args) {
TransitionNativeToVM transition(Thread::Current());
NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
const Instance& expected = Instance::CheckedHandle(arguments->NativeArgAt(0));
const Instance& actual = Instance::CheckedHandle(arguments->NativeArgAt(1));
@ -64,6 +65,7 @@ static Dart_NativeFunction native_lookup(Dart_Handle name,
bool* auto_setup_scope) {
ASSERT(auto_setup_scope != NULL);
*auto_setup_scope = true;
TransitionNativeToVM transition(Thread::Current());
const Object& obj = Object::Handle(Api::UnwrapHandle(name));
ASSERT(obj.IsString());
const char* function_name = obj.ToCString();

View file

@ -92,7 +92,7 @@ TEST_CASE(GrowableArraySort) {
EXPECT_EQ(4, g.Last());
}
TEST_CASE(GrowableHandlePtr) {
ISOLATE_UNIT_TEST_CASE(GrowableHandlePtr) {
Zone* zone = Thread::Current()->zone();
GrowableHandlePtrArray<const String> test1(zone, 1);
EXPECT_EQ(0, test1.length());

View file

@ -73,7 +73,7 @@ int VMHandles::ZoneHandleCount() {
}
void HandleScope::Initialize() {
ASSERT(thread()->no_handle_scope_depth() == 0);
ASSERT(thread()->MayAllocateHandles());
VMHandles* handles = thread()->zone()->handles();
ASSERT(handles != NULL);
saved_handle_block_ = handles->scoped_blocks_;
@ -102,14 +102,4 @@ HandleScope::~HandleScope() {
#endif
}
#if defined(DEBUG)
NoHandleScope::NoHandleScope(Thread* thread) : StackResource(thread) {
thread->IncrementNoHandleScopeDepth();
}
NoHandleScope::~NoHandleScope() {
thread()->DecrementNoHandleScopeDepth();
}
#endif // defined(DEBUG)
} // namespace dart

View file

@ -45,15 +45,6 @@ namespace dart {
// Handles::AllocateZoneHandle() function for creating zone handles.
// The ZoneHandle function of the object type is the only way to create
// zone handles in the dart VM.
//
// There are some critical regions of the Dart VM were we may need to manipulate
// raw dart objects directly. We use NOHANDLESCOPE to assert that we do not
// add code that will allocate new handles during this critical area.
// {
// NOHANDLESCOPE(thread);
// ....
// ....
// }
// Forward declarations.
class ObjectPointerVisitor;
@ -307,43 +298,6 @@ class HandleScope : public StackResource {
#define HANDLESCOPE(thread) \
dart::HandleScope vm_internal_handles_scope_(thread);
// The class NoHandleScope is used in critical regions of the virtual machine
// code where raw dart object pointers are directly manipulated.
// This class asserts that we do not add code that will allocate new handles
// during this critical area.
// It is used as follows:
// {
// NOHANDLESCOPE(thread);
// ....
// .....
// critical code that manipulates dart objects directly.
// ....
// }
#if defined(DEBUG)
class NoHandleScope : public StackResource {
public:
explicit NoHandleScope(Thread* thread);
~NoHandleScope();
private:
DISALLOW_COPY_AND_ASSIGN(NoHandleScope);
};
#else // defined(DEBUG)
class NoHandleScope : public ValueObject {
public:
explicit NoHandleScope(Thread* thread) {}
NoHandleScope() {}
~NoHandleScope() {}
private:
DISALLOW_COPY_AND_ASSIGN(NoHandleScope);
};
#endif // defined(DEBUG)
// Macro to start a no handles scope in the code.
#define NOHANDLESCOPE(thread) \
dart::NoHandleScope no_vm_internal_handles_scope_(thread);
} // namespace dart
#endif // RUNTIME_VM_HANDLES_H_

View file

@ -82,7 +82,7 @@ uword Handles<kHandleSizeInWords, kHandlesPerChunk, kOffsetOfRawPtr>::
#if defined(DEBUG)
Thread* thread = Thread::Current();
ASSERT(thread->top_handle_scope() != NULL);
ASSERT(thread->no_handle_scope_depth() == 0);
ASSERT(thread->MayAllocateHandles());
#endif // DEBUG
Handles* handles = zone->handles();
ASSERT(handles != NULL);
@ -97,7 +97,7 @@ uword Handles<kHandleSizeInWords, kHandlesPerChunk, kOffsetOfRawPtr>::
#if defined(DEBUG)
Thread* thread = Thread::Current();
ASSERT(zone->ContainsNestedZone(thread->zone()));
ASSERT(thread->no_handle_scope_depth() == 0);
ASSERT(thread->MayAllocateHandles());
#endif // DEBUG
Handles* handles = zone->handles();
ASSERT(handles != NULL);

View file

@ -14,7 +14,7 @@
namespace dart {
// Unit test for Zone handle allocation.
TEST_CASE(AllocateZoneHandle) {
ISOLATE_UNIT_TEST_CASE(AllocateZoneHandle) {
#if defined(DEBUG)
FLAG_trace_handles = true;
#endif
@ -38,7 +38,7 @@ TEST_CASE(AllocateZoneHandle) {
}
// Unit test for Scope handle allocation.
TEST_CASE(AllocateScopeHandle) {
ISOLATE_UNIT_TEST_CASE(AllocateScopeHandle) {
#if defined(DEBUG)
FLAG_trace_handles = true;
#endif
@ -86,11 +86,11 @@ TEST_CASE(CheckHandleValidity) {
#if defined(DEBUG)
FLAG_trace_handles = true;
#endif
Thread* current = Thread::Current();
Dart_Handle handle = NULL;
// Check validity using zone handles.
{
StackZone sz(current);
TransitionNativeToVM transition(thread);
StackZone sz(thread);
handle = reinterpret_cast<Dart_Handle>(&Smi::ZoneHandle(Smi::New(1)));
EXPECT_VALID(handle);
}
@ -98,18 +98,26 @@ TEST_CASE(CheckHandleValidity) {
// Check validity using scoped handles.
{
HANDLESCOPE(current);
Dart_EnterScope();
handle = reinterpret_cast<Dart_Handle>(&Smi::Handle(Smi::New(1)));
EXPECT_VALID(handle);
{
TransitionNativeToVM transition(thread);
HANDLESCOPE(thread);
handle = reinterpret_cast<Dart_Handle>(&Smi::Handle(Smi::New(1)));
EXPECT_VALID(handle);
}
Dart_ExitScope();
}
EXPECT(!Api::IsValid(handle));
// Check validity using persistent handle.
Isolate* isolate = Isolate::Current();
Dart_Handle scoped_handle;
{
TransitionNativeToVM transition(thread);
scoped_handle = Api::NewHandle(thread, Smi::New(1));
}
Dart_PersistentHandle persistent_handle =
Dart_NewPersistentHandle(Api::NewHandle(thread, Smi::New(1)));
Dart_NewPersistentHandle(scoped_handle);
EXPECT_VALID(persistent_handle);
Dart_DeletePersistentHandle(persistent_handle);

View file

@ -66,12 +66,15 @@ TEST_CASE(LargeSweep) {
EXPECT_VALID(result);
EXPECT(!Dart_IsNull(result));
EXPECT(Dart_IsList(result));
TransitionNativeToVM transition(thread);
Isolate* isolate = Isolate::Current();
Heap* heap = isolate->heap();
heap->CollectGarbage(Heap::kOld);
{
TransitionNativeToVM transition(thread);
thread->heap()->CollectGarbage(Heap::kOld);
}
Dart_ExitScope();
heap->CollectGarbage(Heap::kOld);
{
TransitionNativeToVM transition(thread);
thread->heap()->CollectGarbage(Heap::kOld);
}
}
#ifndef PRODUCT
@ -118,78 +121,84 @@ TEST_CASE(ClassHeapStats) {
Dart_Handle result = Dart_Invoke(h_lib, NewString("main"), 0, NULL);
EXPECT_VALID(result);
EXPECT(!Dart_IsNull(result));
TransitionNativeToVM transition(thread);
Library& lib = Library::Handle();
lib ^= Api::UnwrapHandle(h_lib);
EXPECT(!lib.IsNull());
const Class& cls = Class::Handle(GetClass(lib, "A"));
ASSERT(!cls.IsNull());
intptr_t cid = cls.id();
ClassHeapStats* class_stats =
ClassHeapStatsTestHelper::GetHeapStatsForCid(class_table, cid);
// Verify preconditions:
EXPECT_EQ(0, class_stats->pre_gc.old_count);
EXPECT_EQ(0, class_stats->post_gc.old_count);
EXPECT_EQ(0, class_stats->recent.old_count);
EXPECT_EQ(0, class_stats->pre_gc.new_count);
EXPECT_EQ(0, class_stats->post_gc.new_count);
// Class allocated twice since GC from new space.
EXPECT_EQ(2, class_stats->recent.new_count);
// Perform GC.
heap->CollectGarbage(Heap::kNew);
// Verify postconditions:
EXPECT_EQ(0, class_stats->pre_gc.old_count);
EXPECT_EQ(0, class_stats->post_gc.old_count);
EXPECT_EQ(0, class_stats->recent.old_count);
// Total allocations before GC.
EXPECT_EQ(2, class_stats->pre_gc.new_count);
// Only one survived.
EXPECT_EQ(1, class_stats->post_gc.new_count);
EXPECT_EQ(0, class_stats->recent.new_count);
// Perform GC. The following is heavily dependent on the behaviour
// of the GC: Retained instance of A will be promoted.
heap->CollectGarbage(Heap::kNew);
// Verify postconditions:
EXPECT_EQ(0, class_stats->pre_gc.old_count);
EXPECT_EQ(0, class_stats->post_gc.old_count);
// One promoted instance.
EXPECT_EQ(1, class_stats->promoted_count);
// Promotion counted as an allocation from old space.
EXPECT_EQ(1, class_stats->recent.old_count);
// There was one instance allocated before GC.
EXPECT_EQ(1, class_stats->pre_gc.new_count);
// There are no instances allocated in new space after GC.
EXPECT_EQ(0, class_stats->post_gc.new_count);
// No new allocations.
EXPECT_EQ(0, class_stats->recent.new_count);
// Perform a GC on new space.
heap->CollectGarbage(Heap::kNew);
// There were no instances allocated before GC.
EXPECT_EQ(0, class_stats->pre_gc.new_count);
// There are no instances allocated in new space after GC.
EXPECT_EQ(0, class_stats->post_gc.new_count);
// No new allocations.
EXPECT_EQ(0, class_stats->recent.new_count);
// Nothing was promoted.
EXPECT_EQ(0, class_stats->promoted_count);
heap->CollectGarbage(Heap::kOld);
// Verify postconditions:
EXPECT_EQ(1, class_stats->pre_gc.old_count);
EXPECT_EQ(1, class_stats->post_gc.old_count);
EXPECT_EQ(0, class_stats->recent.old_count);
ClassHeapStats* class_stats;
{
TransitionNativeToVM transition(thread);
Library& lib = Library::Handle();
lib ^= Api::UnwrapHandle(h_lib);
EXPECT(!lib.IsNull());
const Class& cls = Class::Handle(GetClass(lib, "A"));
ASSERT(!cls.IsNull());
intptr_t cid = cls.id();
class_stats =
ClassHeapStatsTestHelper::GetHeapStatsForCid(class_table, cid);
// Verify preconditions:
EXPECT_EQ(0, class_stats->pre_gc.old_count);
EXPECT_EQ(0, class_stats->post_gc.old_count);
EXPECT_EQ(0, class_stats->recent.old_count);
EXPECT_EQ(0, class_stats->pre_gc.new_count);
EXPECT_EQ(0, class_stats->post_gc.new_count);
// Class allocated twice since GC from new space.
EXPECT_EQ(2, class_stats->recent.new_count);
// Perform GC.
heap->CollectGarbage(Heap::kNew);
// Verify postconditions:
EXPECT_EQ(0, class_stats->pre_gc.old_count);
EXPECT_EQ(0, class_stats->post_gc.old_count);
EXPECT_EQ(0, class_stats->recent.old_count);
// Total allocations before GC.
EXPECT_EQ(2, class_stats->pre_gc.new_count);
// Only one survived.
EXPECT_EQ(1, class_stats->post_gc.new_count);
EXPECT_EQ(0, class_stats->recent.new_count);
// Perform GC. The following is heavily dependent on the behaviour
// of the GC: Retained instance of A will be promoted.
heap->CollectGarbage(Heap::kNew);
// Verify postconditions:
EXPECT_EQ(0, class_stats->pre_gc.old_count);
EXPECT_EQ(0, class_stats->post_gc.old_count);
// One promoted instance.
EXPECT_EQ(1, class_stats->promoted_count);
// Promotion counted as an allocation from old space.
EXPECT_EQ(1, class_stats->recent.old_count);
// There was one instance allocated before GC.
EXPECT_EQ(1, class_stats->pre_gc.new_count);
// There are no instances allocated in new space after GC.
EXPECT_EQ(0, class_stats->post_gc.new_count);
// No new allocations.
EXPECT_EQ(0, class_stats->recent.new_count);
// Perform a GC on new space.
heap->CollectGarbage(Heap::kNew);
// There were no instances allocated before GC.
EXPECT_EQ(0, class_stats->pre_gc.new_count);
// There are no instances allocated in new space after GC.
EXPECT_EQ(0, class_stats->post_gc.new_count);
// No new allocations.
EXPECT_EQ(0, class_stats->recent.new_count);
// Nothing was promoted.
EXPECT_EQ(0, class_stats->promoted_count);
heap->CollectGarbage(Heap::kOld);
// Verify postconditions:
EXPECT_EQ(1, class_stats->pre_gc.old_count);
EXPECT_EQ(1, class_stats->post_gc.old_count);
EXPECT_EQ(0, class_stats->recent.old_count);
}
// Exit scope, freeing instance.
Dart_ExitScope();
// Perform GC.
heap->CollectGarbage(Heap::kOld);
// Verify postconditions:
EXPECT_EQ(1, class_stats->pre_gc.old_count);
EXPECT_EQ(0, class_stats->post_gc.old_count);
EXPECT_EQ(0, class_stats->recent.old_count);
// Perform GC.
heap->CollectGarbage(Heap::kOld);
EXPECT_EQ(0, class_stats->pre_gc.old_count);
EXPECT_EQ(0, class_stats->post_gc.old_count);
EXPECT_EQ(0, class_stats->recent.old_count);
{
TransitionNativeToVM transition(thread);
// Perform GC.
heap->CollectGarbage(Heap::kOld);
// Verify postconditions:
EXPECT_EQ(1, class_stats->pre_gc.old_count);
EXPECT_EQ(0, class_stats->post_gc.old_count);
EXPECT_EQ(0, class_stats->recent.old_count);
// Perform GC.
heap->CollectGarbage(Heap::kOld);
EXPECT_EQ(0, class_stats->pre_gc.old_count);
EXPECT_EQ(0, class_stats->post_gc.old_count);
EXPECT_EQ(0, class_stats->recent.old_count);
}
FLAG_concurrent_sweep = saved_concurrent_sweep_mode;
}
@ -214,9 +223,6 @@ TEST_CASE(ArrayHeapStats) {
Dart_Handle result = Dart_Invoke(h_lib, NewString("main"), 0, NULL);
EXPECT_VALID(result);
EXPECT(!Dart_IsNull(result));
Library& lib = Library::Handle();
lib ^= Api::UnwrapHandle(h_lib);
EXPECT(!lib.IsNull());
intptr_t before = class_stats->recent.new_size;
Dart_Handle result2 = Dart_Invoke(h_lib, NewString("main"), 0, NULL);
EXPECT_VALID(result2);

View file

@ -1158,6 +1158,21 @@ Thread* Isolate::mutator_thread() const {
return thread_registry()->mutator_thread();
}
RawObject* Isolate::CallTagHandler(Dart_LibraryTag tag,
const Object& arg1,
const Object& arg2) {
Thread* thread = Thread::Current();
Api::Scope api_scope(thread);
Dart_Handle api_arg1 = Api::NewHandle(thread, arg1.raw());
Dart_Handle api_arg2 = Api::NewHandle(thread, arg2.raw());
Dart_Handle api_result;
{
TransitionVMToNative transition(thread);
api_result = library_tag_handler_(tag, api_arg1, api_arg2);
}
return Api::UnwrapHandle(api_result);
}
void Isolate::SetupImagePage(const uint8_t* image_buffer, bool is_executable) {
Image image(image_buffer);
heap_->SetupImagePage(image.object_start(), image.object_size(),
@ -1657,7 +1672,6 @@ static void ShutdownIsolate(uword parameter) {
#if defined(DEBUG)
isolate->ValidateConstants();
#endif // defined(DEBUG)
TransitionVMToNative transition(thread);
Dart::RunShutdownCallback();
}
// Shut the isolate down.

View file

@ -280,9 +280,10 @@ class Isolate : public BaseIsolate {
environment_callback_ = value;
}
Dart_LibraryTagHandler library_tag_handler() const {
return library_tag_handler_;
}
bool HasTagHandler() const { return library_tag_handler_ != nullptr; }
RawObject* CallTagHandler(Dart_LibraryTag tag,
const Object& arg1,
const Object& arg2);
void set_library_tag_handler(Dart_LibraryTagHandler value) {
library_tag_handler_ = value;
}

View file

@ -161,7 +161,7 @@ TEST_CASE(JSON_JSONStream_ObjectPrintf) {
EXPECT_STREQ("{\"key\":\"2 hello\"}", js.ToCString());
}
TEST_CASE(JSON_JSONStream_DartObject) {
ISOLATE_UNIT_TEST_CASE(JSON_JSONStream_DartObject) {
JSONStream js;
{
JSONArray jsarr(&js);
@ -216,7 +216,9 @@ TEST_CASE(JSON_JSONStream_DartString) {
EXPECT_VALID(lib);
Dart_Handle result;
TransitionNativeToVM transition1(thread);
String& obj = String::Handle();
TransitionVMToNative transition2(thread);
{
result = Dart_GetField(lib, NewString("ascii"));

View file

@ -124,12 +124,14 @@ Program* Program::ReadFromFile(const char* script_uri,
return NULL;
}
kernel::Program* kernel_program = NULL;
const String& uri = String::Handle(String::New(script_uri));
const Object& ret = Object::Handle(thread->isolate()->CallTagHandler(
Dart_kKernelTag, Object::null_object(), uri));
Api::Scope api_scope(thread);
Dart_Handle retval = Api::NewHandle(thread, ret.raw());
{
const String& uri = String::Handle(String::New(script_uri));
TransitionVMToNative transition(thread);
Api::Scope api_scope(thread);
Dart_Handle retval = (thread->isolate()->library_tag_handler())(
Dart_kKernelTag, Api::Null(), Api::NewHandle(thread, uri.raw()));
if (!Dart_IsError(retval)) {
Dart_TypedData_Type data_type;
uint8_t* data;

View file

@ -160,7 +160,6 @@ class RunKernelTask : public ThreadPool::Task {
OS::PrintErr(DART_KERNEL_ISOLATE_NAME ": Error: %s\n",
error.ToErrorCString());
}
TransitionVMToNative transition(T);
Dart::RunShutdownCallback();
}
@ -376,6 +375,7 @@ class KernelCompilationRequest : public ValueObject {
char const* library_uri,
char const* klass,
bool is_static) {
TransitionNativeToVM transition(Thread::Current());
Dart_CObject tag;
tag.type = Dart_CObject_kInt32;
tag.value.as_int32 = KernelIsolate::kCompileExpressionTag;
@ -460,13 +460,18 @@ class KernelCompilationRequest : public ValueObject {
&suppress_warnings};
message.value.as_array.values = message_arr;
message.value.as_array.length = ARRAY_SIZE(message_arr);
// Send the message.
Dart_PostCObject(kernel_port, &message);
// Wait for reply to arrive.
MonitorLocker ml(monitor_);
while (result_.status == Dart_KernelCompilationStatus_Unknown) {
ml.Wait();
{
TransitionVMToNative transition(Thread::Current());
// Send the message.
Dart_PostCObject(kernel_port, &message);
// Wait for reply to arrive.
MonitorLocker ml(monitor_);
while (result_.status == Dart_KernelCompilationStatus_Unknown) {
ml.Wait();
}
}
for (intptr_t i = 0; i < num_definitions; ++i) {
@ -819,6 +824,7 @@ Dart_KernelCompilationResult KernelIsolate::CompileExpressionToKernel(
return result;
}
TransitionVMToNative transition(Thread::Current());
KernelCompilationRequest request;
return request.SendAndWaitForResponse(kernel_port, expression, definitions,
type_definitions, library_url, klass,

View file

@ -572,20 +572,12 @@ void KernelLoader::LoadNativeExtensionLibraries(
if (uri_path.IsNull()) continue;
Dart_LibraryTagHandler handler = I->library_tag_handler();
if (handler == NULL) {
if (!I->HasTagHandler()) {
H.ReportError("no library handler registered.");
}
I->BlockClassFinalization();
{
TransitionVMToNative transition(thread_);
Api::Scope api_scope(thread_);
Dart_Handle retval = handler(Dart_kImportExtensionTag,
Api::NewHandle(thread_, library.raw()),
Api::NewHandle(thread_, uri_path.raw()));
result = Api::UnwrapHandle(retval);
}
result = I->CallTagHandler(Dart_kImportExtensionTag, library, uri_path);
I->UnblockClassFinalization();
if (result.IsError()) {

View file

@ -48,6 +48,7 @@ VM_UNIT_TEST_CASE(Metric_OnDemand) {
TestCase::CreateTestIsolate();
{
Thread* thread = Thread::Current();
TransitionNativeToVM transition(thread);
StackZone zone(thread);
HANDLESCOPE(thread);
MyMetric metric;

View file

@ -44,12 +44,14 @@ NativeFunction NativeEntry::ResolveNative(const Library& library,
Dart_NativeFunction native_function = NULL;
{
Thread* T = Thread::Current();
TransitionVMToNative transition(T);
Dart_EnterScope(); // Enter a new Dart API scope as we invoke API entries.
Dart_NativeEntryResolver resolver = library.native_entry_resolver();
native_function = resolver(Api::NewHandle(T, function_name.raw()),
number_of_arguments, auto_setup_scope);
Dart_ExitScope(); // Exit the Dart API scope.
Api::Scope api_scope(T);
Dart_Handle api_function_name = Api::NewHandle(T, function_name.raw());
{
TransitionVMToNative transition(T);
Dart_NativeEntryResolver resolver = library.native_entry_resolver();
native_function =
resolver(api_function_name, number_of_arguments, auto_setup_scope);
}
}
return reinterpret_cast<NativeFunction>(native_function);
}
@ -180,34 +182,16 @@ void NativeEntry::AutoScopeNativeCallWrapperNoStackCheck(
Isolate* isolate = thread->isolate();
ApiState* state = isolate->api_state();
ASSERT(state != NULL);
ApiLocalScope* current_top_scope = thread->api_top_scope();
ApiLocalScope* scope = thread->api_reusable_scope();
TRACE_NATIVE_CALL("0x%" Px "", reinterpret_cast<uintptr_t>(func));
TransitionGeneratedToNative transition(thread);
if (scope == NULL) {
scope =
new ApiLocalScope(current_top_scope, thread->top_exit_frame_info());
ASSERT(scope != NULL);
} else {
scope->Reinit(thread, current_top_scope, thread->top_exit_frame_info());
thread->set_api_reusable_scope(NULL);
}
thread->set_api_top_scope(scope); // New scope is now the top scope.
func(args);
if (ReturnValueIsError(arguments)) {
PropagateErrors(arguments);
}
ASSERT(current_top_scope == scope->previous());
thread->set_api_top_scope(current_top_scope); // Reset top scope to prev.
if (thread->api_reusable_scope() == NULL) {
scope->Reset(thread); // Reset the old scope which we just exited.
thread->set_api_reusable_scope(scope);
} else {
ASSERT(thread->api_reusable_scope() != scope);
delete scope;
thread->EnterApiScope();
{
TransitionGeneratedToNative transition(thread);
func(args);
if (ReturnValueIsError(arguments)) {
PropagateErrors(arguments);
}
}
thread->ExitApiScope();
DEOPTIMIZE_ALOT;
}
ASSERT(thread->execution_state() == Thread::kThreadInGenerated);

View file

@ -11956,15 +11956,9 @@ bool LibraryPrefix::LoadLibrary() const {
isolate->object_store()->pending_deferred_loads());
pending_deferred_loads.Add(deferred_lib);
const String& lib_url = String::Handle(zone, deferred_lib.url());
Dart_LibraryTagHandler handler = isolate->library_tag_handler();
Object& obj = Object::Handle(zone);
{
TransitionVMToNative transition(thread);
Api::Scope api_scope(thread);
obj = Api::UnwrapHandle(handler(Dart_kImportTag,
Api::NewHandle(thread, importer()),
Api::NewHandle(thread, lib_url.raw())));
}
const Object& obj = Object::Handle(
zone, isolate->CallTagHandler(
Dart_kImportTag, Library::Handle(zone, importer()), lib_url));
if (obj.IsError()) {
Exceptions::PropagateError(Error::Cast(obj));
}

View file

@ -176,7 +176,11 @@ TEST_CASE(ObjectIdRingScavengeMoveTest) {
EXPECT_NE(RawObject::ToAddr(raw_obj1), RawObject::ToAddr(raw_object_moved1));
EXPECT_NE(RawObject::ToAddr(raw_obj2), RawObject::ToAddr(raw_object_moved2));
// Test that we still point at the same list.
Dart_Handle moved_handle = Api::NewHandle(thread, raw_object_moved1);
Dart_Handle moved_handle;
{
TransitionNativeToVM transition(thread);
moved_handle = Api::NewHandle(thread, raw_object_moved1);
}
EXPECT_VALID(moved_handle);
EXPECT(!Dart_IsNull(moved_handle));
EXPECT(Dart_IsList(moved_handle));
@ -197,7 +201,7 @@ ISOLATE_UNIT_TEST_CASE(ObjectIdRingOldGCTest) {
intptr_t raw_obj_id1 = -1;
intptr_t raw_obj_id2 = -1;
{
Dart_EnterScope();
Api::Scope api_scope(thread);
Dart_Handle result;
// Create a string in the old heap.
result = Api::NewHandle(thread, String::New("old", Heap::kOld));
@ -225,7 +229,6 @@ ISOLATE_UNIT_TEST_CASE(ObjectIdRingOldGCTest) {
EXPECT_EQ(RawObject::ToAddr(raw_obj), RawObject::ToAddr(raw_obj1));
EXPECT_EQ(RawObject::ToAddr(raw_obj), RawObject::ToAddr(raw_obj2));
// Exit scope. Freeing result handle.
Dart_ExitScope();
}
// Force a GC. No reference exist to the old string anymore. It should be
// collected and the object id ring will now return the null object for

View file

@ -2249,9 +2249,6 @@ ISOLATE_UNIT_TEST_CASE(Script) {
const char* kScript = "main() {}";
Dart_Handle h_lib = TestCase::LoadTestScript(kScript, NULL);
EXPECT_VALID(h_lib);
Library& lib = Library::Handle();
lib ^= Api::UnwrapHandle(h_lib);
EXPECT(!lib.IsNull());
Dart_Handle result = Dart_Invoke(h_lib, NewString("main"), 0, NULL);
EXPECT_VALID(result);
}
@ -3831,7 +3828,7 @@ TEST_CASE(FunctionWithBreakpointNotInlined) {
Dart_Handle result = Dart_Invoke(lib, NewString("test"), 0, NULL);
EXPECT_VALID(result);
Function& func_b = Function::Handle();
// With no breakpoint, function A.b is inlineable.
{
TransitionNativeToVM transition(thread);
const String& name = String::Handle(String::New(TestCase::url()));
@ -3840,16 +3837,25 @@ TEST_CASE(FunctionWithBreakpointNotInlined) {
EXPECT(!vmlib.IsNull());
const Class& class_a = Class::Handle(
vmlib.LookupClass(String::Handle(Symbols::New(thread, "A"))));
func_b = GetFunction(class_a, "b");
Function& func_b = Function::Handle(GetFunction(class_a, "b"));
EXPECT(func_b.CanBeInlined());
}
// With no breakpoint, function A.b is inlineable.
EXPECT(func_b.CanBeInlined());
// After setting a breakpoint in a function A.b, it is no longer inlineable.
result = Dart_SetBreakpoint(NewString(TestCase::url()), kBreakpointLine);
EXPECT_VALID(result);
EXPECT(!func_b.CanBeInlined());
// After setting a breakpoint in a function A.b, it is no longer inlineable.
{
TransitionNativeToVM transition(thread);
const String& name = String::Handle(String::New(TestCase::url()));
const Library& vmlib =
Library::Handle(Library::LookupLibrary(thread, name));
EXPECT(!vmlib.IsNull());
const Class& class_a = Class::Handle(
vmlib.LookupClass(String::Handle(Symbols::New(thread, "A"))));
Function& func_b = Function::Handle(GetFunction(class_a, "b"));
EXPECT(!func_b.CanBeInlined());
}
}
ISOLATE_UNIT_TEST_CASE(SpecialClassesHaveEmptyArrays) {
@ -4191,13 +4197,12 @@ TEST_CASE(InstanceEquality) {
Dart_Handle h_lib = TestCase::LoadTestScript(kScript, NULL);
EXPECT_VALID(h_lib);
Library& lib = Library::Handle();
lib ^= Api::UnwrapHandle(h_lib);
EXPECT(!lib.IsNull());
Dart_Handle result = Dart_Invoke(h_lib, NewString("main"), 0, NULL);
EXPECT_VALID(result);
TransitionNativeToVM transition(thread);
Library& lib = Library::Handle();
lib ^= Api::UnwrapHandle(h_lib);
const Class& clazz = Class::Handle(GetClass(lib, "A"));
EXPECT(!clazz.IsNull());
const Instance& a0 = Instance::Handle(Instance::New(clazz));
@ -4218,15 +4223,12 @@ TEST_CASE(HashCode) {
Dart_Handle h_lib = TestCase::LoadTestScript(kScript, NULL);
EXPECT_VALID(h_lib);
Library& lib = Library::Handle();
lib ^= Api::UnwrapHandle(h_lib);
EXPECT(!lib.IsNull());
Dart_Handle h_result = Dart_Invoke(h_lib, NewString("foo"), 0, NULL);
EXPECT_VALID(h_result);
Integer& result = Integer::Handle();
result ^= Api::UnwrapHandle(h_result);
TransitionNativeToVM transition(thread);
Integer& result = Integer::Handle();
result ^= Api::UnwrapHandle(h_result);
String& foo = String::Handle(String::New("foo"));
Integer& expected = Integer::Handle();
expected ^= foo.HashCode();
@ -4286,9 +4288,6 @@ TEST_CASE(LinkedHashMap) {
"}";
Dart_Handle h_lib = TestCase::LoadTestScript(kScript, NULL);
EXPECT_VALID(h_lib);
Library& lib = Library::Handle();
lib ^= Api::UnwrapHandle(h_lib);
EXPECT(!lib.IsNull());
Dart_Handle h_result = Dart_Invoke(h_lib, NewString("makeMap"), 0, NULL);
EXPECT_VALID(h_result);
@ -4313,12 +4312,10 @@ TEST_CASE(LinkedHashMap_iteration) {
"}";
Dart_Handle h_lib = TestCase::LoadTestScript(kScript, NULL);
EXPECT_VALID(h_lib);
Library& lib = Library::Handle();
lib ^= Api::UnwrapHandle(h_lib);
EXPECT(!lib.IsNull());
Dart_Handle h_result = Dart_Invoke(h_lib, NewString("makeMap"), 0, NULL);
EXPECT_VALID(h_result);
TransitionNativeToVM transition(thread);
Instance& dart_map = Instance::Handle();
dart_map ^= Api::UnwrapHandle(h_result);
ASSERT(dart_map.IsLinkedHashMap());

File diff suppressed because it is too large Load diff

View file

@ -8,7 +8,7 @@
namespace dart {
TEST_CASE(LocalScope) {
ISOLATE_UNIT_TEST_CASE(LocalScope) {
// Allocate a couple of local variables first.
const Type& dynamic_type = Type::ZoneHandle(Type::DynamicType());
const String& a = String::ZoneHandle(Symbols::New(thread, "a"));

View file

@ -167,16 +167,19 @@ void Service::CancelStream(const char* stream_id) {
RawObject* Service::RequestAssets() {
Thread* T = Thread::Current();
TransitionVMToNative transition(T);
Api::Scope api_scope(T);
if (get_service_assets_callback_ == NULL) {
return Object::null();
Object& object = Object::Handle();
{
Api::Scope api_scope(T);
TransitionVMToNative transition(T);
if (get_service_assets_callback_ == NULL) {
return Object::null();
}
Dart_Handle handle = get_service_assets_callback_();
if (Dart_IsError(handle)) {
Dart_PropagateError(handle);
}
object = Api::UnwrapHandle(handle);
}
Dart_Handle handle = get_service_assets_callback_();
if (Dart_IsError(handle)) {
Dart_PropagateError(handle);
}
const Object& object = Object::Handle(Api::UnwrapHandle(handle));
if (object.IsNull()) {
return Object::null();
}
@ -197,7 +200,7 @@ RawObject* Service::RequestAssets() {
Exceptions::PropagateError(error);
return Object::null();
}
return Api::UnwrapHandle(handle);
return object.raw();
}
static uint8_t* allocator(uint8_t* ptr, intptr_t old_size, intptr_t new_size) {
@ -2704,7 +2707,6 @@ static bool CompileExpression(Thread* thread, JSONStream* js) {
bool is_static = BoolParameter::Parse(js->LookupParam("isStatic"), false);
Dart_KernelCompilationResult compilation_result;
const GrowableObjectArray& params =
GrowableObjectArray::Handle(thread->zone(), GrowableObjectArray::New());
if (!ParseCSVList(js->LookupParam("definitions"), params)) {
@ -2719,14 +2721,12 @@ static bool CompileExpression(Thread* thread, JSONStream* js) {
return true;
}
{
TransitionVMToNative transition(thread);
compilation_result = KernelIsolate::CompileExpressionToKernel(
js->LookupParam("expression"),
Array::Handle(Array::MakeFixedLength(params)),
Array::Handle(Array::MakeFixedLength(type_params)),
js->LookupParam("libraryUri"), js->LookupParam("klass"), is_static);
}
Dart_KernelCompilationResult compilation_result =
KernelIsolate::CompileExpressionToKernel(
js->LookupParam("expression"),
Array::Handle(Array::MakeFixedLength(params)),
Array::Handle(Array::MakeFixedLength(type_params)),
js->LookupParam("libraryUri"), js->LookupParam("klass"), is_static);
if (compilation_result.status != Dart_KernelCompilationStatus_Ok) {
js->PrintError(kExpressionCompilationError, compilation_result.error);
@ -3070,8 +3070,7 @@ static bool ReloadSources(Thread* thread, JSONStream* js) {
}
Isolate* isolate = thread->isolate();
Dart_LibraryTagHandler handler = isolate->library_tag_handler();
if (handler == NULL) {
if (!isolate->HasTagHandler()) {
js->PrintError(kFeatureDisabled,
"A library tag handler must be installed.");
return true;

View file

@ -384,7 +384,6 @@ class RunServiceTask : public ThreadPool::Task {
if (!error.IsNull() && !error.IsUnwindError()) {
OS::PrintErr("vm-service: Error: %s\n", error.ToErrorCString());
}
TransitionVMToNative transition(T);
Dart::RunShutdownCallback();
}
ASSERT(ServiceIsolate::IsServiceIsolate(I));

View file

@ -760,24 +760,23 @@ VM_UNIT_TEST_CASE(FullSnapshot) {
{
TestIsolateScope __test_isolate__;
// Create a test library and Load up a test script in it.
TestCase::LoadTestScript(kScriptChars, NULL);
Thread* thread = Thread::Current();
TransitionNativeToVM transition(thread);
StackZone zone(thread);
HandleScope scope(thread);
// Create a test library and Load up a test script in it.
TestCase::LoadTestScript(kScriptChars, NULL);
EXPECT_VALID(Api::CheckAndFinalizePendingClasses(thread));
timer1.Stop();
OS::PrintErr("Without Snapshot: %" Pd64 "us\n", timer1.TotalElapsedTime());
// Write snapshot with object content.
{
TransitionNativeToVM transition(thread);
FullSnapshotWriter writer(
Snapshot::kFull, NULL, &isolate_snapshot_data_buffer,
&malloc_allocator, NULL, NULL /* image_writer */);
writer.WriteFullSnapshot();
}
FullSnapshotWriter writer(Snapshot::kFull, NULL,
&isolate_snapshot_data_buffer, &malloc_allocator,
NULL, NULL /* image_writer */);
writer.WriteFullSnapshot();
}
// Now Create another isolate using the snapshot and execute a method
@ -869,8 +868,11 @@ VM_UNIT_TEST_CASE(FullSnapshot1) {
// Helper function to call a top level Dart function and serialize the result.
static Message* GetSerialized(Dart_Handle lib, const char* dart_function) {
Dart_Handle result;
result = Dart_Invoke(lib, NewString(dart_function), 0, NULL);
EXPECT_VALID(result);
{
TransitionVMToNative transition(Thread::Current());
result = Dart_Invoke(lib, NewString(dart_function), 0, NULL);
EXPECT_VALID(result);
}
Object& obj = Object::Handle(Api::UnwrapHandle(result));
// Serialize the object into a message.
@ -1009,6 +1011,7 @@ VM_UNIT_TEST_CASE(DartGeneratedMessages) {
{
Thread* thread = Thread::Current();
CHECK_API_SCOPE(thread);
TransitionNativeToVM transition(thread);
HANDLESCOPE(thread);
{
@ -1081,6 +1084,7 @@ VM_UNIT_TEST_CASE(DartGeneratedListMessages) {
{
CHECK_API_SCOPE(thread);
TransitionNativeToVM transition(thread);
HANDLESCOPE(thread);
StackZone zone(thread);
{
@ -1208,6 +1212,7 @@ VM_UNIT_TEST_CASE(DartGeneratedArrayLiteralMessages) {
{
CHECK_API_SCOPE(thread);
TransitionNativeToVM transition(thread);
HANDLESCOPE(thread);
StackZone zone(thread);
{
@ -1445,6 +1450,7 @@ VM_UNIT_TEST_CASE(DartGeneratedListMessagesWithBackref) {
{
CHECK_API_SCOPE(thread);
TransitionNativeToVM transition(thread);
HANDLESCOPE(thread);
StackZone zone(thread);
{
@ -1653,6 +1659,7 @@ VM_UNIT_TEST_CASE(DartGeneratedArrayLiteralMessagesWithBackref) {
{
CHECK_API_SCOPE(thread);
TransitionNativeToVM transition(thread);
HANDLESCOPE(thread);
StackZone zone(thread);
{
@ -1883,6 +1890,7 @@ VM_UNIT_TEST_CASE(DartGeneratedListMessagesWithTypedData) {
{
CHECK_API_SCOPE(thread);
TransitionNativeToVM transition(thread);
HANDLESCOPE(thread);
StackZone zone(thread);
{

View file

@ -11,15 +11,15 @@ namespace dart {
#ifndef PRODUCT
static RawObject* ExecuteScript(const char* script) {
TransitionVMToNative transition(Thread::Current());
Dart_Handle h_lib = TestCase::LoadTestScript(script, NULL);
EXPECT_VALID(h_lib);
Library& lib = Library::Handle();
lib ^= Api::UnwrapHandle(h_lib);
EXPECT(!lib.IsNull());
Dart_Handle result = Dart_Invoke(h_lib, NewString("main"), 0, NULL);
EXPECT_VALID(result);
return Api::UnwrapHandle(h_lib);
Dart_Handle lib;
{
TransitionVMToNative transition(Thread::Current());
lib = TestCase::LoadTestScript(script, NULL);
EXPECT_VALID(lib);
Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
EXPECT_VALID(result);
}
return Api::UnwrapHandle(lib);
}
ISOLATE_UNIT_TEST_CASE(SourceReport_Coverage_NoCalls) {

View file

@ -38,6 +38,7 @@ ISOLATE_UNIT_TEST_CASE(EmptyDartStackFrameIteration) {
#define REGISTER_FUNCTION(name, count) {"" #name, FUNCTION_NAME(name), count},
void FUNCTION_NAME(StackFrame_equals)(Dart_NativeArguments args) {
TransitionNativeToVM transition(Thread::Current());
NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
const Instance& expected = Instance::CheckedHandle(arguments->NativeArgAt(0));
const Instance& actual = Instance::CheckedHandle(arguments->NativeArgAt(1));
@ -49,6 +50,7 @@ void FUNCTION_NAME(StackFrame_equals)(Dart_NativeArguments args) {
}
void FUNCTION_NAME(StackFrame_frameCount)(Dart_NativeArguments args) {
TransitionNativeToVM transition(Thread::Current());
int count = 0;
StackFrameIterator frames(ValidationPolicy::kValidateFrames,
Thread::Current(),
@ -56,25 +58,20 @@ void FUNCTION_NAME(StackFrame_frameCount)(Dart_NativeArguments args) {
while (frames.NextFrame() != NULL) {
count += 1; // Count the frame.
}
{
TransitionNativeToVM transition(Thread::Current());
VerifyPointersVisitor::VerifyPointers();
}
VerifyPointersVisitor::VerifyPointers();
NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
arguments->SetReturn(Object::Handle(Smi::New(count)));
}
void FUNCTION_NAME(StackFrame_dartFrameCount)(Dart_NativeArguments args) {
TransitionNativeToVM transition(Thread::Current());
int count = 0;
DartFrameIterator frames(Thread::Current(),
StackFrameIterator::kNoCrossThreadIteration);
while (frames.NextFrame() != NULL) {
count += 1; // Count the dart frame.
}
{
TransitionNativeToVM transition(Thread::Current());
VerifyPointersVisitor::VerifyPointers();
}
VerifyPointersVisitor::VerifyPointers();
NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
arguments->SetReturn(Object::Handle(Smi::New(count)));
}
@ -143,6 +140,7 @@ static Dart_NativeFunction native_lookup(Dart_Handle name,
bool* auto_setup_scope) {
ASSERT(auto_setup_scope != NULL);
*auto_setup_scope = false;
TransitionNativeToVM transition(Thread::Current());
const Object& obj = Object::Handle(Api::UnwrapHandle(name));
ASSERT(obj.IsString());
const char* function_name = obj.ToCString();

View file

@ -89,7 +89,6 @@ Thread::Thread(Isolate* isolate)
no_callback_scope_depth_(0),
#if defined(DEBUG)
top_handle_scope_(NULL),
no_handle_scope_depth_(0),
no_safepoint_scope_depth_(0),
#endif
reusable_handles_(),
@ -885,6 +884,33 @@ int Thread::ZoneSizeInBytes() const {
return total;
}
void Thread::EnterApiScope() {
ASSERT(MayAllocateHandles());
ApiLocalScope* new_scope = api_reusable_scope();
if (new_scope == NULL) {
new_scope = new ApiLocalScope(api_top_scope(), top_exit_frame_info());
ASSERT(new_scope != NULL);
} else {
new_scope->Reinit(this, api_top_scope(), top_exit_frame_info());
set_api_reusable_scope(NULL);
}
set_api_top_scope(new_scope); // New scope is now the top scope.
}
void Thread::ExitApiScope() {
ASSERT(MayAllocateHandles());
ApiLocalScope* scope = api_top_scope();
ApiLocalScope* reusable_scope = api_reusable_scope();
set_api_top_scope(scope->previous()); // Reset top scope to previous.
if (reusable_scope == NULL) {
scope->Reset(this); // Reset the old scope which we just exited.
set_api_reusable_scope(scope);
} else {
ASSERT(reusable_scope != scope);
delete scope;
}
}
void Thread::UnwindScopes(uword stack_marker) {
// Unwind all scopes using the same stack_marker, i.e. all scopes allocated
// under the same top_exit_frame_info.

View file

@ -356,6 +356,9 @@ class Thread : public BaseThread {
ApiLocalScope* api_top_scope() const { return api_top_scope_; }
void set_api_top_scope(ApiLocalScope* value) { api_top_scope_ = value; }
void EnterApiScope();
void ExitApiScope();
// The isolate that this thread is operating on, or NULL if none.
Isolate* isolate() const { return isolate_; }
static intptr_t isolate_offset() { return OFFSET_OF(Thread, isolate_); }
@ -474,28 +477,6 @@ class Thread : public BaseThread {
bool bump_allocate() const { return bump_allocate_; }
void set_bump_allocate(bool b) { bump_allocate_ = b; }
int32_t no_handle_scope_depth() const {
#if defined(DEBUG)
return no_handle_scope_depth_;
#else
return 0;
#endif
}
void IncrementNoHandleScopeDepth() {
#if defined(DEBUG)
ASSERT(no_handle_scope_depth_ < INT_MAX);
no_handle_scope_depth_ += 1;
#endif
}
void DecrementNoHandleScopeDepth() {
#if defined(DEBUG)
ASSERT(no_handle_scope_depth_ > 0);
no_handle_scope_depth_ -= 1;
#endif
}
HandleScope* top_handle_scope() const {
#if defined(DEBUG)
return top_handle_scope_;
@ -731,6 +712,11 @@ class Thread : public BaseThread {
execution_state_ = static_cast<uint32_t>(state);
}
bool MayAllocateHandles() {
return (execution_state() == kThreadInVM) ||
(execution_state() == kThreadInGenerated);
}
bool TryEnterSafepoint() {
uint32_t new_state = SetAtSafepoint(true, 0);
if (AtomicOperations::CompareAndSwapUint32(&safepoint_state_, 0,
@ -877,7 +863,6 @@ class Thread : public BaseThread {
int32_t no_callback_scope_depth_;
#if defined(DEBUG)
HandleScope* top_handle_scope_;
int32_t no_handle_scope_depth_;
int32_t no_safepoint_scope_depth_;
#endif
VMHandles reusable_handles_;

View file

@ -665,14 +665,11 @@ Dart_Handle TestCase::EvaluateExpression(const Library& lib,
if (!KernelIsolate::IsRunning()) {
UNREACHABLE();
} else {
Dart_KernelCompilationResult compilation_result;
{
TransitionVMToNative transition(thread);
compilation_result = KernelIsolate::CompileExpressionToKernel(
expr.ToCString(), param_names, Array::empty_array(),
String::Handle(lib.url()).ToCString(), /* klass=*/nullptr,
/* is_static= */ false);
}
Dart_KernelCompilationResult compilation_result =
KernelIsolate::CompileExpressionToKernel(
expr.ToCString(), param_names, Array::empty_array(),
String::Handle(lib.url()).ToCString(), /* klass=*/nullptr,
/* is_static= */ false);
if (compilation_result.status != Dart_KernelCompilationStatus_Ok) {
return Dart_NewApiError(compilation_result.error);
}

View file

@ -64,8 +64,10 @@
TestIsolateScope __test_isolate__; \
Thread* __thread__ = Thread::Current(); \
ASSERT(__thread__->isolate() == __test_isolate__.isolate()); \
TransitionNativeToVM transition1(__thread__); \
StackZone __zone__(__thread__); \
HandleScope __hs__(__thread__); \
TransitionVMToNative transition2(__thread__); \
Dart_TestHelper##name(__thread__); \
} \
static void Dart_TestHelper##name(Thread* thread)