Files
sdk/runtime/vm/object_store.h
T
Daco Harkes 6544c69e23 [vm/ffi] Convert Objects to Dart_Handles in FFI calls
This includes support for calling Dart_PropagateError in native code
when doing FFI calls, and catching uncaught exceptions with Dart_IsError
when doing FFI callbacks.

The support for Dart_PropagateError adds a catch entry to the FFI
trampoline, which prevents inlining these trampolines in AOT. This
regresses the FfiCall benchmarks by 1-2% in AOT.

In addition, Dart_PropagateError requires maintaining a bit whether we
entered native/VM code from generated code through FFI or not. That way
we can do the proper transition on the exception path. When entering
generated code, we store this bit on the stack, right after the entry
frame.

Design: http://go/dart-ffi-handles

Issue: https://github.com/dart-lang/sdk/issues/36858
Issue: https://github.com/dart-lang/sdk/issues/41319

Change-Id: Idfd7ff69132fb29cc730931a4113d914d4437396
Cq-Include-Trybots: luci.dart.try:vm-ffi-android-debug-arm-try,vm-ffi-android-debug-arm64-try,app-kernel-linux-debug-x64-try,vm-kernel-linux-debug-ia32-try,vm-kernel-win-debug-x64-try,vm-kernel-win-debug-ia32-try,vm-kernel-precomp-linux-debug-x64-try,vm-dartkb-linux-release-x64-abi-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-asan-linux-release-x64-try,vm-kernel-linux-release-simarm-try,vm-kernel-linux-release-simarm64-try,vm-kernel-precomp-android-release-arm_x64-try,vm-kernel-precomp-obfuscate-linux-release-x64-try,dart-sdk-linux-try,analyzer-analysis-server-linux-try,analyzer-linux-release-try,front-end-linux-release-x64-try,vm-kernel-precomp-win-release-x64-try,vm-kernel-mac-debug-x64-try,vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-nnbd-linux-debug-x64-try,analyzer-nnbd-linux-release-try,front-end-nnbd-linux-release-x64-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/145591
Commit-Queue: Daco Harkes <dacoharkes@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
Reviewed-by: Alexander Markov <alexmarkov@google.com>
2020-06-12 11:14:22 +00:00

437 lines
25 KiB
C++

