| 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 |