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 @@
#include "codegen/compvars.h"
#include "core/ast.h"
#include "core/util.h"
#include "runtime/code.h"
#include "runtime/types.h"
namespace pyston {
......@@ -39,27 +40,57 @@ DS_DEFINE_RWLOCK(codegen_rwlock);
CLFunction::CLFunction(int num_args, int num_defaults, bool takes_varargs, bool takes_kwargs,
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)),
param_names(this->source->ast, this->source->getInternedStrings()),
always_use_version(NULL),
code_obj(NULL),
times_interpreted(0),
internal_callable(NULL, NULL) {
assert(num_args >= num_defaults);
}
CLFunction::CLFunction(int num_args, int num_defaults, bool takes_varargs, bool takes_kwargs,
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),
param_names(param_names),
always_use_version(NULL),
code_obj(NULL),
times_interpreted(0),
internal_callable(NULL, NULL) {
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,
std::vector<AST_stmt*> body, BoxedString* fn)
: parent_module(m),
......
......@@ -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'");
}
return codeForCLFunction(cl);
return (Box*)cl->getCode();
}
static Box* evalMain(Box* boxedCode, Box* globals, Box* locals, PyCompilerFlags* flags) {
......
......@@ -343,6 +343,8 @@ typedef std::vector<CompiledFunction*> FunctionList;
struct CallRewriteArgs;
class BoxedCode;
class CLFunction {
BoxedCode* code_obj;
public:
ParamReceiveSpec paramspec;
......@@ -354,9 +356,6 @@ public:
CompiledFunction* always_use_version; // if this version is set, always use it (for unboxed cases)
std::unordered_map<const OSREntryDescriptor*, CompiledFunction*> osr_versions;
// Please use codeForFunction() to access this:
BoxedCode* code_obj;
int propagated_cxx_exceptions = 0;
// For use by the interpreter/baseline jit:
......@@ -379,25 +378,9 @@ public:
int numReceivedArgs() { return paramspec.totalReceived(); }
void 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;
}
}
BoxedCode* getCode();
void addVersion(CompiledFunction* compiled);
bool isGenerator() const {
if (source)
......
......@@ -11,13 +11,11 @@
// 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.
//
#include "runtime/code.h"
#include <sstream>
#include "Python.h"
#include "code.h"
#include "core/ast.h"
#include "gc/collector.h"
#include "runtime/objmodel.h"
......@@ -29,96 +27,78 @@ extern "C" {
BoxedClass* code_cls;
}
class BoxedCode : public Box {
public:
CLFunction* f;
BoxedCode(CLFunction* f) : f(f) {}
void BoxedCode::gcHandler(GCVisitor* v, Box* b) {
assert(b->cls == code_cls);
Box::gcHandler(v, b);
}
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) {
assert(b->cls == code_cls);
Box::gcHandler(v, b);
}
Box* BoxedCode::filename(Box* b, void*) {
RELEASE_ASSERT(b->cls == code_cls, "");
return static_cast<BoxedCode*>(b)->f->source->getFn();
}
static Box* name(Box* b, void*) {
RELEASE_ASSERT(b->cls == code_cls, "");
return static_cast<BoxedCode*>(b)->f->source->getName();
}
Box* BoxedCode::firstlineno(Box* b, void*) {
RELEASE_ASSERT(b->cls == code_cls, "");
BoxedCode* code = static_cast<BoxedCode*>(b);
CLFunction* cl = code->f;
static Box* filename(Box* b, void*) {
RELEASE_ASSERT(b->cls == code_cls, "");
return static_cast<BoxedCode*>(b)->f->source->getFn();
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);
}
static Box* firstlineno(Box* b, void*) {
RELEASE_ASSERT(b->cls == code_cls, "");
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(-1);
if (cl->source->ast->lineno == (uint32_t)-1)
return boxInt(-1);
return boxInt(cl->source->ast->lineno);
}
static Box* argcount(Box* b, void*) {
RELEASE_ASSERT(b->cls == code_cls, "");
return boxInt(cl->source->ast->lineno);
}
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*) {
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]);
}
return boxInt(static_cast<BoxedCode*>(b)->f->paramspec.num_args);
}
static Box* flags(Box* b, void*) {
RELEASE_ASSERT(b->cls == code_cls, "");
BoxedCode* code = static_cast<BoxedCode*>(b);
int flags = 0;
if (code->f->param_names.vararg.size())
flags |= CO_VARARGS;
if (code->f->param_names.kwarg.size())
flags |= CO_VARKEYWORDS;
if (code->f->isGenerator())
flags |= CO_GENERATOR;
return boxInt(flags);
}
};
Box* BoxedCode::varnames(Box* b, void*) {
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]);
}
Box* codeForCLFunction(CLFunction* f) {
if (!f->code_obj) {
f->code_obj = new BoxedCode(f);
// CLFunctions don't currently participate in GC. They actually never get freed currently.
gc::registerPermanentRoot(f->code_obj);
}
return f->code_obj;
Box* BoxedCode::flags(Box* b, void*) {
RELEASE_ASSERT(b->cls == code_cls, "");
BoxedCode* code = static_cast<BoxedCode*>(b);
int flags = 0;
if (code->f->param_names.vararg.size())
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) {
return codeForCLFunction(f->f);
return f->f->getCode();
}
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:
Box* globals = it.getGlobalsDict();
BoxedFrame* f = fi->frame_obj = new BoxedFrame(std::move(it));
f->_globals = globals;
f->_code = codeForCLFunction(cl);
f->_code = (Box*)cl->getCode();
}
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