1// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#ifndef RUNTIME_VM_STUB_CODE_H_
6#define RUNTIME_VM_STUB_CODE_H_
7
8#include "vm/allocation.h"
9#include "vm/compiler/runtime_api.h"
10#include "vm/object.h"
11#include "vm/stub_code_list.h"
12
13#if !defined(DART_PRECOMPILED_RUNTIME)
14#include "vm/compiler/assembler/assembler.h"
15#include "vm/compiler/stub_code_compiler.h"
16#endif // !defined(DART_PRECOMPILED_RUNTIME)
17
18namespace dart {
19
20// Forward declarations.
21class Code;
22class Isolate;
23class ObjectPointerVisitor;
24
25// Is it permitted for the stubs above to refer to Object::null(), which is
26// allocated in the VM isolate and shared across all isolates.
27// However, in cases where a simple GC-safe placeholder is needed on the stack,
28// using Smi 0 instead of Object::null() is slightly more efficient, since a Smi
29// does not require relocation.
30
31// class StubCode is used to maintain the lifecycle of stubs.
32class StubCode : public AllStatic {
33 public:
34 // Generate all stubs which are shared across all isolates, this is done
35 // only once and the stub code resides in the vm_isolate heap.
36 static void Init();
37
38 static void Cleanup();
39
40 // Returns true if stub code has been initialized.
41 static bool HasBeenInitialized() {
42 return initialized_.load(order: std::memory_order_acquire);
43 }
44 static void InitializationDone() {
45 initialized_.store(arg: true, order: std::memory_order_release);
46 }
47
48 // Check if specified pc is in the dart invocation stub used for
49 // transitioning into dart code.
50 static bool InInvocationStub(uword pc);
51
52 // Check if the specified pc is in the jump to frame stub.
53 static bool InJumpToFrameStub(uword pc);
54
55 // Returns nullptr if no stub found.
56 static const char* NameOfStub(uword entry_point);
57
58// Define the shared stub code accessors.
59#define STUB_CODE_ACCESSOR(name) \
60 static const Code& name() { return *entries_[k##name##Index].code; } \
61 static intptr_t name##Size() { return name().Size(); }
62 VM_STUB_CODE_LIST(STUB_CODE_ACCESSOR);
63#undef STUB_CODE_ACCESSOR
64
65#if !defined(DART_PRECOMPILED_RUNTIME)
66 static const Code& SubtypeTestCacheStubForUsedInputs(intptr_t i) {
67 switch (i) {
68 case 1:
69 return StubCode::Subtype1TestCache();
70 case 2:
71 return StubCode::Subtype2TestCache();
72 case 3:
73 return StubCode::Subtype3TestCache();
74 case 4:
75 return StubCode::Subtype4TestCache();
76 case 6:
77 return StubCode::Subtype6TestCache();
78 case 7:
79 return StubCode::Subtype7TestCache();
80 default:
81 UNREACHABLE();
82 return StubCode::Subtype7TestCache();
83 }
84 }
85 static CodePtr GetAllocationStubForClass(const Class& cls);
86 static CodePtr GetAllocationStubForTypedData(classid_t class_id);
87#endif // !defined(DART_PRECOMPILED_RUNTIME)
88
89#if !defined(TARGET_ARCH_IA32)
90 static CodePtr GetBuildGenericMethodExtractorStub(
91 compiler::ObjectPoolBuilder* pool) {
92 return GetBuildMethodExtractorStub(pool, /*generic=*/generic: true);
93 }
94 static CodePtr GetBuildNonGenericMethodExtractorStub(
95 compiler::ObjectPoolBuilder* pool) {
96 return GetBuildMethodExtractorStub(pool, /*generic=*/generic: false);
97 }
98#endif
99
100#if !defined(DART_PRECOMPILED_RUNTIME)
101 // Generate the stub and finalize the generated code into the stub
102 // code executable area.
103 static CodePtr Generate(const char* name,
104 compiler::ObjectPoolBuilder* object_pool_builder,
105 void (compiler::StubCodeCompiler::*GenerateStub)());
106#endif // !defined(DART_PRECOMPILED_RUNTIME)
107
108 static const Code& UnoptimizedStaticCallEntry(intptr_t num_args_tested);
109
110 static const char* NameAt(intptr_t index) { return entries_[index].name; }
111
112 static const Code& EntryAt(intptr_t index) { return *(entries_[index].code); }
113 static void EntryAtPut(intptr_t index, Code* entry) {
114 DEBUG_ASSERT(entry->IsReadOnlyHandle());
115 ASSERT(entries_[index].code == nullptr);
116 entries_[index].code = entry;
117 }
118 static intptr_t NumEntries() { return kNumStubEntries; }
119
120#if !defined(DART_PRECOMPILED_RUNTIME)
121#define GENERATE_STUB(name) \
122 static CodePtr BuildIsolateSpecific##name##Stub( \
123 compiler::ObjectPoolBuilder* opw) { \
124 return StubCode::Generate( \
125 "_iso_stub_" #name, opw, \
126 &compiler::StubCodeCompiler::Generate##name##Stub); \
127 }
128 VM_STUB_CODE_LIST(GENERATE_STUB);
129#undef GENERATE_STUB
130#endif // !defined(DART_PRECOMPILED_RUNTIME)
131
132 private:
133 friend class MegamorphicCacheTable;
134
135 static CodePtr GetBuildMethodExtractorStub(compiler::ObjectPoolBuilder* pool,
136 bool generic);
137
138 enum {
139#define STUB_CODE_ENTRY(name) k##name##Index,
140 VM_STUB_CODE_LIST(STUB_CODE_ENTRY)
141#undef STUB_CODE_ENTRY
142 kNumStubEntries
143 };
144
145 struct StubCodeEntry {
146 Code* code;
147 const char* name;
148#if !defined(DART_PRECOMPILED_RUNTIME)
149 void (compiler::StubCodeCompiler::*generator)();
150#endif
151 };
152 static StubCodeEntry entries_[kNumStubEntries];
153 static AcqRelAtomic<bool> initialized_;
154};
155
156} // namespace dart
157
158#endif // RUNTIME_VM_STUB_CODE_H_
159

source code of flutter_engine/third_party/dart/runtime/vm/stub_code.h