objmodel.h 12.2 KB
Newer Older
Marius Wachtler's avatar
Marius Wachtler committed
1
// Copyright (c) 2014-2016 Dropbox, Inc.
Kevin Modzelewski's avatar
Kevin Modzelewski committed
2
//
Kevin Modzelewski's avatar
Kevin Modzelewski committed
3 4 5
// 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
Kevin Modzelewski's avatar
Kevin Modzelewski committed
6
//
Kevin Modzelewski's avatar
Kevin Modzelewski committed
7
//    http://www.apache.org/licenses/LICENSE-2.0
Kevin Modzelewski's avatar
Kevin Modzelewski committed
8
//
Kevin Modzelewski's avatar
Kevin Modzelewski committed
9 10 11 12 13 14 15 16 17 18
// 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_OBJMODEL_H
#define PYSTON_RUNTIME_OBJMODEL_H

#include <stdint.h>
19
#include <string>
Kevin Modzelewski's avatar
Kevin Modzelewski committed
20

21
#include "core/options.h"
Kevin Modzelewski's avatar
Kevin Modzelewski committed
22 23 24 25 26 27 28 29 30
#include "core/types.h"

namespace pyston {

class Box;
class BoxedClass;
class BoxedInt;
class BoxedList;
class BoxedString;
Marius Wachtler's avatar
Marius Wachtler committed
31
class BoxedGenerator;
32
class BoxedTuple;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
33

34
// user-level raise functions that implement python-level semantics
35
ExcInfo excInfoForRaise(Box*, Box*, Box*);
36 37
extern "C" void raise0(ExcInfo* frame_exc_info) __attribute__((__noreturn__));
extern "C" void raise0_capi(ExcInfo* frame_exc_info) noexcept;
38
extern "C" void raise3(Box*, Box*, Box*) __attribute__((__noreturn__));
39
extern "C" void raise3_capi(Box*, Box*, Box*) noexcept;
40
extern "C" void rawReraise(Box*, Box*, Box*) __attribute__((__noreturn__));
41
void raiseExc(STOLEN(Box*) exc_obj) __attribute__((__noreturn__));
42
void _printStacktrace();
43

44
extern "C" Box* deopt(AST_expr* expr, Box* value) __attribute__((noinline));
Kevin Modzelewski's avatar
Kevin Modzelewski committed
45

46
// helper function for raising from the runtime:
47 48
void raiseExcHelper(BoxedClass*, const char* fmt, ...) __attribute__((__noreturn__))
__attribute__((format(printf, 2, 3)));
49
void raiseExcHelper(BoxedClass*, Box* arg) __attribute__((__noreturn__));
50

Kevin Modzelewski's avatar
Kevin Modzelewski committed
51
// TODO sort this
52
extern "C" void printHelper(Box* dest, Box* var, bool nl);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
53
extern "C" void my_assert(bool b);
54 55
extern "C" Box* getattr(Box* obj, BoxedString* attr) __attribute__((noinline));
extern "C" Box* getattr_capi(Box* obj, BoxedString* attr) noexcept __attribute__((noinline));
56
extern "C" Box* getattrMaybeNonstring(Box* obj, Box* attr);
Kevin Modzelewski's avatar
Format!  
Kevin Modzelewski committed
57 58
// XXX: testing.  this tail-calls in optimized builds so force it to inline for unoptimized as well to get the same
// behavior.
Kevin Modzelewski's avatar
Kevin Modzelewski committed
59
extern "C" void setattr(Box* obj, BoxedString* attr, STOLEN(Box*) attr_val) __attribute__((noinline));
60
extern "C" void delattr(Box* obj, BoxedString* attr) __attribute__((noinline));
61
extern "C" void delattrGeneric(Box* obj, BoxedString* attr, DelattrRewriteArgs* rewrite_args);
62 63 64 65 66 67 68
extern "C" bool nonzero(Box* obj) __attribute__((noinline));
extern "C" Box* runtimeCall(Box*, ArgPassSpec, Box*, Box*, Box*, Box**, const std::vector<BoxedString*>*)
    __attribute__((noinline));
extern "C" Box* runtimeCallCapi(Box*, ArgPassSpec, Box*, Box*, Box*, Box**, const std::vector<BoxedString*>*) noexcept
    __attribute__((noinline));
extern "C" Box* callattr(Box*, BoxedString*, CallattrFlags, Box*, Box*, Box*, Box**, const std::vector<BoxedString*>*)
    __attribute__((noinline));
69
extern "C" Box* callattrCapi(Box*, BoxedString*, CallattrFlags, Box*, Box*, Box*, Box**,
70 71 72 73 74 75
                             const std::vector<BoxedString*>*) noexcept __attribute__((noinline));
extern "C" BoxedString* str(Box* obj) __attribute__((noinline));
extern "C" BoxedString* repr(Box* obj) __attribute__((noinline));
extern "C" bool exceptionMatches(Box* obj, Box* cls) __attribute__((noinline));
extern "C" BoxedInt* hash(Box* obj) __attribute__((noinline));
extern "C" int64_t hashUnboxed(Box* obj) __attribute__((noinline));
Marius Wachtler's avatar
Marius Wachtler committed
76
extern "C" Box* abs_(Box* obj);
77
// extern "C" Box* chr(Box* arg);
78 79
extern "C" Box* compare(Box*, Box*, int) __attribute__((noinline));
extern "C" BoxedInt* len(Box* obj) __attribute__((noinline));
80
// extern "C" Box* trap();
81 82 83 84 85 86 87
extern "C" i64 unboxedLen(Box* obj) __attribute__((noinline));
extern "C" Box* binop(Box* lhs, Box* rhs, int op_type) __attribute__((noinline));
extern "C" Box* augbinop(Box* lhs, Box* rhs, int op_type) __attribute__((noinline));
extern "C" Box* getitem(Box* value, Box* slice) __attribute__((noinline));
extern "C" Box* getitem_capi(Box* value, Box* slice) noexcept __attribute__((noinline));
extern "C" void setitem(Box* target, Box* slice, Box* value) __attribute__((noinline));
extern "C" void delitem(Box* target, Box* slice) __attribute__((noinline));
88
extern "C" PyObject* apply_slice(PyObject* u, PyObject* v, PyObject* w) noexcept;
89 90 91 92 93
extern "C" Box* getclsattr(Box* obj, BoxedString* attr) __attribute__((noinline));
extern "C" Box* getclsattrMaybeNonstring(Box* obj, Box* attr) __attribute__((noinline));
extern "C" Box* unaryop(Box* operand, int op_type) __attribute__((noinline));
extern "C" Box* importFrom(Box* obj, BoxedString* attr) __attribute__((noinline));
extern "C" Box* importStar(Box* from_module, Box* to_globals) __attribute__((noinline));
94
extern "C" Box** unpackIntoArray(Box* obj, int64_t expected_size, Box** out_keep_alive);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
95
extern "C" void assertNameDefined(bool b, const char* name, BoxedClass* exc_cls, bool local_var_msg);
Travis Hance's avatar
Travis Hance committed
96
extern "C" void assertFailDerefNameDefined(const char* name);
97
extern "C" void assertFail(Box* assertion_type, Box* msg);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
98
extern "C" void dictSetInternal(Box* d, STOLEN(Box*) k, STOLEN(Box* v));
99 100 101 102 103

inline bool isSubclass(BoxedClass* child, BoxedClass* parent) {
    return child == parent || PyType_IsSubtype(child, parent);
}

Travis Hance's avatar
Travis Hance committed
104
extern "C" BoxedClosure* createClosure(BoxedClosure* parent_closure, size_t size);
105 106 107

Box* getiter(Box* o);
extern "C" Box* getPystonIter(Box* o);
108
extern "C" Box* getiterHelper(Box* o);
109
extern "C" Box* createBoxedIterWrapperIfNeeded(Box* o) __attribute__((noinline));
110

Kevin Modzelewski's avatar
Kevin Modzelewski committed
111
struct SetattrRewriteArgs;
112
template <Rewritable rewritable>
Kevin Modzelewski's avatar
Kevin Modzelewski committed
113
void setattrGeneric(Box* obj, BoxedString* attr, STOLEN(Box*) val, SetattrRewriteArgs* rewrite_args);
114

Kevin Modzelewski's avatar
Kevin Modzelewski committed
115
struct BinopRewriteArgs;
116 117
template <Rewritable rewritable, bool inplace>
Box* binopInternal(Box* lhs, Box* rhs, int op_type, BinopRewriteArgs* rewrite_args);
118

Kevin Modzelewski's avatar
Kevin Modzelewski committed
119
struct CallRewriteArgs;
120
template <ExceptionStyle S, Rewritable rewritable>
Kevin Modzelewski's avatar
Kevin Modzelewski committed
121
Box* runtimeCallInternal(Box* obj, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* arg3,
122
                         Box** args, const std::vector<BoxedString*>* keyword_names) noexcept(S == CAPI);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
123

124
struct GetitemRewriteArgs;
125
template <ExceptionStyle S, Rewritable rewritable = REWRITABLE>
126
Box* getitemInternal(Box* target, Box* slice, GetitemRewriteArgs* rewrite_args) noexcept(S == CAPI);
127 128 129
template <ExceptionStyle S> inline Box* getitemInternal(Box* target, Box* slice) noexcept(S == CAPI) {
    return getitemInternal<S, NOT_REWRITABLE>(target, slice, NULL);
}
130

Kevin Modzelewski's avatar
Kevin Modzelewski committed
131
struct LenRewriteArgs;
132 133
template <ExceptionStyle S, Rewritable rewritable>
BoxedInt* lenInternal(Box* obj, LenRewriteArgs* rewrite_args) noexcept(S == CAPI);
134
Box* lenCallInternal(BoxedFunctionBase* f, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2,
135
                     Box* arg3, Box** args, const std::vector<BoxedString*>* keyword_names);
136

137
template <ExceptionStyle S, Rewritable rewritable = REWRITABLE>
Travis Hance's avatar
Travis Hance committed
138
Box* callFunc(BoxedFunctionBase* func, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2,
139
              Box* arg3, Box** args, const std::vector<BoxedString*>* keyword_names) noexcept(S == CAPI);
140

141 142 143 144 145
enum LookupScope {
    CLASS_ONLY = 1,
    INST_ONLY = 2,
    CLASS_OR_INST = 3,
};
146
struct CallattrRewriteArgs;
147
template <ExceptionStyle S, Rewritable rewritable>
148
Box* callattrInternal(Box* obj, BoxedString* attr, LookupScope, CallattrRewriteArgs* rewrite_args, ArgPassSpec argspec,
149 150
                      Box* arg1, Box* arg2, Box* arg3, Box** args,
                      const std::vector<BoxedString*>* keyword_names) noexcept(S == CAPI);
151
extern "C" void delattr_internal(Box* obj, BoxedString* attr, bool allow_custom, DelattrRewriteArgs* rewrite_args);
Travis Hance's avatar
Travis Hance committed
152
struct CompareRewriteArgs;
153
template <Rewritable rewritable>
Travis Hance's avatar
Travis Hance committed
154
Box* compareInternal(Box* lhs, Box* rhs, int op_type, CompareRewriteArgs* rewrite_args);
155 156 157

// This is the equivalent of PyObject_GetAttr. Unlike getattrInternalGeneric, it checks for custom __getattr__ or
// __getattribute__ methods.
158
template <ExceptionStyle S, Rewritable rewritable = REWRITABLE>
159
Box* getattrInternal(Box* obj, BoxedString* attr, GetattrRewriteArgs* rewrite_args) noexcept(S == CAPI);
160 161 162
template <ExceptionStyle S> inline Box* getattrInternal(Box* obj, BoxedString* attr) noexcept(S == CAPI) {
    return getattrInternal<S, NOT_REWRITABLE>(obj, attr, NULL);
}
163 164 165 166

// This is the equivalent of PyObject_GenericGetAttr, which performs the default lookup rules for getattr() (check for
// data descriptor, check for instance attribute, check for non-data descriptor). It does not check for __getattr__ or
// __getattribute__.
167
template <bool IsType, Rewritable rewritable>
168 169
Box* getattrInternalGeneric(Box* obj, BoxedString* attr, GetattrRewriteArgs* rewrite_args, bool cls_only, bool for_call,
                            Box** bind_obj_out, RewriterVar** r_bind_obj_out);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
170

171 172
extern "C" PyObject* type_getattro(PyObject* o, PyObject* name) noexcept;

173 174
// This is the equivalent of _PyType_Lookup(), which calls Box::getattr() on each item in the object's MRO in the
// appropriate order. It does not do any descriptor logic.
175
template <Rewritable rewritable = REWRITABLE>
Kevin Modzelewski's avatar
Kevin Modzelewski committed
176 177
BORROWED(Box*) typeLookup(BoxedClass* cls, BoxedString* attr, GetattrRewriteArgs* rewrite_args);
inline BORROWED(Box*) typeLookup(BoxedClass* cls, BoxedString* attr) {
178 179
    return typeLookup<NOT_REWRITABLE>(cls, attr, NULL);
}
180

181 182
extern "C" void raiseAttributeErrorStr(const char* typeName, llvm::StringRef attr) __attribute__((__noreturn__));
extern "C" void raiseAttributeError(Box* obj, llvm::StringRef attr) __attribute__((__noreturn__));
183 184
extern "C" void raiseAttributeErrorStrCapi(const char* typeName, llvm::StringRef attr) noexcept;
extern "C" void raiseAttributeErrorCapi(Box* obj, llvm::StringRef attr) noexcept;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
185
extern "C" void raiseNotIterableError(const char* typeName) __attribute__((__noreturn__));
186
extern "C" void raiseIndexErrorStr(const char* typeName) __attribute__((__noreturn__));
187
extern "C" void raiseIndexErrorStrCapi(const char* typeName) noexcept;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
188

189
Box* typeCall(Box*, BoxedTuple*, BoxedDict*);
Rudi Chen's avatar
Rudi Chen committed
190 191
Box* type_new(BoxedClass* metatype, Box* args, Box* kwds) noexcept;
Box* typeNewGeneric(Box* cls, Box* arg1, Box* arg2, Box** _args);
192

193 194 195
// These process a potential descriptor, differing in their behavior if the object was not a descriptor.
// the OrNull variant returns NULL to signify it wasn't a descriptor, and the processDescriptor version
// returns obj.
196
Box* processDescriptor(Box* obj, Box* inst, Box* owner);
197
Box* processDescriptorOrNull(Box* obj, Box* inst, Box* owner);
198

199
template <ExceptionStyle S, Rewritable rewritable>
200
Box* callCLFunc(FunctionMetadata* f, CallRewriteArgs* rewrite_args, int num_output_args, BoxedClosure* closure,
201
                BoxedGenerator* generator, Box* globals, Box* oarg1, Box* oarg2, Box* oarg3,
202
                Box** oargs) noexcept(S == CAPI);
203 204

static const char* objectNewParameterTypeErrorMsg() {
205
    if (PY_VERSION_HEX >= version_hex(2, 7, 4)) {
206 207 208 209 210
        return "object() takes no parameters";
    } else {
        return "object.__new__() takes no parameters";
    }
}
211

Marius Wachtler's avatar
Marius Wachtler committed
212 213 214 215 216 217 218
inline std::tuple<Box*, Box*, Box*, Box**> getTupleFromArgsArray(Box** args, int num_args) {
    Box* arg1 = num_args >= 1 ? args[0] : nullptr;
    Box* arg2 = num_args >= 2 ? args[1] : nullptr;
    Box* arg3 = num_args >= 3 ? args[2] : nullptr;
    Box** argtuple = num_args >= 4 ? &args[3] : nullptr;
    return std::make_tuple(arg1, arg2, arg3, argtuple);
}
Travis Hance's avatar
exec  
Travis Hance committed
219

Travis Hance's avatar
Travis Hance committed
220 221
// The `globals` argument can be either a BoxedModule or a BoxedDict

222 223
// Corresponds to a name lookup with GLOBAL scope.  Checks the passed globals object, then the builtins,
// and if not found raises an exception.
224 225 226
extern "C" Box* getGlobal(Box* globals, BoxedString* name) __attribute__((noinline));
extern "C" void setGlobal(Box* globals, BoxedString* name, STOLEN(Box*) value) __attribute__((noinline));
extern "C" void delGlobal(Box* globals, BoxedString* name) __attribute__((noinline));
Travis Hance's avatar
Travis Hance committed
227

228 229 230
extern "C" void boxedLocalsSet(Box* boxedLocals, BoxedString* attr, Box* val);
extern "C" Box* boxedLocalsGet(Box* boxedLocals, BoxedString* attr, Box* globals);
extern "C" void boxedLocalsDel(Box* boxedLocals, BoxedString* attr);
231

Kevin Modzelewski's avatar
Kevin Modzelewski committed
232 233
extern "C" void checkRefs(Box* b);   // asserts that b has >= 0 refs
extern "C" Box* assertAlive(Box* b); // asserts that b has > 0 refs, and returns b
234
extern "C" void xdecrefAndRethrow(void* cxa_ptr, int num_decref, ...);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
235 236
}
#endif