Files
sdk/runtime/vm/thread.h
T
Florian Schneider 63a8e5227d VM: More abstract interface for generating stub calls.
This makes the code in the code generator independent from how stubs
are actually called (i.e. directly embedding the target address, or
indirectly by loading the target address from the code object).

BUG=
R=rmacnak@google.com

Review URL: https://codereview.chromium.org//1270803003 .
2015-08-05 10:18:35 +02:00

249 lines
7.1 KiB
C++

// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef VM_THREAD_H_
#define VM_THREAD_H_
#include "vm/globals.h"
#include "vm/os_thread.h"
#include "vm/store_buffer.h"
namespace dart {
class CHA;
class HandleScope;
class Heap;
class Isolate;
class Object;
class RawBool;
class RawObject;
class StackResource;
class Zone;
// List of VM-global objects/addresses cached in each Thread object.
#define CACHED_VM_OBJECTS_LIST(V) \
V(RawObject*, object_null_, Object::null(), NULL) \
V(RawBool*, bool_true_, Object::bool_true().raw(), NULL) \
V(RawBool*, bool_false_, Object::bool_false().raw(), NULL) \
#define CACHED_ADDRESSES_LIST(V) \
V(uword, update_store_buffer_entry_point_, \
StubCode::UpdateStoreBuffer_entry()->EntryPoint(), 0)
#define CACHED_CONSTANTS_LIST(V) \
CACHED_VM_OBJECTS_LIST(V) \
CACHED_ADDRESSES_LIST(V)
// A VM thread; may be executing Dart code or performing helper tasks like
// garbage collection or compilation. The Thread structure associated with
// a thread is allocated by EnsureInit before entering an isolate, and destroyed
// automatically when the underlying OS thread exits. NOTE: On Windows, CleanUp
// must currently be called manually (issue 23474).
class Thread {
public:
// The currently executing thread, or NULL if not yet initialized.
static Thread* Current() {
return reinterpret_cast<Thread*>(OSThread::GetThreadLocal(thread_key_));
}
// Initializes the current thread as a VM thread, if not already done.
static void EnsureInit();
// Makes the current thread enter 'isolate'.
static void EnterIsolate(Isolate* isolate);
// Makes the current thread exit its isolate.
static void ExitIsolate();
// A VM thread other than the main mutator thread can enter an isolate as a
// "helper" to gain limited concurrent access to the isolate. One example is
// SweeperTask (which uses the class table, which is copy-on-write).
// TODO(koda): Properly synchronize heap access to expand allowed operations.
static void EnterIsolateAsHelper(Isolate* isolate);
static void ExitIsolateAsHelper();
// Called when the current thread transitions from mutator to collector.
// Empties the store buffer block into the isolate.
// TODO(koda): Always run GC in separate thread.
static void PrepareForGC();
#if defined(TARGET_OS_WINDOWS)
// Clears the state of the current thread and frees the allocation.
static void CleanUp();
#endif
// Called at VM startup.
static void InitOnceBeforeIsolate();
static void InitOnceAfterObjectAndStubCode();
~Thread();
// The topmost zone used for allocation in this thread.
Zone* zone() const { return state_.zone; }
// 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_);
}
// The (topmost) CHA for the compilation in the isolate of this thread.
// TODO(23153): Move this out of Isolate/Thread.
CHA* cha() const;
void set_cha(CHA* value);
void StoreBufferAddObject(RawObject* obj);
void StoreBufferAddObjectGC(RawObject* obj);
#if defined(TESTING)
bool StoreBufferContains(RawObject* obj) const {
return store_buffer_block_->Contains(obj);
}
#endif
void StoreBufferBlockProcess(bool check_threshold);
static intptr_t store_buffer_block_offset() {
return OFFSET_OF(Thread, store_buffer_block_);
}
uword top_exit_frame_info() const { return state_.top_exit_frame_info; }
static intptr_t top_exit_frame_info_offset() {
return OFFSET_OF(Thread, state_) + OFFSET_OF(State, top_exit_frame_info);
}
StackResource* top_resource() const { return state_.top_resource; }
void set_top_resource(StackResource* value) {
state_.top_resource = value;
}
static intptr_t top_resource_offset() {
return OFFSET_OF(Thread, state_) + OFFSET_OF(State, top_resource);
}
static intptr_t heap_offset() {
return OFFSET_OF(Thread, heap_);
}
int32_t no_handle_scope_depth() const {
#if defined(DEBUG)
return state_.no_handle_scope_depth;
#else
return 0;
#endif
}
void IncrementNoHandleScopeDepth() {
#if defined(DEBUG)
ASSERT(state_.no_handle_scope_depth < INT_MAX);
state_.no_handle_scope_depth += 1;
#endif
}
void DecrementNoHandleScopeDepth() {
#if defined(DEBUG)
ASSERT(state_.no_handle_scope_depth > 0);
state_.no_handle_scope_depth -= 1;
#endif
}
HandleScope* top_handle_scope() const {
#if defined(DEBUG)
return state_.top_handle_scope;
#else
return 0;
#endif
}
void set_top_handle_scope(HandleScope* handle_scope) {
#if defined(DEBUG)
state_.top_handle_scope = handle_scope;
#endif
}
int32_t no_safepoint_scope_depth() const {
#if defined(DEBUG)
return state_.no_safepoint_scope_depth;
#else
return 0;
#endif
}
void IncrementNoSafepointScopeDepth() {
#if defined(DEBUG)
ASSERT(state_.no_safepoint_scope_depth < INT_MAX);
state_.no_safepoint_scope_depth += 1;
#endif
}
void DecrementNoSafepointScopeDepth() {
#if defined(DEBUG)
ASSERT(state_.no_safepoint_scope_depth > 0);
state_.no_safepoint_scope_depth -= 1;
#endif
}
// Collection of isolate-specific state of a thread that is saved/restored
// on isolate exit/re-entry.
struct State {
Zone* zone;
uword top_exit_frame_info;
StackResource* top_resource;
#if defined(DEBUG)
HandleScope* top_handle_scope;
intptr_t no_handle_scope_depth;
int32_t no_safepoint_scope_depth;
#endif
};
#define DEFINE_OFFSET_METHOD(type_name, member_name, expr, default_init_value) \
static intptr_t member_name##offset() { \
return OFFSET_OF(Thread, member_name); \
}
CACHED_CONSTANTS_LIST(DEFINE_OFFSET_METHOD)
#undef DEFINE_OFFSET_METHOD
static bool CanLoadFromThread(const Object& object);
static intptr_t OffsetFromThread(const Object& object);
private:
static ThreadLocalKey thread_key_;
Isolate* isolate_;
Heap* heap_;
State state_;
StoreBufferBlock* store_buffer_block_;
#define DECLARE_MEMBERS(type_name, member_name, expr, default_init_value) \
type_name member_name;
CACHED_CONSTANTS_LIST(DECLARE_MEMBERS)
#undef DECLARE_MEMBERS
explicit Thread(bool init_vm_constants = true);
void InitVMConstants();
void ClearState() {
memset(&state_, 0, sizeof(state_));
}
void set_zone(Zone* zone) {
state_.zone = zone;
}
void set_top_exit_frame_info(uword top_exit_frame_info) {
state_.top_exit_frame_info = top_exit_frame_info;
}
static void SetCurrent(Thread* current);
void Schedule(Isolate* isolate);
void Unschedule();
friend class ApiZone;
friend class Isolate;
friend class StackZone;
DISALLOW_COPY_AND_ASSIGN(Thread);
};
} // namespace dart
#endif // VM_THREAD_H_