OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/stub_code.h" | 5 #include "vm/stub_code.h" |
6 | 6 |
7 #include "platform/assert.h" | 7 #include "platform/assert.h" |
8 #include "platform/globals.h" | 8 #include "platform/globals.h" |
9 #include "vm/assembler.h" | 9 #include "vm/assembler.h" |
| 10 #include "vm/clustered_snapshot.h" |
10 #include "vm/disassembler.h" | 11 #include "vm/disassembler.h" |
11 #include "vm/flags.h" | 12 #include "vm/flags.h" |
12 #include "vm/object_store.h" | 13 #include "vm/object_store.h" |
13 #include "vm/safepoint.h" | 14 #include "vm/safepoint.h" |
14 #include "vm/snapshot.h" | 15 #include "vm/snapshot.h" |
15 #include "vm/virtual_memory.h" | 16 #include "vm/virtual_memory.h" |
16 #include "vm/visitor.h" | 17 #include "vm/visitor.h" |
17 #include "vm/clustered_snapshot.h" | |
18 | 18 |
19 namespace dart { | 19 namespace dart { |
20 | 20 |
21 DEFINE_FLAG(bool, disassemble_stubs, false, "Disassemble generated stubs."); | 21 DEFINE_FLAG(bool, disassemble_stubs, false, "Disassemble generated stubs."); |
22 | 22 |
23 StubEntry* StubCode::entries_[kNumStubEntries] = { | 23 StubEntry* StubCode::entries_[kNumStubEntries] = { |
24 #define STUB_CODE_DECLARE(name) NULL, | 24 #define STUB_CODE_DECLARE(name) NULL, |
25 VM_STUB_CODE_LIST(STUB_CODE_DECLARE) | 25 VM_STUB_CODE_LIST(STUB_CODE_DECLARE) |
26 #undef STUB_CODE_DECLARE | 26 #undef STUB_CODE_DECLARE |
27 }; | 27 }; |
28 | 28 |
29 | |
30 StubEntry::StubEntry(const Code& code) | 29 StubEntry::StubEntry(const Code& code) |
31 : code_(code.raw()), | 30 : code_(code.raw()), |
32 entry_point_(code.UncheckedEntryPoint()), | 31 entry_point_(code.UncheckedEntryPoint()), |
33 checked_entry_point_(code.CheckedEntryPoint()), | 32 checked_entry_point_(code.CheckedEntryPoint()), |
34 size_(code.Size()), | 33 size_(code.Size()), |
35 label_(code.UncheckedEntryPoint()) {} | 34 label_(code.UncheckedEntryPoint()) {} |
36 | 35 |
37 | |
38 // Visit all object pointers. | 36 // Visit all object pointers. |
39 void StubEntry::VisitObjectPointers(ObjectPointerVisitor* visitor) { | 37 void StubEntry::VisitObjectPointers(ObjectPointerVisitor* visitor) { |
40 ASSERT(visitor != NULL); | 38 ASSERT(visitor != NULL); |
41 visitor->VisitPointer(reinterpret_cast<RawObject**>(&code_)); | 39 visitor->VisitPointer(reinterpret_cast<RawObject**>(&code_)); |
42 } | 40 } |
43 | 41 |
44 | |
45 #define STUB_CODE_GENERATE(name) \ | 42 #define STUB_CODE_GENERATE(name) \ |
46 code ^= Generate("_stub_" #name, StubCode::Generate##name##Stub); \ | 43 code ^= Generate("_stub_" #name, StubCode::Generate##name##Stub); \ |
47 entries_[k##name##Index] = new StubEntry(code); | 44 entries_[k##name##Index] = new StubEntry(code); |
48 | 45 |
49 | |
50 void StubCode::InitOnce() { | 46 void StubCode::InitOnce() { |
51 #if defined(DART_PRECOMPILED_RUNTIME) | 47 #if defined(DART_PRECOMPILED_RUNTIME) |
52 // Stubs will be loaded from the snapshot. | 48 // Stubs will be loaded from the snapshot. |
53 UNREACHABLE(); | 49 UNREACHABLE(); |
54 #else | 50 #else |
55 // Generate all the stubs. | 51 // Generate all the stubs. |
56 Code& code = Code::Handle(); | 52 Code& code = Code::Handle(); |
57 VM_STUB_CODE_LIST(STUB_CODE_GENERATE); | 53 VM_STUB_CODE_LIST(STUB_CODE_GENERATE); |
58 #endif // DART_PRECOMPILED_RUNTIME | 54 #endif // DART_PRECOMPILED_RUNTIME |
59 } | 55 } |
60 | 56 |
61 | |
62 #undef STUB_CODE_GENERATE | 57 #undef STUB_CODE_GENERATE |
63 | 58 |
64 | |
65 void StubCode::Init(Isolate* isolate) {} | 59 void StubCode::Init(Isolate* isolate) {} |
66 | 60 |
67 | |
68 void StubCode::VisitObjectPointers(ObjectPointerVisitor* visitor) {} | 61 void StubCode::VisitObjectPointers(ObjectPointerVisitor* visitor) {} |
69 | 62 |
70 | |
71 bool StubCode::HasBeenInitialized() { | 63 bool StubCode::HasBeenInitialized() { |
72 #if !defined(TARGET_ARCH_DBC) | 64 #if !defined(TARGET_ARCH_DBC) |
73 // Use JumpToHandler and InvokeDart as canaries. | 65 // Use JumpToHandler and InvokeDart as canaries. |
74 const StubEntry* entry_1 = StubCode::JumpToFrame_entry(); | 66 const StubEntry* entry_1 = StubCode::JumpToFrame_entry(); |
75 const StubEntry* entry_2 = StubCode::InvokeDartCode_entry(); | 67 const StubEntry* entry_2 = StubCode::InvokeDartCode_entry(); |
76 return (entry_1 != NULL) && (entry_2 != NULL); | 68 return (entry_1 != NULL) && (entry_2 != NULL); |
77 #else | 69 #else |
78 return true; | 70 return true; |
79 #endif | 71 #endif |
80 } | 72 } |
81 | 73 |
82 | |
83 bool StubCode::InInvocationStub(uword pc) { | 74 bool StubCode::InInvocationStub(uword pc) { |
84 #if !defined(TARGET_ARCH_DBC) | 75 #if !defined(TARGET_ARCH_DBC) |
85 ASSERT(HasBeenInitialized()); | 76 ASSERT(HasBeenInitialized()); |
86 uword entry = StubCode::InvokeDartCode_entry()->EntryPoint(); | 77 uword entry = StubCode::InvokeDartCode_entry()->EntryPoint(); |
87 uword size = StubCode::InvokeDartCodeSize(); | 78 uword size = StubCode::InvokeDartCodeSize(); |
88 return (pc >= entry) && (pc < (entry + size)); | 79 return (pc >= entry) && (pc < (entry + size)); |
89 #else | 80 #else |
90 // On DBC we use a special marker PC to signify entry frame because there is | 81 // On DBC we use a special marker PC to signify entry frame because there is |
91 // no such thing as invocation stub. | 82 // no such thing as invocation stub. |
92 return (pc & 2) != 0; | 83 return (pc & 2) != 0; |
93 #endif | 84 #endif |
94 } | 85 } |
95 | 86 |
96 | |
97 bool StubCode::InJumpToFrameStub(uword pc) { | 87 bool StubCode::InJumpToFrameStub(uword pc) { |
98 #if !defined(TARGET_ARCH_DBC) | 88 #if !defined(TARGET_ARCH_DBC) |
99 ASSERT(HasBeenInitialized()); | 89 ASSERT(HasBeenInitialized()); |
100 uword entry = StubCode::JumpToFrame_entry()->EntryPoint(); | 90 uword entry = StubCode::JumpToFrame_entry()->EntryPoint(); |
101 uword size = StubCode::JumpToFrameSize(); | 91 uword size = StubCode::JumpToFrameSize(); |
102 return (pc >= entry) && (pc < (entry + size)); | 92 return (pc >= entry) && (pc < (entry + size)); |
103 #else | 93 #else |
104 // This stub does not exist on DBC. | 94 // This stub does not exist on DBC. |
105 return false; | 95 return false; |
106 #endif | 96 #endif |
107 } | 97 } |
108 | 98 |
109 | |
110 RawCode* StubCode::GetAllocationStubForClass(const Class& cls) { | 99 RawCode* StubCode::GetAllocationStubForClass(const Class& cls) { |
111 // These stubs are not used by DBC. | 100 // These stubs are not used by DBC. |
112 #if !defined(TARGET_ARCH_DBC) | 101 #if !defined(TARGET_ARCH_DBC) |
113 Thread* thread = Thread::Current(); | 102 Thread* thread = Thread::Current(); |
114 Zone* zone = thread->zone(); | 103 Zone* zone = thread->zone(); |
115 const Error& error = Error::Handle(zone, cls.EnsureIsFinalized(thread)); | 104 const Error& error = Error::Handle(zone, cls.EnsureIsFinalized(thread)); |
116 ASSERT(error.IsNull()); | 105 ASSERT(error.IsNull()); |
117 if (cls.id() == kArrayCid) { | 106 if (cls.id() == kArrayCid) { |
118 return AllocateArray_entry()->code(); | 107 return AllocateArray_entry()->code(); |
119 } | 108 } |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
168 object_pool.DebugPrint(); | 157 object_pool.DebugPrint(); |
169 } | 158 } |
170 #endif // !PRODUCT | 159 #endif // !PRODUCT |
171 } | 160 } |
172 return stub.raw(); | 161 return stub.raw(); |
173 #endif // !DBC | 162 #endif // !DBC |
174 UNIMPLEMENTED(); | 163 UNIMPLEMENTED(); |
175 return Code::null(); | 164 return Code::null(); |
176 } | 165 } |
177 | 166 |
178 | |
179 const StubEntry* StubCode::UnoptimizedStaticCallEntry( | 167 const StubEntry* StubCode::UnoptimizedStaticCallEntry( |
180 intptr_t num_args_tested) { | 168 intptr_t num_args_tested) { |
181 // These stubs are not used by DBC. | 169 // These stubs are not used by DBC. |
182 #if !defined(TARGET_ARCH_DBC) | 170 #if !defined(TARGET_ARCH_DBC) |
183 switch (num_args_tested) { | 171 switch (num_args_tested) { |
184 case 0: | 172 case 0: |
185 return ZeroArgsUnoptimizedStaticCall_entry(); | 173 return ZeroArgsUnoptimizedStaticCall_entry(); |
186 case 1: | 174 case 1: |
187 return OneArgUnoptimizedStaticCall_entry(); | 175 return OneArgUnoptimizedStaticCall_entry(); |
188 case 2: | 176 case 2: |
189 return TwoArgsUnoptimizedStaticCall_entry(); | 177 return TwoArgsUnoptimizedStaticCall_entry(); |
190 default: | 178 default: |
191 UNIMPLEMENTED(); | 179 UNIMPLEMENTED(); |
192 return NULL; | 180 return NULL; |
193 } | 181 } |
194 #else | 182 #else |
195 return NULL; | 183 return NULL; |
196 #endif | 184 #endif |
197 } | 185 } |
198 | 186 |
199 | |
200 RawCode* StubCode::Generate(const char* name, | 187 RawCode* StubCode::Generate(const char* name, |
201 void (*GenerateStub)(Assembler* assembler)) { | 188 void (*GenerateStub)(Assembler* assembler)) { |
202 Assembler assembler; | 189 Assembler assembler; |
203 GenerateStub(&assembler); | 190 GenerateStub(&assembler); |
204 const Code& code = | 191 const Code& code = |
205 Code::Handle(Code::FinalizeCode(name, &assembler, false /* optimized */)); | 192 Code::Handle(Code::FinalizeCode(name, &assembler, false /* optimized */)); |
206 #ifndef PRODUCT | 193 #ifndef PRODUCT |
207 if (FLAG_support_disassembler && FLAG_disassemble_stubs) { | 194 if (FLAG_support_disassembler && FLAG_disassemble_stubs) { |
208 LogBlock lb; | 195 LogBlock lb; |
209 THR_Print("Code for stub '%s': {\n", name); | 196 THR_Print("Code for stub '%s': {\n", name); |
210 DisassembleToStdout formatter; | 197 DisassembleToStdout formatter; |
211 code.Disassemble(&formatter); | 198 code.Disassemble(&formatter); |
212 THR_Print("}\n"); | 199 THR_Print("}\n"); |
213 const ObjectPool& object_pool = ObjectPool::Handle(code.object_pool()); | 200 const ObjectPool& object_pool = ObjectPool::Handle(code.object_pool()); |
214 object_pool.DebugPrint(); | 201 object_pool.DebugPrint(); |
215 } | 202 } |
216 #endif // !PRODUCT | 203 #endif // !PRODUCT |
217 return code.raw(); | 204 return code.raw(); |
218 } | 205 } |
219 | 206 |
220 | |
221 const char* StubCode::NameOfStub(uword entry_point) { | 207 const char* StubCode::NameOfStub(uword entry_point) { |
222 #define VM_STUB_CODE_TESTER(name) \ | 208 #define VM_STUB_CODE_TESTER(name) \ |
223 if ((name##_entry() != NULL) && \ | 209 if ((name##_entry() != NULL) && \ |
224 (entry_point == name##_entry()->EntryPoint())) { \ | 210 (entry_point == name##_entry()->EntryPoint())) { \ |
225 return "" #name; \ | 211 return "" #name; \ |
226 } | 212 } |
227 VM_STUB_CODE_LIST(VM_STUB_CODE_TESTER); | 213 VM_STUB_CODE_LIST(VM_STUB_CODE_TESTER); |
228 #undef VM_STUB_CODE_TESTER | 214 #undef VM_STUB_CODE_TESTER |
229 return NULL; | 215 return NULL; |
230 } | 216 } |
231 | 217 |
232 } // namespace dart | 218 } // namespace dart |
OLD | NEW |