| // 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 VM_STUB_CODE_H_ |
| #define VM_STUB_CODE_H_ |
| |
| #include "vm/allocation.h" |
| #include "vm/assembler.h" |
| |
| namespace dart { |
| |
| // Forward declarations. |
| class Code; |
| class Isolate; |
| class ObjectPointerVisitor; |
| class RawCode; |
| |
| |
| // List of stubs created in the VM isolate, these stubs are shared by different |
| // isolates running in this dart process. |
| #define VM_STUB_CODE_LIST(V) \ |
| V(CallToRuntime) \ |
| V(PrintStopMessage) \ |
| V(CallNativeCFunction) \ |
| V(AllocateArray) \ |
| V(CallNoSuchMethodFunction) \ |
| V(InstanceFunctionLookup) \ |
| V(CallStaticFunction) \ |
| V(CallClosureFunction) \ |
| V(FixCallersTarget) \ |
| V(Deoptimize) \ |
| V(DeoptimizeLazy) \ |
| V(BreakpointStatic) \ |
| V(BreakpointReturn) \ |
| V(Subtype1TestCache) \ |
| V(Subtype2TestCache) \ |
| V(Subtype3TestCache) \ |
| V(GetStackPointer) \ |
| V(JumpToExceptionHandler) \ |
| V(IdenticalWithNumberCheck) \ |
| |
| // 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. |
| |
| // List of stubs created per isolate, these stubs could potentially contain |
| // embedded objects and hence cannot be shared across isolates. |
| #define STUB_CODE_LIST(V) \ |
| V(InvokeDartCode) \ |
| V(AllocateContext) \ |
| V(UpdateStoreBuffer) \ |
| V(OneArgCheckInlineCache) \ |
| V(TwoArgsCheckInlineCache) \ |
| V(ThreeArgsCheckInlineCache) \ |
| V(OneArgOptimizedCheckInlineCache) \ |
| V(TwoArgsOptimizedCheckInlineCache) \ |
| V(ThreeArgsOptimizedCheckInlineCache) \ |
| V(ClosureCallInlineCache) \ |
| V(MegamorphicCall) \ |
| V(OptimizeFunction) \ |
| V(BreakpointDynamic) \ |
| V(EqualityWithNullArg) \ |
| |
| // class StubEntry is used to describe stub methods generated in dart to |
| // abstract out common code executed from generated dart code. |
| class StubEntry { |
| public: |
| StubEntry(const char* name, const Code& code); |
| ~StubEntry() {} |
| |
| const ExternalLabel& label() const { return label_; } |
| uword EntryPoint() const { return entry_point_; } |
| intptr_t Size() const { return size_; } |
| |
| // Visit all object pointers. |
| void VisitObjectPointers(ObjectPointerVisitor* visitor); |
| |
| private: |
| RawCode* code_; |
| uword entry_point_; |
| intptr_t size_; |
| ExternalLabel label_; |
| |
| DISALLOW_COPY_AND_ASSIGN(StubEntry); |
| }; |
| |
| |
| // class StubCode is used to maintain the lifecycle of stubs. |
| class StubCode { |
| public: |
| StubCode() |
| : |
| #define STUB_CODE_INITIALIZER(name) \ |
| name##_entry_(NULL), |
| STUB_CODE_LIST(STUB_CODE_INITIALIZER) |
| dummy_(NULL) {} |
| ~StubCode(); |
| |
| void GenerateFor(Isolate* isolate); |
| |
| // 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 InitOnce(); |
| |
| // Generate all stubs which are generated on a per isolate basis as they |
| // have embedded objects which are isolate specific. |
| static void Init(Isolate* isolate); |
| |
| static void VisitObjectPointers(ObjectPointerVisitor* visitor); |
| |
| // Check if specified pc is in the dart invocation stub used for |
| // transitioning into dart code. |
| static bool InInvocationStub(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 StubEntry* name##_entry() { \ |
| return name##_entry_; \ |
| } \ |
| static const ExternalLabel& name##Label() { \ |
| return name##_entry()->label(); \ |
| } \ |
| static uword name##EntryPoint() { \ |
| return name##_entry()->EntryPoint(); \ |
| } \ |
| static intptr_t name##Size() { \ |
| return name##_entry()->Size(); \ |
| } |
| VM_STUB_CODE_LIST(STUB_CODE_ACCESSOR); |
| #undef STUB_CODE_ACCESSOR |
| |
| // Define the per-isolate stub code accessors. |
| #define STUB_CODE_ACCESSOR(name) \ |
| static StubEntry* name##_entry() { \ |
| return Isolate::Current()->stub_code()->name##_entry_; \ |
| } \ |
| static const ExternalLabel& name##Label() { \ |
| return name##_entry()->label(); \ |
| } \ |
| static uword name##EntryPoint() { \ |
| return name##_entry()->EntryPoint(); \ |
| } \ |
| static intptr_t name##Size() { \ |
| return name##_entry()->Size(); \ |
| } |
| STUB_CODE_LIST(STUB_CODE_ACCESSOR); |
| #undef STUB_CODE_ACCESSOR |
| |
| static RawCode* GetAllocationStubForClass(const Class& cls); |
| static RawCode* GetAllocationStubForClosure(const Function& func); |
| |
| static const intptr_t kNoInstantiator = 0; |
| |
| private: |
| friend class MegamorphicCacheTable; |
| |
| static const intptr_t kStubCodeSize = 4 * KB; |
| |
| #define STUB_CODE_GENERATE(name) \ |
| static void Generate##name##Stub(Assembler* assembler); |
| VM_STUB_CODE_LIST(STUB_CODE_GENERATE); |
| STUB_CODE_LIST(STUB_CODE_GENERATE); |
| #undef STUB_CODE_GENERATE |
| |
| #define STUB_CODE_ENTRY(name) \ |
| static StubEntry* name##_entry_; |
| VM_STUB_CODE_LIST(STUB_CODE_ENTRY); |
| #undef STUB_CODE_ENTRY |
| |
| #define STUB_CODE_ENTRY(name) \ |
| StubEntry* name##_entry_; |
| STUB_CODE_LIST(STUB_CODE_ENTRY); |
| #undef STUB_CODE_ENTRY |
| // This dummy field is needed so that we can intialize the stubs from a macro. |
| void* dummy_; |
| |
| // Generate the stub and finalize the generated code into the stub |
| // code executable area. |
| static RawCode* Generate(const char* name, |
| void (*GenerateStub)(Assembler* assembler)); |
| |
| static void GenerateMegamorphicMissStub(Assembler* assembler); |
| static void GenerateAllocationStubForClass(Assembler* assembler, |
| const Class& cls); |
| static void GenerateAllocationStubForClosure(Assembler* assembler, |
| const Function& func); |
| static void GenerateNArgsCheckInlineCacheStub(Assembler* assembler, |
| intptr_t num_args); |
| static void GenerateUsageCounterIncrement(Assembler* assembler, |
| Register temp_reg); |
| static void GenerateOptimizedUsageCounterIncrement(Assembler* assembler); |
| }; |
| |
| } // namespace dart |
| |
| #endif // VM_STUB_CODE_H_ |