|  | // 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 "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 SnapshotReader; | 
|  | class SnapshotWriter; | 
|  |  | 
|  | DECLARE_FLAG(bool, disassemble_stubs); | 
|  |  | 
|  | // 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(); | 
|  |  | 
|  | // Returns true if stub code has been initialized. | 
|  | static bool HasBeenInitialized() { | 
|  | return initialized_.load(std::memory_order_acquire); | 
|  | } | 
|  | static void InitializationDone() { | 
|  | initialized_.store(true, std::memory_order_release); | 
|  | } | 
|  |  | 
|  | // Check if specified pc is in the dart invocation stub used for | 
|  | // transitioning into dart code. | 
|  | static bool InInvocationStub(uword pc); | 
|  |  | 
|  | // Check if the specified pc is in the jump to frame stub. | 
|  | static bool InJumpToFrameStub(uword pc); | 
|  |  | 
|  | // Returns NULL if no stub found. | 
|  | static const char* NameOfStub(uword entry_point); | 
|  |  | 
|  | // Define the shared stub code accessors. | 
|  | #define STUB_CODE_ACCESSOR(name)                                               \ | 
|  | static const Code& name() { return *entries_[k##name##Index].code; }         \ | 
|  | static intptr_t name##Size() { return name().Size(); } | 
|  | VM_STUB_CODE_LIST(STUB_CODE_ACCESSOR); | 
|  | #undef STUB_CODE_ACCESSOR | 
|  |  | 
|  | #if !defined(DART_PRECOMPILED_RUNTIME) | 
|  | static CodePtr GetAllocationStubForClass(const Class& cls); | 
|  | static CodePtr GetAllocationStubForTypedData(classid_t class_id); | 
|  | #endif  // !defined(DART_PRECOMPILED_RUNTIME) | 
|  |  | 
|  | #if !defined(TARGET_ARCH_IA32) | 
|  | static CodePtr GetBuildGenericMethodExtractorStub( | 
|  | compiler::ObjectPoolBuilder* pool) { | 
|  | return GetBuildMethodExtractorStub(pool, /*generic=*/true); | 
|  | } | 
|  | static CodePtr GetBuildNonGenericMethodExtractorStub( | 
|  | compiler::ObjectPoolBuilder* pool) { | 
|  | return GetBuildMethodExtractorStub(pool, /*generic=*/false); | 
|  | } | 
|  | #endif | 
|  |  | 
|  | #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 (*GenerateStub)(compiler::Assembler* assembler)); | 
|  | #endif  // !defined(DART_PRECOMPILED_RUNTIME) | 
|  |  | 
|  | static const Code& UnoptimizedStaticCallEntry(intptr_t num_args_tested); | 
|  |  | 
|  | static const char* NameAt(intptr_t index) { return entries_[index].name; } | 
|  |  | 
|  | static const Code& EntryAt(intptr_t index) { return *(entries_[index].code); } | 
|  | static void EntryAtPut(intptr_t index, Code* entry) { | 
|  | ASSERT(entry->IsReadOnlyHandle()); | 
|  | ASSERT(entries_[index].code == nullptr); | 
|  | entries_[index].code = entry; | 
|  | } | 
|  | static intptr_t NumEntries() { return kNumStubEntries; } | 
|  |  | 
|  | #if !defined(DART_PRECOMPILED_RUNTIME) | 
|  | #define GENERATE_STUB(name)                                                    \ | 
|  | static CodePtr BuildIsolateSpecific##name##Stub(                             \ | 
|  | compiler::ObjectPoolBuilder* opw) {                                      \ | 
|  | return StubCode::Generate(                                                 \ | 
|  | "_iso_stub_" #name, opw,                                               \ | 
|  | compiler::StubCodeCompiler::Generate##name##Stub);                     \ | 
|  | } | 
|  | VM_STUB_CODE_LIST(GENERATE_STUB); | 
|  | #undef GENERATE_STUB | 
|  | #endif  // !defined(DART_PRECOMPILED_RUNTIME) | 
|  |  | 
|  | private: | 
|  | friend class MegamorphicCacheTable; | 
|  |  | 
|  | static CodePtr GetBuildMethodExtractorStub(compiler::ObjectPoolBuilder* pool, | 
|  | bool generic); | 
|  |  | 
|  | enum { | 
|  | #define STUB_CODE_ENTRY(name) k##name##Index, | 
|  | VM_STUB_CODE_LIST(STUB_CODE_ENTRY) | 
|  | #undef STUB_CODE_ENTRY | 
|  | kNumStubEntries | 
|  | }; | 
|  |  | 
|  | struct StubCodeEntry { | 
|  | Code* code; | 
|  | const char* name; | 
|  | #if !defined(DART_PRECOMPILED_RUNTIME) | 
|  | void (*generator)(compiler::Assembler* assembler); | 
|  | #endif | 
|  | }; | 
|  | static StubCodeEntry entries_[kNumStubEntries]; | 
|  | static AcqRelAtomic<bool> initialized_; | 
|  | }; | 
|  |  | 
|  | }  // namespace dart | 
|  |  | 
|  | #endif  // RUNTIME_VM_STUB_CODE_H_ |