57b27a7b44
- Updated conditional compilation flags throughout the runtime codebase to transition from DART_DYNAMIC_MODULES to DART_BYTECODE_INTERPRETER. - Adjusted logic in various files including object_graph_copy.cc, object_reload.cc, profiler.cc, and others to ensure compatibility with the new interpreter model. - Ensured that all references to dynamic modules are replaced with bytecode interpreter checks, maintaining functionality for interpreted code execution. - Modified stack frame handling and service-related code to align with the new interpreter architecture. - Updated tests and service implementations to reflect the changes in the runtime environment. Signed-off-by: Tony <tonylu@tony-cloud.com>
230 lines
8.1 KiB
C++
230 lines
8.1 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_NATIVE_ARGUMENTS_H_
|
|
#define RUNTIME_VM_NATIVE_ARGUMENTS_H_
|
|
|
|
#include "platform/assert.h"
|
|
#include "platform/memory_sanitizer.h"
|
|
#include "vm/globals.h"
|
|
#include "vm/simulator.h"
|
|
#include "vm/stub_code.h"
|
|
|
|
namespace dart {
|
|
|
|
// Forward declarations.
|
|
class BootstrapNatives;
|
|
class Object;
|
|
class Simulator;
|
|
class Thread;
|
|
|
|
#if defined(TESTING) || defined(DEBUG)
|
|
|
|
#if defined(DART_INCLUDE_SIMULATOR)
|
|
// The simulator/isolate might not exist yet for an async FFI callback, so do
|
|
// not check. An equivalent check exists in the simulator itself.
|
|
#define CHECK_STACK_ALIGNMENT \
|
|
{ \
|
|
}
|
|
#elif defined(DART_HOST_OS_WINDOWS)
|
|
// The compiler may dynamically align the stack on Windows, so do not check.
|
|
#define CHECK_STACK_ALIGNMENT \
|
|
{ \
|
|
}
|
|
#else
|
|
#define CHECK_STACK_ALIGNMENT \
|
|
{ \
|
|
ASSERT(Utils::IsAligned(OSThread::GetCurrentStackPointer(), \
|
|
OS::ActivationFrameAlignment())); \
|
|
}
|
|
#endif
|
|
|
|
#define DEOPTIMIZE_ALOT \
|
|
if (FLAG_deoptimize_alot) { \
|
|
DeoptimizeFunctionsOnStack(); \
|
|
}
|
|
|
|
#else
|
|
|
|
#define CHECK_STACK_ALIGNMENT \
|
|
{ \
|
|
}
|
|
#define DEOPTIMIZE_ALOT \
|
|
{ \
|
|
}
|
|
|
|
#endif
|
|
|
|
// Class NativeArguments is used to access arguments passed in from
|
|
// generated dart code to a runtime function or a dart library native
|
|
// function. It is also used to set the return value if any at the slot
|
|
// reserved for return values.
|
|
// All runtime function/dart library native functions have the
|
|
// following signature:
|
|
// void function_name(NativeArguments arguments);
|
|
// Inside the function, arguments are accessed as follows:
|
|
// const Instance& arg0 = Instance::CheckedHandle(arguments.NativeArgAt(0));
|
|
// const Smi& arg1 = Smi::CheckedHandle(arguments.NativeArgAt(1));
|
|
// If the function is generic, type arguments are accessed as follows:
|
|
// const TypeArguments& type_args =
|
|
// TypeArguments::Handle(arguments.NativeTypeArgs());
|
|
// The return value is set as follows:
|
|
// arguments.SetReturn(result);
|
|
// NOTE: Since we pass 'this' as a pass-by-value argument in the stubs we don't
|
|
// have DISALLOW_COPY_AND_ASSIGN in the class definition and do not make it a
|
|
// subclass of ValueObject.
|
|
class NativeArguments {
|
|
private:
|
|
using ArgcBits = BitField<intptr_t, int32_t, 0, 24>;
|
|
using GenericFunctionBit = BitField<intptr_t, bool, ArgcBits::kNextBit>;
|
|
using ReverseArgOrderBit =
|
|
BitField<intptr_t, bool, GenericFunctionBit::kNextBit>;
|
|
|
|
public:
|
|
Thread* thread() const { return thread_; }
|
|
|
|
// Includes type arguments vector.
|
|
int ArgCount() const { return ArgcBits::decode(argc_tag_); }
|
|
|
|
ObjectPtr ArgAt(int index) const {
|
|
ASSERT((index >= 0) && (index < ArgCount()));
|
|
ObjectPtr* arg_ptr =
|
|
&(argv_[ReverseArgOrderBit::decode(argc_tag_) ? index : -index]);
|
|
// Tell MemorySanitizer the ObjectPtr was initialized (by generated code).
|
|
MSAN_UNPOISON(arg_ptr, kWordSize);
|
|
return *arg_ptr;
|
|
}
|
|
|
|
void SetArgAt(int index, const Object& value) const {
|
|
ASSERT(thread_->execution_state() == Thread::kThreadInVM);
|
|
ASSERT((index >= 0) && (index < ArgCount()));
|
|
argv_[ReverseArgOrderBit::decode(argc_tag_) ? index : -index] = value.ptr();
|
|
}
|
|
|
|
// Does not include hidden type arguments vector.
|
|
int NativeArgCount() const { return ArgCount() - NumHiddenArgs(); }
|
|
|
|
ObjectPtr NativeArg0() const { return ArgAt(NumHiddenArgs()); }
|
|
|
|
ObjectPtr NativeArgAt(int index) const {
|
|
ASSERT((index >= 0) && (index < NativeArgCount()));
|
|
return ArgAt(index + NumHiddenArgs());
|
|
}
|
|
|
|
TypeArgumentsPtr NativeTypeArgs() const {
|
|
ASSERT(ToGenericFunction());
|
|
return TypeArguments::RawCast(ArgAt(0));
|
|
}
|
|
|
|
int NativeTypeArgCount() const {
|
|
if (ToGenericFunction()) {
|
|
TypeArguments& type_args = TypeArguments::Handle(NativeTypeArgs());
|
|
if (type_args.IsNull()) {
|
|
// null vector represents infinite list of dynamics
|
|
return INT_MAX;
|
|
}
|
|
return type_args.Length();
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
AbstractTypePtr NativeTypeArgAt(int index) const {
|
|
ASSERT((index >= 0) && (index < NativeTypeArgCount()));
|
|
TypeArguments& type_args = TypeArguments::Handle(NativeTypeArgs());
|
|
if (type_args.IsNull()) {
|
|
// null vector represents infinite list of dynamics
|
|
return Type::dynamic_type().ptr();
|
|
}
|
|
return type_args.TypeAt(index);
|
|
}
|
|
|
|
void SetReturn(const Object& value) const {
|
|
ASSERT(thread_->execution_state() == Thread::kThreadInVM);
|
|
*retval_ = value.ptr();
|
|
}
|
|
|
|
ObjectPtr ReturnValue() const {
|
|
// Tell MemorySanitizer the retval_ was initialized (by generated code).
|
|
MSAN_UNPOISON(retval_, kWordSize);
|
|
return *retval_;
|
|
}
|
|
|
|
uword GetCallerSP() const {
|
|
return reinterpret_cast<uword>(
|
|
retval_ + (ReverseArgOrderBit::decode(argc_tag_) ? 0 : 1));
|
|
}
|
|
|
|
static intptr_t thread_offset() {
|
|
return OFFSET_OF(NativeArguments, thread_);
|
|
}
|
|
static intptr_t argc_tag_offset() {
|
|
return OFFSET_OF(NativeArguments, argc_tag_);
|
|
}
|
|
static intptr_t argv_offset() { return OFFSET_OF(NativeArguments, argv_); }
|
|
static intptr_t retval_offset() {
|
|
return OFFSET_OF(NativeArguments, retval_);
|
|
}
|
|
|
|
static intptr_t ParameterCountForResolution(const Function& function) {
|
|
ASSERT(function.is_old_native());
|
|
ASSERT(!function.IsGenerativeConstructor()); // Not supported.
|
|
ASSERT(!function.IsClosureFunction()); // Not supported.
|
|
return function.NumParameters();
|
|
}
|
|
|
|
static int ComputeArgcTag(const Function& function) {
|
|
ASSERT(function.is_old_native());
|
|
ASSERT(!function.IsGenerativeConstructor()); // Not supported.
|
|
ASSERT(!function.IsClosureFunction()); // Not supported.
|
|
bool is_generic = function.IsGeneric();
|
|
return ArgcBits::encode(function.NumParameters() + (is_generic ? 1 : 0)) |
|
|
GenericFunctionBit::encode(is_generic);
|
|
}
|
|
|
|
private:
|
|
friend class Api;
|
|
friend class Interpreter;
|
|
friend class NativeEntry;
|
|
friend class Simulator;
|
|
|
|
#if defined(DART_BYTECODE_INTERPRETER)
|
|
NativeArguments(Thread* thread,
|
|
int argc_tag,
|
|
ObjectPtr* argv,
|
|
ObjectPtr* retval)
|
|
: thread_(thread),
|
|
argc_tag_(ReverseArgOrderBit::update(true, argc_tag)),
|
|
argv_(argv),
|
|
retval_(retval) {}
|
|
NativeArguments() = default;
|
|
#endif // defined(DART_BYTECODE_INTERPRETER)
|
|
|
|
// Since this function is passed an ObjectPtr directly, we need to be
|
|
// exceedingly careful when we use it. If there are any other side
|
|
// effects in the statement that may cause GC, it could lead to
|
|
// bugs.
|
|
void SetReturnUnsafe(ObjectPtr value) const {
|
|
ASSERT(thread_->execution_state() == Thread::kThreadInVM);
|
|
*retval_ = value;
|
|
}
|
|
|
|
// Returns true if the arguments are those of a generic function call.
|
|
bool ToGenericFunction() const {
|
|
return GenericFunctionBit::decode(argc_tag_);
|
|
}
|
|
|
|
int NumHiddenArgs() const {
|
|
return GenericFunctionBit::decode(argc_tag_) ? 1 : 0;
|
|
}
|
|
|
|
Thread* thread_; // Current thread pointer.
|
|
intptr_t argc_tag_; // Encodes argument count and invoked native call type.
|
|
ObjectPtr* argv_; // Pointer to an array of arguments to runtime call.
|
|
ObjectPtr* retval_; // Pointer to the return value area.
|
|
};
|
|
|
|
} // namespace dart
|
|
|
|
#endif // RUNTIME_VM_NATIVE_ARGUMENTS_H_
|