Commit 1573116c authored by Rudi Chen's avatar Rudi Chen

Some reorganization of CLFunction/BoxedCode code.

- The code_obj field of CLFunction should be private since we require
  the use of an accessor there.
- Move some functions implementations out of headers.
- Put static methods into class.
parent 3132de84
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include "codegen/compvars.h" #include "codegen/compvars.h"
#include "core/ast.h" #include "core/ast.h"
#include "core/util.h" #include "core/util.h"
#include "runtime/code.h"
#include "runtime/types.h" #include "runtime/types.h"
namespace pyston { namespace pyston {
...@@ -39,27 +40,57 @@ DS_DEFINE_RWLOCK(codegen_rwlock); ...@@ -39,27 +40,57 @@ DS_DEFINE_RWLOCK(codegen_rwlock);
CLFunction::CLFunction(int num_args, int num_defaults, bool takes_varargs, bool takes_kwargs, CLFunction::CLFunction(int num_args, int num_defaults, bool takes_varargs, bool takes_kwargs,
std::unique_ptr<SourceInfo> source) std::unique_ptr<SourceInfo> source)
: paramspec(num_args, num_defaults, takes_varargs, takes_kwargs), : code_obj(NULL),
paramspec(num_args, num_defaults, takes_varargs, takes_kwargs),
source(std::move(source)), source(std::move(source)),
param_names(this->source->ast, this->source->getInternedStrings()), param_names(this->source->ast, this->source->getInternedStrings()),
always_use_version(NULL), always_use_version(NULL),
code_obj(NULL),
times_interpreted(0), times_interpreted(0),
internal_callable(NULL, NULL) { internal_callable(NULL, NULL) {
assert(num_args >= num_defaults); assert(num_args >= num_defaults);
} }
CLFunction::CLFunction(int num_args, int num_defaults, bool takes_varargs, bool takes_kwargs, CLFunction::CLFunction(int num_args, int num_defaults, bool takes_varargs, bool takes_kwargs,
const ParamNames& param_names) const ParamNames& param_names)
: paramspec(num_args, num_defaults, takes_varargs, takes_kwargs), : code_obj(NULL),
paramspec(num_args, num_defaults, takes_varargs, takes_kwargs),
source(nullptr), source(nullptr),
param_names(param_names), param_names(param_names),
always_use_version(NULL), always_use_version(NULL),
code_obj(NULL),
times_interpreted(0), times_interpreted(0),
internal_callable(NULL, NULL) { internal_callable(NULL, NULL) {
assert(num_args >= num_defaults); assert(num_args >= num_defaults);
} }
BoxedCode* CLFunction::getCode() {
if (!code_obj) {
code_obj = new BoxedCode(this);
// CLFunctions don't currently participate in GC. They actually never get freed currently.
gc::registerPermanentRoot(code_obj);
}
return code_obj;
}
void CLFunction::addVersion(CompiledFunction* compiled) {
assert(compiled);
assert((compiled->spec != NULL) + (compiled->entry_descriptor != NULL) == 1);
assert(compiled->clfunc == NULL);
assert(compiled->code);
compiled->clfunc = this;
if (compiled->entry_descriptor == NULL) {
bool could_have_speculations = (source.get() != NULL);
if (!could_have_speculations && versions.size() == 0 && compiled->effort == EffortLevel::MAXIMAL
&& compiled->spec->accepts_all_inputs && compiled->spec->boxed_return_value)
always_use_version = compiled;
assert(compiled->spec->arg_types.size() == paramspec.totalReceived());
versions.push_back(compiled);
} else {
osr_versions[compiled->entry_descriptor] = compiled;
}
}
SourceInfo::SourceInfo(BoxedModule* m, ScopingAnalysis* scoping, FutureFlags future_flags, AST* ast, SourceInfo::SourceInfo(BoxedModule* m, ScopingAnalysis* scoping, FutureFlags future_flags, AST* ast,
std::vector<AST_stmt*> body, BoxedString* fn) std::vector<AST_stmt*> body, BoxedString* fn)
: parent_module(m), : parent_module(m),
......
...@@ -531,7 +531,7 @@ Box* compile(Box* source, Box* fn, Box* type, Box** _args) { ...@@ -531,7 +531,7 @@ Box* compile(Box* source, Box* fn, Box* type, Box** _args) {
raiseExcHelper(ValueError, "compile() arg 3 must be 'exec', 'eval' or 'single'"); raiseExcHelper(ValueError, "compile() arg 3 must be 'exec', 'eval' or 'single'");
} }
return codeForCLFunction(cl); return (Box*)cl->getCode();
} }
static Box* evalMain(Box* boxedCode, Box* globals, Box* locals, PyCompilerFlags* flags) { static Box* evalMain(Box* boxedCode, Box* globals, Box* locals, PyCompilerFlags* flags) {
......
...@@ -343,6 +343,8 @@ typedef std::vector<CompiledFunction*> FunctionList; ...@@ -343,6 +343,8 @@ typedef std::vector<CompiledFunction*> FunctionList;
struct CallRewriteArgs; struct CallRewriteArgs;
class BoxedCode; class BoxedCode;
class CLFunction { class CLFunction {
BoxedCode* code_obj;
public: public:
ParamReceiveSpec paramspec; ParamReceiveSpec paramspec;
...@@ -354,9 +356,6 @@ public: ...@@ -354,9 +356,6 @@ public:
CompiledFunction* always_use_version; // if this version is set, always use it (for unboxed cases) CompiledFunction* always_use_version; // if this version is set, always use it (for unboxed cases)
std::unordered_map<const OSREntryDescriptor*, CompiledFunction*> osr_versions; std::unordered_map<const OSREntryDescriptor*, CompiledFunction*> osr_versions;
// Please use codeForFunction() to access this:
BoxedCode* code_obj;
int propagated_cxx_exceptions = 0; int propagated_cxx_exceptions = 0;
// For use by the interpreter/baseline jit: // For use by the interpreter/baseline jit:
...@@ -379,25 +378,9 @@ public: ...@@ -379,25 +378,9 @@ public:
int numReceivedArgs() { return paramspec.totalReceived(); } int numReceivedArgs() { return paramspec.totalReceived(); }
void addVersion(CompiledFunction* compiled) { BoxedCode* getCode();
assert(compiled);
assert((compiled->spec != NULL) + (compiled->entry_descriptor != NULL) == 1); void addVersion(CompiledFunction* compiled);
assert(compiled->clfunc == NULL);
assert(compiled->code);
compiled->clfunc = this;
if (compiled->entry_descriptor == NULL) {
bool could_have_speculations = (source.get() != NULL);
if (!could_have_speculations && versions.size() == 0 && compiled->effort == EffortLevel::MAXIMAL
&& compiled->spec->accepts_all_inputs && compiled->spec->boxed_return_value)
always_use_version = compiled;
assert(compiled->spec->arg_types.size() == paramspec.totalReceived());
versions.push_back(compiled);
} else {
osr_versions[compiled->entry_descriptor] = compiled;
}
}
bool isGenerator() const { bool isGenerator() const {
if (source) if (source)
......
...@@ -11,13 +11,11 @@ ...@@ -11,13 +11,11 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
//
#include "runtime/code.h"
#include <sstream> #include <sstream>
#include "Python.h"
#include "code.h"
#include "core/ast.h" #include "core/ast.h"
#include "gc/collector.h" #include "gc/collector.h"
#include "runtime/objmodel.h" #include "runtime/objmodel.h"
...@@ -29,96 +27,78 @@ extern "C" { ...@@ -29,96 +27,78 @@ extern "C" {
BoxedClass* code_cls; BoxedClass* code_cls;
} }
class BoxedCode : public Box { void BoxedCode::gcHandler(GCVisitor* v, Box* b) {
public: assert(b->cls == code_cls);
CLFunction* f; Box::gcHandler(v, b);
}
BoxedCode(CLFunction* f) : f(f) {}
DEFAULT_CLASS(code_cls); Box* BoxedCode::name(Box* b, void*) {
RELEASE_ASSERT(b->cls == code_cls, "");
return static_cast<BoxedCode*>(b)->f->source->getName();
}
static void gcHandler(GCVisitor* v, Box* b) { Box* BoxedCode::filename(Box* b, void*) {
assert(b->cls == code_cls); RELEASE_ASSERT(b->cls == code_cls, "");
Box::gcHandler(v, b); return static_cast<BoxedCode*>(b)->f->source->getFn();
} }
static Box* name(Box* b, void*) { Box* BoxedCode::firstlineno(Box* b, void*) {
RELEASE_ASSERT(b->cls == code_cls, ""); RELEASE_ASSERT(b->cls == code_cls, "");
return static_cast<BoxedCode*>(b)->f->source->getName(); BoxedCode* code = static_cast<BoxedCode*>(b);
} CLFunction* cl = code->f;
static Box* filename(Box* b, void*) { if (!cl->source) {
RELEASE_ASSERT(b->cls == code_cls, ""); // I don't think it really matters what we return here;
return static_cast<BoxedCode*>(b)->f->source->getFn(); // in CPython, builtin functions don't have code objects.
return boxInt(-1);
} }
static Box* firstlineno(Box* b, void*) { if (cl->source->ast->lineno == (uint32_t)-1)
RELEASE_ASSERT(b->cls == code_cls, ""); return boxInt(-1);
BoxedCode* code = static_cast<BoxedCode*>(b);
CLFunction* cl = code->f;
if (!cl->source) {
// I don't think it really matters what we return here;
// in CPython, builtin functions don't have code objects.
return boxInt(-1);
}
if (cl->source->ast->lineno == (uint32_t)-1) return boxInt(cl->source->ast->lineno);
return boxInt(-1); }
return boxInt(cl->source->ast->lineno);
}
static Box* argcount(Box* b, void*) {
RELEASE_ASSERT(b->cls == code_cls, "");
return boxInt(static_cast<BoxedCode*>(b)->f->paramspec.num_args); Box* BoxedCode::argcount(Box* b, void*) {
} RELEASE_ASSERT(b->cls == code_cls, "");
static Box* varnames(Box* b, void*) { return boxInt(static_cast<BoxedCode*>(b)->f->paramspec.num_args);
RELEASE_ASSERT(b->cls == code_cls, ""); }
BoxedCode* code = static_cast<BoxedCode*>(b);
auto& param_names = code->f->param_names;
if (!param_names.takes_param_names)
return EmptyTuple;
std::vector<Box*, StlCompatAllocator<Box*>> elts;
for (auto sr : param_names.args)
elts.push_back(boxString(sr));
if (param_names.vararg.size())
elts.push_back(boxString(param_names.vararg));
if (param_names.kwarg.size())
elts.push_back(boxString(param_names.kwarg));
return BoxedTuple::create(elts.size(), &elts[0]);
}
static Box* flags(Box* b, void*) { Box* BoxedCode::varnames(Box* b, void*) {
RELEASE_ASSERT(b->cls == code_cls, ""); RELEASE_ASSERT(b->cls == code_cls, "");
BoxedCode* code = static_cast<BoxedCode*>(b); BoxedCode* code = static_cast<BoxedCode*>(b);
int flags = 0; auto& param_names = code->f->param_names;
if (code->f->param_names.vararg.size()) if (!param_names.takes_param_names)
flags |= CO_VARARGS; return EmptyTuple;
if (code->f->param_names.kwarg.size())
flags |= CO_VARKEYWORDS; std::vector<Box*, StlCompatAllocator<Box*>> elts;
if (code->f->isGenerator()) for (auto sr : param_names.args)
flags |= CO_GENERATOR; elts.push_back(boxString(sr));
return boxInt(flags); if (param_names.vararg.size())
} elts.push_back(boxString(param_names.vararg));
}; if (param_names.kwarg.size())
elts.push_back(boxString(param_names.kwarg));
return BoxedTuple::create(elts.size(), &elts[0]);
}
Box* codeForCLFunction(CLFunction* f) { Box* BoxedCode::flags(Box* b, void*) {
if (!f->code_obj) { RELEASE_ASSERT(b->cls == code_cls, "");
f->code_obj = new BoxedCode(f); BoxedCode* code = static_cast<BoxedCode*>(b);
// CLFunctions don't currently participate in GC. They actually never get freed currently.
gc::registerPermanentRoot(f->code_obj); int flags = 0;
} if (code->f->param_names.vararg.size())
return f->code_obj; flags |= CO_VARARGS;
if (code->f->param_names.kwarg.size())
flags |= CO_VARKEYWORDS;
if (code->f->isGenerator())
flags |= CO_GENERATOR;
return boxInt(flags);
} }
Box* codeForFunction(BoxedFunction* f) { Box* codeForFunction(BoxedFunction* f) {
return codeForCLFunction(f->f); return f->f->getCode();
} }
CLFunction* clfunctionFromCode(Box* code) { CLFunction* clfunctionFromCode(Box* code) {
......
// Copyright (c) 2014-2015 Dropbox, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PYSTON_RUNTIME_CODE_H
#define PYSTON_RUNTIME_CODE_H
#include "Python.h"
#include "runtime/types.h"
namespace pyston {
class BoxedCode : public Box {
public:
CLFunction* f;
BoxedCode(CLFunction* f) : f(f) {}
DEFAULT_CLASS(code_cls);
static void gcHandler(GCVisitor* v, Box* b);
// These need to be static functions rather than methods because function
// pointers could point to them.
static Box* name(Box* b, void*);
static Box* filename(Box* b, void*);
static Box* firstlineno(Box* b, void*);
static Box* argcount(Box* b, void*);
static Box* varnames(Box* b, void*);
static Box* flags(Box* b, void*);
};
}
#endif
...@@ -134,7 +134,7 @@ public: ...@@ -134,7 +134,7 @@ public:
Box* globals = it.getGlobalsDict(); Box* globals = it.getGlobalsDict();
BoxedFrame* f = fi->frame_obj = new BoxedFrame(std::move(it)); BoxedFrame* f = fi->frame_obj = new BoxedFrame(std::move(it));
f->_globals = globals; f->_globals = globals;
f->_code = codeForCLFunction(cl); f->_code = (Box*)cl->getCode();
} }
return fi->frame_obj; return fi->frame_obj;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment