// Copyright (c) 2011, 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_STUB_CODE_H_ #define RUNTIME_VM_STUB_CODE_H_ #include #include "vm/allocation.h" #include "vm/compiler/runtime_api.h" #include "vm/object.h" #include "vm/stub_code_list.h" #if !defined(DART_PRECOMPILED_RUNTIME) #include "vm/compiler/assembler/assembler.h" #include "vm/compiler/stub_code_compiler.h" #endif // !defined(DART_PRECOMPILED_RUNTIME) namespace dart { // Forward declarations. class Code; class Isolate; class ObjectPointerVisitor; class Thread; // Is it permitted for the stubs above to refer to Object::null(), which is // allocated in the VM isolate and shared across all isolates. // However, in cases where a simple GC-safe placeholder is needed on the stack, // using Smi 0 instead of Object::null() is slightly more efficient, since a Smi // does not require relocation. // class StubCode is used to maintain the lifecycle of stubs. class StubCode : public AllStatic { public: // Generate all stubs which are shared across all isolates, this is done // only once and the stub code resides in the vm_isolate heap. static void Init(); static void Cleanup(); // Check if specified pc is in the dart invocation stub used for // transitioning into dart code. static bool InInvocationStub(Thread* T, uword pc, bool is_interpreted_frame = false); // Check if the specified pc is in the jump to frame stub. static bool InJumpToFrameStub(Thread* T, uword pc); // Returns nullptr if no stub found. static const char* NameOfStub(uword entry_point); // Callback is called for each stub until it returns false. static void ForEachStub( const std::function& callback); static constexpr const char* StubNames[] = { #define STUB_CODE_NAME(name) #name, VM_STUB_CODE_LIST(STUB_CODE_NAME) #undef STUB_CODE_NAME }; // Define the shared stub code accessors. #define STUB_CODE_ACCESSOR(name) \ static const Code& name() { return Roots::stub_handle(k##name##Index); } VM_STUB_CODE_LIST(STUB_CODE_ACCESSOR); #undef STUB_CODE_ACCESSOR #if !defined(DART_PRECOMPILED_RUNTIME) static const Code& SubtypeTestCacheStubForUsedInputs(intptr_t i) { switch (i) { case 1: return StubCode::Subtype1TestCache(); case 2: return StubCode::Subtype2TestCache(); case 3: return StubCode::Subtype3TestCache(); case 4: return StubCode::Subtype4TestCache(); case 6: return StubCode::Subtype6TestCache(); case 7: return StubCode::Subtype7TestCache(); default: UNREACHABLE(); return StubCode::Subtype7TestCache(); } } static CodePtr GetAllocationStubForClass(const Class& cls); static CodePtr GetAllocationStubForTypedData(classid_t class_id); #endif // !defined(DART_PRECOMPILED_RUNTIME) #if !defined(DART_PRECOMPILED_RUNTIME) // Generate the stub and finalize the generated code into the stub // code executable area. static CodePtr Generate(const char* name, compiler::ObjectPoolBuilder* object_pool_builder, void (compiler::StubCodeCompiler::*GenerateStub)()); #endif // !defined(DART_PRECOMPILED_RUNTIME) static const Code& UnoptimizedStaticCallEntry(intptr_t num_args_tested); static const char* NameAt(intptr_t index) { return StubNames[index]; } static const Code& EntryAt(intptr_t index) { return Roots::stub_handle(index); } static void EntryAtPut(intptr_t index, CodePtr code) { Roots::stub_handle(index).initRO(code); } static intptr_t NumEntries() { return kNumStubEntries; } private: friend class MegamorphicCacheTable; enum { #define STUB_CODE_ENTRY(name) k##name##Index, VM_STUB_CODE_LIST(STUB_CODE_ENTRY) #undef STUB_CODE_ENTRY kNumStubEntries }; }; } // namespace dart #endif // RUNTIME_VM_STUB_CODE_H_