• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2020 Google LLC
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "src/sksl/SkSLThreadContext.h"
9 
10 #include "include/private/SkSLProgramElement.h"
11 #include "include/sksl/SkSLPosition.h"
12 #include "src/sksl/SkSLCompiler.h"
13 #include "src/sksl/SkSLModifiersPool.h"
14 #include "src/sksl/SkSLPool.h"
15 #include "src/sksl/ir/SkSLSymbolTable.h"
16 
17 #include <type_traits>
18 
19 namespace SkSL {
20 
ThreadContext(SkSL::Compiler * compiler,SkSL::ProgramKind kind,const SkSL::ProgramSettings & settings,const SkSL::Module * module,bool isModule)21 ThreadContext::ThreadContext(SkSL::Compiler* compiler,
22                              SkSL::ProgramKind kind,
23                              const SkSL::ProgramSettings& settings,
24                              const SkSL::Module* module,
25                              bool isModule)
26         : fCompiler(compiler)
27         , fOldConfig(fCompiler->fContext->fConfig)
28         , fOldModifiersPool(fCompiler->fContext->fModifiersPool)
29         , fOldErrorReporter(*fCompiler->fContext->fErrors)
30         , fSettings(settings) {
31     if (!isModule) {
32         if (settings.fUseMemoryPool) {
33             fPool = Pool::Create();
34             fPool->attachToThread();
35         }
36         fModifiersPool = std::make_unique<SkSL::ModifiersPool>();
37         fCompiler->fContext->fModifiersPool = fModifiersPool.get();
38     }
39 
40     fConfig = std::make_unique<SkSL::ProgramConfig>();
41     fConfig->fKind = kind;
42     fConfig->fSettings = settings;
43     fConfig->fIsBuiltinCode = isModule;
44     fCompiler->fContext->fConfig = fConfig.get();
45     fCompiler->fContext->fErrors = &fDefaultErrorReporter;
46     fCompiler->fContext->fModule = module;
47     fCompiler->fSymbolTable = module->fSymbols;
48     this->setupSymbolTable();
49 }
50 
~ThreadContext()51 ThreadContext::~ThreadContext() {
52     if (SymbolTable()) {
53         fCompiler->fSymbolTable = nullptr;
54         fProgramElements.clear();
55     } else {
56         // We should only be here with a null symbol table if ReleaseProgram was called
57         SkASSERT(fProgramElements.empty());
58     }
59     fCompiler->fContext->fErrors = &fOldErrorReporter;
60     fCompiler->fContext->fConfig = fOldConfig;
61     fCompiler->fContext->fModifiersPool = fOldModifiersPool;
62     if (fPool) {
63         fPool->detachFromThread();
64     }
65 }
66 
setupSymbolTable()67 void ThreadContext::setupSymbolTable() {
68     SkSL::Context& context = *fCompiler->fContext;
69     SymbolTable::Push(&fCompiler->fSymbolTable, context.fConfig->fIsBuiltinCode);
70 
71     SkSL::SymbolTable& symbolTable = *fCompiler->fSymbolTable;
72     symbolTable.markModuleBoundary();
73 }
74 
Context()75 SkSL::Context& ThreadContext::Context() {
76     return Compiler().context();
77 }
78 
Settings()79 const SkSL::ProgramSettings& ThreadContext::Settings() {
80     return Context().fConfig->fSettings;
81 }
82 
SymbolTable()83 std::shared_ptr<SkSL::SymbolTable>& ThreadContext::SymbolTable() {
84     return Compiler().fSymbolTable;
85 }
86 
Modifiers(const SkSL::Modifiers & modifiers)87 const SkSL::Modifiers* ThreadContext::Modifiers(const SkSL::Modifiers& modifiers) {
88     return Context().fModifiersPool->add(modifiers);
89 }
90 
RTAdjustState()91 ThreadContext::RTAdjustData& ThreadContext::RTAdjustState() {
92     return Instance().fRTAdjust;
93 }
94 
SetErrorReporter(ErrorReporter * errorReporter)95 void ThreadContext::SetErrorReporter(ErrorReporter* errorReporter) {
96     SkASSERT(errorReporter);
97     Context().fErrors = errorReporter;
98 }
99 
ReportError(std::string_view msg,Position pos)100 void ThreadContext::ReportError(std::string_view msg, Position pos) {
101     GetErrorReporter().error(pos, msg);
102 }
103 
handleError(std::string_view msg,Position pos)104 void ThreadContext::DefaultErrorReporter::handleError(std::string_view msg, Position pos) {
105     SK_ABORT("error: %.*s\nNo SkSL error reporter configured, treating this as a fatal error\n",
106              (int)msg.length(), msg.data());
107 }
108 
109 thread_local ThreadContext* instance = nullptr;
110 
IsActive()111 bool ThreadContext::IsActive() {
112     return instance != nullptr;
113 }
114 
Instance()115 ThreadContext& ThreadContext::Instance() {
116     SkASSERTF(instance, "dsl::Start() has not been called");
117     return *instance;
118 }
119 
SetInstance(std::unique_ptr<ThreadContext> newInstance)120 void ThreadContext::SetInstance(std::unique_ptr<ThreadContext> newInstance) {
121     SkASSERT((instance == nullptr) != (newInstance == nullptr));
122     delete instance;
123     instance = newInstance.release();
124 }
125 
126 } // namespace SkSL
127