// Copyright (c) 2012, 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 RUNTIME_VM_OBJECT_STORE_H_
#define RUNTIME_VM_OBJECT_STORE_H_
#include "vm/object.h"
namespace dart {
// Forward declarations.
class Isolate;
class ObjectPointerVisitor;
// A list of the bootstrap libraries including CamelName and name.
//
// These are listed in the order that they are compiled (see vm/bootstrap.cc).
#define FOR_EACH_BOOTSTRAP_LIBRARY(M) \
M(Core, core) \
M(Async, async) \
M(Collection, collection) \
M(Convert, convert) \
M(Developer, developer) \
M(Ffi, ffi) \
M(Internal, _internal) \
M(Isolate, isolate) \
M(Math, math) \
M(Mirrors, mirrors) \
M(TypedData, typed_data) \
M(VMService, _vmservice) \
M(Wasm, wasm)
// TODO(liama): Once NNBD is enabled, *_type will be deleted and all uses will
// be replaced with *_type_non_nullable. Later, once we drop support for opted
// out code, *_type_legacy will be deleted.
//
// R_ - needs getter only
// RW - needs getter and setter
#define OBJECT_STORE_FIELD_LIST(R_, RW) \
RW(Class, object_class) \
RW(Type, object_type) \
RW(Type, legacy_object_type) \
RW(Type, non_nullable_object_type) \
RW(Type, nullable_object_type) \
RW(Class, null_class) \
RW(Type, null_type) \
RW(Class, never_class) \
RW(Type, never_type) \
RW(Type, function_type) \
RW(Type, legacy_function_type) \
RW(Type, non_nullable_function_type) \
RW(Type, type_type) \
RW(Class, closure_class) \
RW(Type, number_type) \
RW(Type, legacy_number_type) \
RW(Type, non_nullable_number_type) \
RW(Type, int_type) \
RW(Type, legacy_int_type) \
RW(Type, non_nullable_int_type) \
RW(Type, nullable_int_type) \
RW(Class, integer_implementation_class) \
RW(Type, int64_type) \
RW(Class, smi_class) \
RW(Type, smi_type) \
RW(Type, legacy_smi_type) \
RW(Type, non_nullable_smi_type) \
RW(Class, mint_class) \
RW(Type, mint_type) \
RW(Type, legacy_mint_type) \
RW(Type, non_nullable_mint_type) \
RW(Class, double_class) \
RW(Type, double_type) \
RW(Type, legacy_double_type) \
RW(Type, non_nullable_double_type) \
RW(Type, nullable_double_type) \
RW(Type, float32x4_type) \
RW(Type, int32x4_type) \
RW(Type, float64x2_type) \
RW(Type, string_type) \
RW(Type, legacy_string_type) \
RW(Type, non_nullable_string_type) \
RW(Type, non_nullable_list_rare_type) /* maybe be null, lazily built */ \
RW(Type, non_nullable_map_rare_type) /* maybe be null, lazily built */ \
RW(Type, non_nullable_future_rare_type) /* maybe be null, lazily built */ \
RW(TypeArguments, type_argument_int) \
RW(TypeArguments, type_argument_legacy_int) \
RW(TypeArguments, type_argument_non_nullable_int) \
RW(TypeArguments, type_argument_double) \
RW(TypeArguments, type_argument_legacy_double) \
RW(TypeArguments, type_argument_non_nullable_double) \
RW(TypeArguments, type_argument_string) \
RW(TypeArguments, type_argument_legacy_string) \
RW(TypeArguments, type_argument_non_nullable_string) \
RW(TypeArguments, type_argument_string_dynamic) \
RW(TypeArguments, type_argument_legacy_string_dynamic) \
RW(TypeArguments, type_argument_non_nullable_string_dynamic) \
RW(TypeArguments, type_argument_string_string) \
RW(TypeArguments, type_argument_legacy_string_legacy_string) \
RW(TypeArguments, type_argument_non_nullable_string_non_nullable_string) \
RW(Class, compiletime_error_class) \
RW(Class, pragma_class) \
RW(Field, pragma_name) \
RW(Field, pragma_options) \
RW(Class, future_class) \
RW(Type, non_nullable_future_never_type) /* maybe be null, lazily built */ \
RW(Type, nullable_future_null_type) /* maybe be null, lazily built */ \
RW(Class, completer_class) \
RW(Class, symbol_class) \
RW(Class, one_byte_string_class) \
RW(Class, two_byte_string_class) \
RW(Class, external_one_byte_string_class) \
RW(Class, external_two_byte_string_class) \
RW(Type, bool_type) \
RW(Type, legacy_bool_type) \
RW(Type, non_nullable_bool_type) \
RW(Class, bool_class) \
RW(Class, array_class) \
RW(Type, array_type) \
RW(Type, legacy_array_type) \
RW(Type, non_nullable_array_type) \
RW(Class, immutable_array_class) \
RW(Class, growable_object_array_class) \
RW(Class, linked_hash_map_class) \
RW(Class, linked_hash_set_class) \
RW(Class, float32x4_class) \
RW(Class, int32x4_class) \
RW(Class, float64x2_class) \
RW(Class, error_class) \
RW(Class, weak_property_class) \
RW(Array, symbol_table) \
RW(Array, canonical_types) \
RW(Array, canonical_type_parameters) \
RW(Array, canonical_type_arguments) \
RW(Library, async_library) \
RW(Library, builtin_library) \
RW(Library, core_library) \
RW(Library, collection_library) \
RW(Library, convert_library) \
RW(Library, developer_library) \
RW(Library, ffi_library) \
RW(Library, _internal_library) \
RW(Library, isolate_library) \
RW(Library, math_library) \
RW(Library, mirrors_library) \
RW(Library, native_wrappers_library) \
RW(Library, profiler_library) \
RW(Library, root_library) \
RW(Library, typed_data_library) \
RW(Library, _vmservice_library) \
RW(Library, wasm_library) \
RW(GrowableObjectArray, libraries) \
RW(Array, libraries_map) \
RW(GrowableObjectArray, closure_functions) \
RW(GrowableObjectArray, pending_classes) \
RW(Instance, stack_overflow) \
RW(Instance, out_of_memory) \
RW(Function, lookup_port_handler) \
RW(Function, handle_message_function) \
RW(Function, growable_list_factory) \
RW(Function, simple_instance_of_function) \
RW(Function, simple_instance_of_true_function) \
RW(Function, simple_instance_of_false_function) \
RW(Function, async_clear_thread_stack_trace) \
RW(Function, async_set_thread_stack_trace) \
RW(Function, async_star_move_next_helper) \
RW(Function, complete_on_async_return) \
RW(Class, async_star_stream_controller) \
RW(Array, bytecode_attributes) \
RW(GrowableObjectArray, llvm_constant_pool) \
RW(GrowableObjectArray, llvm_function_pool) \
RW(Array, llvm_constant_hash_table) \
RW(CompressedStackMaps, canonicalized_stack_map_entries) \
RW(ObjectPool, global_object_pool) \
RW(Array, unique_dynamic_targets) \
RW(GrowableObjectArray, megamorphic_cache_table) \
RW(Code, build_method_extractor_code) \
RW(Code, dispatch_table_null_error_stub) \
RW(Code, null_error_stub_with_fpu_regs_stub) \
RW(Code, null_error_stub_without_fpu_regs_stub) \
RW(Code, null_arg_error_stub_with_fpu_regs_stub) \
RW(Code, null_arg_error_stub_without_fpu_regs_stub) \
RW(Code, range_error_stub_with_fpu_regs_stub) \
RW(Code, range_error_stub_without_fpu_regs_stub) \
RW(Code, allocate_mint_with_fpu_regs_stub) \
RW(Code, allocate_mint_without_fpu_regs_stub) \
RW(Code, stack_overflow_stub_with_fpu_regs_stub) \
RW(Code, stack_overflow_stub_without_fpu_regs_stub) \
RW(Code, allocate_array_stub) \
RW(Code, allocate_context_stub) \
RW(Code, allocate_object_stub) \
RW(Code, allocate_object_parametrized_stub) \
RW(Code, allocate_unhandled_exception_stub) \
RW(Code, clone_context_stub) \
RW(Code, write_barrier_wrappers_stub) \
RW(Code, array_write_barrier_stub) \
RW(Code, throw_stub) \
RW(Code, re_throw_stub) \
RW(Code, assert_boolean_stub) \
RW(Code, instance_of_stub) \
RW(Code, init_static_field_stub) \
RW(Code, init_instance_field_stub) \
RW(Code, init_late_instance_field_stub) \
RW(Code, init_late_final_instance_field_stub) \
RW(Code, call_closure_no_such_method_stub) \
RW(Code, default_tts_stub) \
RW(Code, default_nullable_tts_stub) \
RW(Code, top_type_tts_stub) \
RW(Code, unreachable_tts_stub) \
RW(Code, slow_tts_stub) \
RW(Array, dispatch_table_code_entries) \
RW(Array, code_order_table) \
RW(Array, obfuscation_map) \
RW(Class, ffi_pointer_class) \
RW(Class, ffi_native_type_class) \
RW(Class, ffi_struct_class) \
RW(Object, ffi_as_function_internal) \
// Please remember the last entry must be referred in the 'to' function below.
#define OBJECT_STORE_STUB_CODE_LIST(DO) \
DO(dispatch_table_null_error_stub, DispatchTableNullError) \
DO(null_error_stub_with_fpu_regs_stub, NullErrorSharedWithFPURegs) \
DO(null_error_stub_without_fpu_regs_stub, NullErrorSharedWithoutFPURegs) \
DO(null_arg_error_stub_with_fpu_regs_stub, NullArgErrorSharedWithFPURegs) \
DO(null_arg_error_stub_without_fpu_regs_stub, \
NullArgErrorSharedWithoutFPURegs) \
DO(range_error_stub_with_fpu_regs_stub, RangeErrorSharedWithFPURegs) \
DO(range_error_stub_without_fpu_regs_stub, RangeErrorSharedWithoutFPURegs) \
DO(allocate_mint_with_fpu_regs_stub, AllocateMintSharedWithFPURegs) \
DO(allocate_mint_without_fpu_regs_stub, AllocateMintSharedWithoutFPURegs) \
DO(stack_overflow_stub_with_fpu_regs_stub, StackOverflowSharedWithFPURegs) \
DO(stack_overflow_stub_without_fpu_regs_stub, \
StackOverflowSharedWithoutFPURegs) \
DO(allocate_array_stub, AllocateArray) \
DO(allocate_context_stub, AllocateContext) \
DO(allocate_object_stub, AllocateObject) \
DO(allocate_object_parametrized_stub, AllocateObjectParameterized) \
DO(allocate_unhandled_exception_stub, AllocateUnhandledException) \
DO(clone_context_stub, CloneContext) \
DO(call_closure_no_such_method_stub, CallClosureNoSuchMethod) \
DO(default_tts_stub, DefaultTypeTest) \
DO(default_nullable_tts_stub, DefaultNullableTypeTest) \
DO(top_type_tts_stub, TopTypeTypeTest) \
DO(unreachable_tts_stub, UnreachableTypeTest) \
DO(slow_tts_stub, SlowTypeTest) \
DO(write_barrier_wrappers_stub, WriteBarrierWrappers) \
DO(array_write_barrier_stub, ArrayWriteBarrier) \
DO(throw_stub, Throw) \
DO(re_throw_stub, ReThrow) \
DO(assert_boolean_stub, AssertBoolean) \
DO(init_static_field_stub, InitStaticField) \
DO(init_instance_field_stub, InitInstanceField) \
DO(init_late_instance_field_stub, InitLateInstanceField) \
DO(init_late_final_instance_field_stub, InitLateFinalInstanceField) \
DO(instance_of_stub, InstanceOf)
#define ISOLATE_OBJECT_STORE_FIELD_LIST(R_, RW) \
RW(UnhandledException, preallocated_unhandled_exception) \
RW(StackTrace, preallocated_stack_trace) \
RW(Array, dart_args_1) \
RW(Array, dart_args_2) \
R_(GrowableObjectArray, resume_capabilities) \
R_(GrowableObjectArray, exit_listeners) \
R_(GrowableObjectArray, error_listeners)
// Please remember the last entry must be referred in the 'to' function below.
class IsolateObjectStore {
public:
explicit IsolateObjectStore(ObjectStore* object_store);
~IsolateObjectStore();
#define DECLARE_GETTER(Type, name) \
Type##Ptr name() const { return name##_; } \
static intptr_t name##_offset() { \
return OFFSET_OF(IsolateObjectStore, name##_); \
}
#define DECLARE_GETTER_AND_SETTER(Type, name) \
DECLARE_GETTER(Type, name) \
void set_##name(const Type& value) { name##_ = value.raw(); }
ISOLATE_OBJECT_STORE_FIELD_LIST(DECLARE_GETTER, DECLARE_GETTER_AND_SETTER)
#undef DECLARE_GETTER
#undef DECLARE_GETTER_AND_SETTER
// Visit all object pointers.
void VisitObjectPointers(ObjectPointerVisitor* visitor);
// Called to initialize objects required by the vm but which invoke
// dart code. If an error occurs the error object is returned otherwise
// a null object is returned.
ErrorPtr PreallocateObjects();
void Init();
void PostLoad();
ObjectStore* object_store() const { return object_store_; }
void set_object_store(ObjectStore* object_store) {
ASSERT(object_store_ == nullptr);
object_store_ = object_store;
}
static intptr_t object_store_offset() {
return OFFSET_OF(IsolateObjectStore, object_store_);
}
#ifndef PRODUCT
void PrintToJSONObject(JSONObject* jsobj);
#endif
private:
// Finds a core library private method in Object.
FunctionPtr PrivateObjectLookup(const String& name);
ObjectPtr* from() {
return reinterpret_cast<ObjectPtr*>(&preallocated_unhandled_exception_);
}
#define DECLARE_OBJECT_STORE_FIELD(type, name) type##Ptr name##_;
ISOLATE_OBJECT_STORE_FIELD_LIST(DECLARE_OBJECT_STORE_FIELD,
DECLARE_OBJECT_STORE_FIELD)
#undef DECLARE_OBJECT_STORE_FIELD
ObjectPtr* to() { return reinterpret_cast<ObjectPtr*>(&error_listeners_); }
ObjectStore* object_store_;
friend class Serializer;
friend class Deserializer;
DISALLOW_COPY_AND_ASSIGN(IsolateObjectStore);
};
// The object store is a per isolate group instance which stores references to
// objects used by the VM shared by all isolates in a group.
class ObjectStore {
public:
enum BootstrapLibraryId {
#define MAKE_ID(Name, _) k##Name,
FOR_EACH_BOOTSTRAP_LIBRARY(MAKE_ID)
#undef MAKE_ID
};
ObjectStore();
~ObjectStore();
#define DECLARE_GETTER(Type, name) \
Type##Ptr name() const { return name##_; } \
static intptr_t name##_offset() { return OFFSET_OF(ObjectStore, name##_); }
#define DECLARE_GETTER_AND_SETTER(Type, name) \
DECLARE_GETTER(Type, name) \
void set_##name(const Type& value) { name##_ = value.raw(); }
OBJECT_STORE_FIELD_LIST(DECLARE_GETTER, DECLARE_GETTER_AND_SETTER)
#undef DECLARE_GETTER
#undef DECLARE_GETTER_AND_SETTER
LibraryPtr bootstrap_library(BootstrapLibraryId index) {
switch (index) {
#define MAKE_CASE(CamelName, name) \
case k##CamelName: \
return name##_library_;
FOR_EACH_BOOTSTRAP_LIBRARY(MAKE_CASE)
#undef MAKE_CASE
default:
UNREACHABLE();
return Library::null();
}
}
void set_bootstrap_library(BootstrapLibraryId index, const Library& value) {
switch (index) {
#define MAKE_CASE(CamelName, name) \
case k##CamelName: \
name##_library_ = value.raw(); \
break;
FOR_EACH_BOOTSTRAP_LIBRARY(MAKE_CASE)
#undef MAKE_CASE
default:
UNREACHABLE();
}
}
// Visit all object pointers.
void VisitObjectPointers(ObjectPointerVisitor* visitor);
// Called to initialize objects required by the vm but which invoke
// dart code. If an error occurs the error object is returned otherwise
// a null object is returned.
ErrorPtr PreallocateObjects();
void InitKnownObjects();
void InitStubs();
#ifndef PRODUCT
void PrintToJSONObject(JSONObject* jsobj);
#endif
private:
// Finds a core library private method in Object.
FunctionPtr PrivateObjectLookup(const String& name);
ObjectPtr* from() { return reinterpret_cast<ObjectPtr*>(&object_class_); }
#define DECLARE_OBJECT_STORE_FIELD(type, name) type##Ptr name##_;
OBJECT_STORE_FIELD_LIST(DECLARE_OBJECT_STORE_FIELD,
DECLARE_OBJECT_STORE_FIELD)
#undef DECLARE_OBJECT_STORE_FIELD
ObjectPtr* to() {
return reinterpret_cast<ObjectPtr*>(&ffi_as_function_internal_);
}
ObjectPtr* to_snapshot(Snapshot::Kind kind) {
switch (kind) {
case Snapshot::kFull:
return reinterpret_cast<ObjectPtr*>(&global_object_pool_);
case Snapshot::kFullJIT:
case Snapshot::kFullAOT:
return reinterpret_cast<ObjectPtr*>(&slow_tts_stub_);
case Snapshot::kMessage:
case Snapshot::kNone:
case Snapshot::kInvalid:
break;
}
UNREACHABLE();
return NULL;
}
friend class Serializer;
friend class Deserializer;
DISALLOW_COPY_AND_ASSIGN(ObjectStore);
};
} // namespace dart
#endif // RUNTIME_VM_OBJECT_STORE_H_