blob: 2d6e1273d99231e36638b13610458a62cb72f717 [file] [log] [blame]
// Copyright (c) 2019, 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_COMPILER_RUNTIME_API_H_
#define RUNTIME_VM_COMPILER_RUNTIME_API_H_
// This header defines the API that compiler can use to interact with the
// underlying Dart runtime that it is embedded into.
//
// Compiler is not allowed to directly interact with any objects - it can only
// use classes like dart::Object, dart::Code, dart::Function and similar as
// opaque handles. All interactions should be done through helper methods
// provided by this header.
//
// This header also provides ways to get word sizes, frame layout, field
// offsets for the target runtime. Note that these can be different from
// those on the host. Helpers providing access to these values live
// in compiler::target namespace.
#include "platform/globals.h"
#include "vm/allocation.h"
#include "vm/bitfield.h"
#include "vm/code_entry_kind.h"
#include "vm/frame_layout.h"
#include "vm/pointer_tagging.h"
namespace dart {
// Forward declarations.
class Class;
class Code;
class Function;
class LocalVariable;
class Object;
class String;
class Zone;
namespace compiler {
class Assembler;
}
namespace compiler {
// Host word sizes.
//
// Code in the compiler namespace should not use kWordSize and derived
// constants directly because the word size on host and target might
// be different.
//
// To prevent this we introduce variables that would shadow these
// constants and introduce compilation errors when used.
//
// target::kWordSize and target::ObjectAlignment give access to
// word size and object aligment offsets for the target.
//
// Similarly kHostWordSize gives access to the host word size.
class InvalidClass {};
extern InvalidClass kWordSize;
extern InvalidClass kWordSizeLog2;
extern InvalidClass kNewObjectAlignmentOffset;
extern InvalidClass kOldObjectAlignmentOffset;
extern InvalidClass kNewObjectBitPosition;
extern InvalidClass kObjectAlignment;
extern InvalidClass kObjectAlignmentLog2;
extern InvalidClass kObjectAlignmentMask;
static constexpr intptr_t kHostWordSize = dart::kWordSize;
static constexpr intptr_t kHostWordSizeLog2 = dart::kWordSizeLog2;
//
// Object handles.
//
// Create an empty handle.
Object& NewZoneHandle(Zone* zone);
// Clone the given handle.
Object& NewZoneHandle(Zone* zone, const Object&);
// Returns true if [a] and [b] are the same object.
bool IsSameObject(const Object& a, const Object& b);
// Returns true if the given handle is a zone handle or one of the global
// cached handles.
bool IsNotTemporaryScopedHandle(const Object& obj);
// Returns true if [obj] resides in old space.
bool IsInOldSpace(const Object& obj);
// Returns true if [obj] is not a Field/ICData clone.
//
// Used to assert that we are not embedding pointers to cloned objects that are
// used by background compiler into object pools / code.
bool IsOriginalObject(const Object& object);
// Clear the given handle.
void SetToNull(Object* obj);
// Helper functions to upcast handles.
//
// Note: compiler code cannot include object.h so it cannot see that Object is
// a superclass of Code or Function - thus we have to cast these pointers using
// reinterpret_cast.
inline const Object& ToObject(const Code& handle) {
return *reinterpret_cast<const Object*>(&handle);
}
inline const Object& ToObject(const Function& handle) {
return *reinterpret_cast<const Object*>(&handle);
}
// Returns some hash value for the given object.
//
// Note: the given hash value does not necessarily match Object.get:hashCode,
// or canonical hash.
intptr_t ObjectHash(const Object& obj);
// If the given object represents a Dart integer returns true and sets [value]
// to the value of the integer.
bool HasIntegerValue(const dart::Object& obj, int64_t* value);
// Creates a random cookie to be used for masking constants embedded in the
// generated code.
int32_t CreateJitCookie();
class RuntimeEntry : public ValueObject {
public:
virtual ~RuntimeEntry() {}
virtual void Call(compiler::Assembler* assembler,
intptr_t argument_count) const = 0;
};
// Allocate a string object with the given content in the runtime heap.
const String& AllocateString(const char* buffer);
DART_NORETURN void BailoutWithBranchOffsetError();
// compiler::target namespace contains information about the target platform:
//
// - word sizes and derived constants
// - offsets of fields
// - sizes of structures
namespace target {
// Currently we define target::word to match dart::word which represents
// host word.
//
// Once refactoring of the compiler is complete we will switch target::word
// to be independent from host word.
typedef dart::word word;
typedef dart::uword uword;
static constexpr word kWordSize = dart::kWordSize;
static constexpr word kWordSizeLog2 = dart::kWordSizeLog2;
static_assert((1 << kWordSizeLog2) == kWordSize,
"kWordSizeLog2 should match kWordSize");
using ObjectAlignment = dart::ObjectAlignment<kWordSize, kWordSizeLog2>;
// Information about frame_layout that compiler should be targeting.
extern FrameLayout frame_layout;
// Returns the FP-relative index where [variable] can be found (assumes
// [variable] is not captured), in bytes.
inline int FrameOffsetInBytesForVariable(const LocalVariable* variable) {
return frame_layout.FrameSlotForVariable(variable) * kWordSize;
}
// Encode tag word for a heap allocated object with the given class id and
// size.
//
// Note: even on 64-bit platforms we only use lower 32-bits of the tag word.
uint32_t MakeTagWordForNewSpaceObject(classid_t cid, uword instance_size);
//
// Target specific information about objects.
//
// Returns true if the given object can be represented as a Smi on the
// target platform.
bool IsSmi(const dart::Object& a);
// Return raw Smi representation of the given object for the target platform.
word ToRawSmi(const dart::Object& a);
// Return raw Smi representation of the given integer value for the target
// platform.
//
// Note: method assumes that caller has validated that value is representable
// as a Smi.
word ToRawSmi(intptr_t value);
// If the given object can be loaded from the thread on the target then
// return true and set offset (if provided) to the offset from the
// thread pointer to a field that contains the object.
bool CanLoadFromThread(const dart::Object& object, word* offset = nullptr);
// On IA32 we can embed raw pointers into generated code.
#if defined(TARGET_ARCH_IA32)
// Returns true if the pointer to the given object can be directly embedded
// into the generated code (because the object is immortal and immovable).
bool CanEmbedAsRawPointerInGeneratedCode(const dart::Object& obj);
// Returns raw pointer value for the given object. Should only be invoked
// if CanEmbedAsRawPointerInGeneratedCode returns true.
word ToRawPointer(const dart::Object& a);
#endif // defined(TARGET_ARCH_IA32)
//
// Target specific offsets and constants.
//
// Currently we use the same names for classes, constants and getters to make
// migration easier.
class RawObject : public AllStatic {
public:
static const word kClassIdTagPos;
static const word kClassIdTagSize;
static const word kBarrierOverlapShift;
};
class Object : public AllStatic {
public:
// Offset of the tags word.
static word tags_offset();
};
class ObjectPool : public AllStatic {
public:
// Return offset to the element with the given [index] in the object pool.
static intptr_t element_offset(intptr_t index);
};
class Class : public AllStatic {
public:
// Return class id of the given class on the target.
static classid_t GetId(const dart::Class& handle);
// Return instance size for the given class on the target.
static uword GetInstanceSize(const dart::Class& handle);
};
class Instance : public AllStatic {
public:
static word DataOffsetFor(intptr_t cid);
};
class Double : public AllStatic {
public:
static word value_offset();
};
class Float32x4 : public AllStatic {
public:
static word value_offset();
};
class Float64x2 : public AllStatic {
public:
static word value_offset();
};
class Thread : public AllStatic {
public:
static word top_offset();
static word end_offset();
static word isolate_offset();
static word call_to_runtime_entry_point_offset();
static word null_error_shared_with_fpu_regs_entry_point_offset();
static word null_error_shared_without_fpu_regs_entry_point_offset();
static word write_barrier_mask_offset();
static word monomorphic_miss_entry_offset();
static word write_barrier_wrappers_thread_offset(intptr_t regno);
static word array_write_barrier_entry_point_offset();
static word write_barrier_entry_point_offset();
static word vm_tag_offset();
#define THREAD_XMM_CONSTANT_LIST(V) \
V(float_not) \
V(float_negate) \
V(float_absolute) \
V(float_zerow) \
V(double_negate) \
V(double_abs)
#define DECLARE_CONSTANT_OFFSET_GETTER(name) \
static word name##_address_offset();
THREAD_XMM_CONSTANT_LIST(DECLARE_CONSTANT_OFFSET_GETTER)
#undef DECLARE_CONSTANT_OFFSET_GETTER
};
class Isolate : public AllStatic {
public:
static word class_table_offset();
};
class ClassTable : public AllStatic {
public:
static word table_offset();
#if !defined(PRODUCT)
static word ClassOffsetFor(intptr_t cid);
static word StateOffsetFor(intptr_t cid);
static word TableOffsetFor(intptr_t cid);
static word CounterOffsetFor(intptr_t cid, bool is_new);
static word SizeOffsetFor(intptr_t cid, bool is_new);
#endif // !defined(PRODUCT)
static const word kSizeOfClassPairLog2;
};
#if !defined(PRODUCT)
class ClassHeapStats : public AllStatic {
public:
static word TraceAllocationMask();
static word state_offset();
static word allocated_since_gc_new_space_offset();
static word allocated_size_since_gc_new_space_offset();
};
#endif // !defined(PRODUCT)
class Instructions : public AllStatic {
public:
static const intptr_t kPolymorphicEntryOffset;
static const intptr_t kMonomorphicEntryOffset;
static intptr_t HeaderSize();
};
class Code : public AllStatic {
public:
#if defined(TARGET_ARCH_IA32)
static uword EntryPointOf(const dart::Code& code);
#endif // defined(TARGET_ARCH_IA32)
static intptr_t object_pool_offset();
static intptr_t entry_point_offset(
CodeEntryKind kind = CodeEntryKind::kNormal);
static intptr_t saved_instructions_offset();
};
class Heap : public AllStatic {
public:
// Return true if an object with the given instance size is allocatable
// in new space on the target.
static bool IsAllocatableInNewSpace(intptr_t instance_size);
};
} // namespace target
} // namespace compiler
} // namespace dart
#endif // RUNTIME_VM_COMPILER_RUNTIME_API_H_