types.h 43.1 KB
Newer Older
Kevin Modzelewski's avatar
Kevin Modzelewski committed
1
// Copyright (c) 2014-2015 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
// 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_TYPES_H
#define PYSTON_RUNTIME_TYPES_H

18
#include <llvm/ADT/StringMap.h>
19
#include <llvm/ADT/Twine.h>
Marius Wachtler's avatar
Marius Wachtler committed
20 21
#include <ucontext.h>

22 23 24
#include "Python.h"
#include "structmember.h"

Travis Hance's avatar
Travis Hance committed
25
#include "codegen/irgen/future.h"
26
#include "core/contiguous_map.h"
27
#include "core/from_llvm/DenseMap.h"
28
#include "core/threading.h"
Kevin Modzelewski's avatar
Kevin Modzelewski committed
29
#include "core/types.h"
30
#include "gc/gc_alloc.h"
Kevin Modzelewski's avatar
Kevin Modzelewski committed
31 32 33 34 35 36 37 38 39 40

namespace pyston {

extern bool IN_SHUTDOWN;

class BoxedString;
class BoxedList;
class BoxedDict;
class BoxedTuple;
class BoxedFile;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
41
class BoxedClosure;
Marius Wachtler's avatar
Marius Wachtler committed
42
class BoxedGenerator;
43
class BoxedLong;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
44 45 46

void setupInt();
void setupFloat();
Travis Hance's avatar
Travis Hance committed
47
void setupComplex();
Kevin Modzelewski's avatar
Kevin Modzelewski committed
48 49 50 51 52 53 54 55 56 57 58
void setupStr();
void setupList();
void list_dtor(BoxedList* l);
void setupBool();
void dict_dtor(BoxedDict* d);
void setupDict();
void tuple_dtor(BoxedTuple* d);
void setupTuple();
void file_dtor(BoxedFile* d);
void setupFile();
void setupCAPI();
Marius Wachtler's avatar
Marius Wachtler committed
59
void setupGenerator();
Travis Hance's avatar
Travis Hance committed
60
void setupDescr();
Kevin Modzelewski's avatar
Kevin Modzelewski committed
61
void setupCode();
62
void setupFrame();
Kevin Modzelewski's avatar
Kevin Modzelewski committed
63

64
void setupSys();
65
void setupBuiltins();
Marius Wachtler's avatar
Marius Wachtler committed
66
void setupPyston();
67
void setupThread();
68
void setupImport();
69
void setupAST();
70
void setupSysEnd();
Kevin Modzelewski's avatar
Kevin Modzelewski committed
71

72 73
BoxedDict* getSysModulesDict();
BoxedList* getSysPath();
74
extern "C" Box* getSysStdout();
75

76 77 78
extern "C" BoxedTuple* EmptyTuple;
extern "C" BoxedString* EmptyString;

79
extern "C" {
80
extern BoxedClass* object_cls, *type_cls, *bool_cls, *int_cls, *long_cls, *float_cls, *str_cls, *function_cls,
81
    *none_cls, *instancemethod_cls, *list_cls, *slice_cls, *module_cls, *dict_cls, *tuple_cls, *file_cls,
82 83 84 85
    *enumerate_cls, *xrange_cls, *member_descriptor_cls, *null_importer_cls, *method_cls, *closure_cls, *generator_cls,
    *complex_cls, *basestring_cls, *property_cls, *staticmethod_cls, *classmethod_cls, *attrwrapper_cls,
    *pyston_getset_cls, *capi_getset_cls, *builtin_function_or_method_cls, *set_cls, *frozenset_cls, *code_cls,
    *frame_cls, *capifunc_cls, *wrapperdescr_cls, *wrapperobject_cls;
86
}
87
#define unicode_cls (&PyUnicode_Type)
88
#define memoryview_cls (&PyMemoryView_Type)
89

90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
#define unicode_cls (&PyUnicode_Type)
#define memoryview_cls (&PyMemoryView_Type)

#define SystemError ((BoxedClass*)PyExc_SystemError)
#define StopIteration ((BoxedClass*)PyExc_StopIteration)
#define NameError ((BoxedClass*)PyExc_NameError)
#define UnboundLocalError ((BoxedClass*)PyExc_UnboundLocalError)
#define BaseException ((BoxedClass*)PyExc_BaseException)
#define TypeError ((BoxedClass*)PyExc_TypeError)
#define AssertionError ((BoxedClass*)PyExc_AssertionError)
#define ValueError ((BoxedClass*)PyExc_ValueError)
#define SystemExit ((BoxedClass*)PyExc_SystemExit)
#define SyntaxError ((BoxedClass*)PyExc_SyntaxError)
#define Exception ((BoxedClass*)PyExc_Exception)
#define AttributeError ((BoxedClass*)PyExc_AttributeError)
#define RuntimeError ((BoxedClass*)PyExc_RuntimeError)
#define ZeroDivisionError ((BoxedClass*)PyExc_ZeroDivisionError)
#define ImportError ((BoxedClass*)PyExc_ImportError)
#define IndexError ((BoxedClass*)PyExc_IndexError)
#define GeneratorExit ((BoxedClass*)PyExc_GeneratorExit)
#define IOError ((BoxedClass*)PyExc_IOError)
#define KeyError ((BoxedClass*)PyExc_KeyError)
#define OverflowError ((BoxedClass*)PyExc_OverflowError)

// Contains a list classes that have BaseException as a parent. This list is NOT guaranteed to be
// comprehensive - it will not contain user-defined exception types. This is mainly for optimization
// purposes, where it's useful to speed up the garbage collection of some exceptions.
extern std::vector<BoxedClass*> exception_types;

Kevin Modzelewski's avatar
Kevin Modzelewski committed
119
extern "C" {
Dong-hee Na's avatar
Dong-hee Na committed
120
extern Box* None, *NotImplemented, *True, *False, *Ellipsis;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
121
}
122
extern "C" {
123 124
extern Box* repr_obj, *len_obj, *hash_obj, *range_obj, *abs_obj, *min_obj, *max_obj, *open_obj, *id_obj, *chr_obj,
    *ord_obj, *trap_obj;
125
} // these are only needed for functionRepr, which is hacky
Kevin Modzelewski's avatar
Kevin Modzelewski committed
126 127 128
extern "C" {
extern BoxedModule* sys_module, *builtins_module, *math_module, *time_module, *thread_module;
}
Kevin Modzelewski's avatar
Kevin Modzelewski committed
129

Kevin Modzelewski's avatar
Kevin Modzelewski committed
130 131
extern "C" inline Box* boxBool(bool b) __attribute__((visibility("default")));
extern "C" inline Box* boxBool(bool b) {
Kevin Modzelewski's avatar
Kevin Modzelewski committed
132 133 134 135
    if (b)
        Py_RETURN_TRUE;
    else
        Py_RETURN_FALSE;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
136 137 138
}
extern "C" inline Box* boxBoolNegated(bool b) __attribute__((visibility("default")));
extern "C" inline Box* boxBoolNegated(bool b) {
Kevin Modzelewski's avatar
Kevin Modzelewski committed
139
    return boxBool(!b);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
140
}
141
extern "C" Box* boxInt(i64) __attribute__((visibility("default")));
Kevin Modzelewski's avatar
Kevin Modzelewski committed
142 143
extern "C" i64 unboxInt(Box*);
extern "C" Box* boxFloat(double d);
144 145
extern "C" Box* boxInstanceMethod(Box* obj, Box* func, Box* type);
extern "C" Box* boxUnboundInstanceMethod(Box* func, Box* type);
146

147 148 149 150
// Both llvm::StringRef and llvm::Twine offer implicit conversions from const char*, so
// put the twine version under a different name.
BoxedString* boxString(llvm::StringRef s);
BoxedString* boxStringTwine(const llvm::Twine& s);
151

152
extern "C" Box* decodeUTF8StringPtr(llvm::StringRef s);
153

154
extern "C" inline void listAppendInternal(Box* self, Box* v) __attribute__((visibility("default")));
155
extern "C" void listAppendArrayInternal(Box* self, Box** v, int nelts);
156 157 158
extern "C" Box* createFunctionFromMetadata(FunctionMetadata* f, BoxedClosure* closure, Box* globals,
                                           std::initializer_list<Box*> defaults) noexcept;
extern "C" FunctionMetadata* getFunctionMetadata(Box* b);
159
extern "C" Box* createUserClass(BoxedString* name, Box* base, Box* attr_dict);
160
extern "C" double unboxFloat(Box* b);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
161 162 163
extern "C" Box* createDict();
extern "C" Box* createList();
extern "C" Box* createSlice(Box* start, Box* stop, Box* step);
164
extern "C" Box* createTuple(int64_t nelts, Box** elts);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
165 166
extern "C" void printFloat(double d);

167
Box* objectStr(Box*);
168
Box* objectRepr(Box*);
169

170 171 172 173 174 175
void checkAndThrowCAPIException();
void throwCAPIException() __attribute__((noreturn));
void ensureCAPIExceptionSet();
struct ExcInfo;
void setCAPIException(const ExcInfo& e);

176 177 178
// Finalizer-related
void default_free(void*);
void dealloc_null(Box* box);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
179
void file_dealloc(Box*) noexcept;
180

Rudi Chen's avatar
Rudi Chen committed
181 182
// In Pyston, this is the same type as CPython's PyTypeObject (they are interchangeable, but we
// use BoxedClass in Pyston wherever possible as a convention).
183
class BoxedClass : public BoxVar {
184 185 186
public:
    typedef void (*gcvisit_func)(GCVisitor*, Box*);

187 188 189 190 191 192
public:
    PyTypeObject_BODY;

    HCAttrs attrs;

    // TODO: these don't actually get deallocated right now
193
    std::unique_ptr<CallattrCapiIC> next_ic;
Marius Wachtler's avatar
Marius Wachtler committed
194
    std::unique_ptr<CallattrIC> hasnext_ic, repr_ic, iter_ic;
195
    std::unique_ptr<NonzeroIC> nonzero_ic;
196
    Box* callHasnextIC(Box* obj, bool null_on_nonexistent);
197
    Box* call_nextIC(Box* obj) noexcept;
198
    Box* callReprIC(Box* obj);
Marius Wachtler's avatar
Marius Wachtler committed
199
    Box* callIterIC(Box* obj);
200
    bool callNonzeroIC(Box* obj);
201 202 203 204

    gcvisit_func gc_visit;

    // Offset of the HCAttrs object or 0 if there are no hcattrs.
Travis Hance's avatar
slots  
Travis Hance committed
205
    // Negative offset is from the end of the class (useful for variable-size objects with the attrs at the end)
206
    // Analogous to tp_dictoffset
Travis Hance's avatar
slots  
Travis Hance committed
207 208
    // A class should have at most of one attrs_offset and tp_dictoffset be nonzero.
    // (But having nonzero attrs_offset here would map to having nonzero tp_dictoffset in CPython)
209
    int attrs_offset;
210

211 212
    bool instancesHaveHCAttrs() { return attrs_offset != 0; }
    bool instancesHaveDictAttrs() { return tp_dictoffset != 0; }
213

214 215
    // A "safe" tp_dealloc destructor/finalizer is one we believe:
    //  1) Can be called at any point after the object is dead.
216
    //      (implies it's references could be finalized already, including its class)
217 218 219 220
    //  2) Won't take a lot of time to run.
    //  3) Won't take up a lot of memory (requiring another GC run).
    //  4) Won't resurrect itself.
    //
221 222 223 224
    // We specify that such destructors are safe for optimization purposes (in our GC, we try to
    // emulate the order of destructor calls and support resurrection by calling them in topological
    // order through multiple GC passes, which is potentially quite expensive). We call the tp_dealloc
    // as the object gets freed rather than put it in a pending finalizer list.
225 226
    bool has_safe_tp_dealloc;

227 228 229 230 231 232 233 234
    // Whether this class object is constant or not, ie whether or not class-level
    // attributes can be changed or added.
    // Does not necessarily imply that the instances of this class are constant,
    // though for now (is_constant && !hasattrs) does imply that the instances are constant.
    bool is_constant;

    // Whether this class was defined by the user or is a builtin type.
    // this is used mostly for debugging.
235
    bool is_user_defined;
236

237 238 239 240 241
    // Whether this is a Pyston-defined class (as opposed to an extension-defined class).
    // We can ensure certain behavior about our Pyston classes (in particular around GC support)
    // that we can't rely on for extension classes.
    bool is_pyston_class;

242 243 244 245 246 247
    // Just for debugging: whether instances of this class should always be considered nonzero.
    // This is the default for anything that doesn't define a __nonzero__ or __len__ method, but
    // for builtin types we have the extra check that we opted into this behavior rather than
    // just forgot to add nonzero/len.
    bool instances_are_nonzero;

Kevin Modzelewski's avatar
Kevin Modzelewski committed
248 249
    bool has___class__; // Has a custom __class__ attribute (ie different from object's __class__ descriptor)
    bool has_instancecheck;
250
    bool has_subclasscheck;
251
    bool has_getattribute;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
252

Kevin Modzelewski's avatar
Kevin Modzelewski committed
253
    typedef bool (*pyston_inquiry)(Box*);
254 255 256 257 258

    // tpp_descr_get is currently just a cache only for the use of tp_descr_get, and shouldn't
    // be called or examined by clients:
    descrgetfunc tpp_descr_get;

Kevin Modzelewski's avatar
Kevin Modzelewski committed
259 260
    pyston_inquiry tpp_hasnext;

Kevin Modzelewski's avatar
Kevin Modzelewski committed
261 262
    ExceptionSwitchableFunction<Box*, Box*, CallRewriteArgs*, ArgPassSpec, Box*, Box*, Box*, Box**,
                                const std::vector<BoxedString*>*> tpp_call;
263

264
    bool hasGenericGetattr() {
265
        if (tp_getattr || tp_getattro != object_cls->tp_getattro)
266 267 268 269 270 271 272 273 274
            return false;

        // instancemethod_cls should have a custom tp_getattr but is currently implemented
        // as a hack within getattrInternalGeneric
        if (this == instancemethod_cls)
            return false;

        return true;
    }
275

276 277 278
    // Checks if this class or one of its parents has a non-default tp_dealloc
    bool hasNonDefaultTpDealloc();

279
    void freeze();
280

281 282 283 284 285 286 287 288 289 290 291 292 293 294 295
    static void gcHandler(GCVisitor* v, Box* b);

    typedef size_t SlotOffset;
    SlotOffset* slotOffsets() { return (BoxedClass::SlotOffset*)((char*)this + this->cls->tp_basicsize); }

    // These should only be used for builtin types:
    static BoxedClass* create(BoxedClass* metatype, BoxedClass* base, gcvisit_func gc_visit, int attrs_offset,
                              int weaklist_offset, int instance_size, bool is_user_defined, const char* name);

    BoxedClass(BoxedClass* base, gcvisit_func gc_visit, int attrs_offset, int weaklist_offset, int instance_size,
               bool is_user_defined, const char* name);


    DEFAULT_CLASS_VAR(type_cls, sizeof(SlotOffset));

296 297 298 299 300 301 302
protected:
    // These functions are not meant for external callers and will mostly just be called
    // by BoxedHeapClass::create(), but setupRuntime() also needs to do some manual class
    // creation due to bootstrapping issues.
    void finishInitialization();

    friend void setupRuntime();
303
    friend void setupSysEnd();
304
    friend void setupThread();
305 306
};

307 308 309 310
// Corresponds to PyHeapTypeObject.  Very similar to BoxedClass, but allocates some extra space for
// structures that otherwise might get allocated statically.  For instance, tp_as_number for builtin
// types will usually point to a `static PyNumberMethods` object, but for a heap-allocated class it
// will point to `this->as_number`.
311 312 313 314 315 316 317
class BoxedHeapClass : public BoxedClass {
public:
    PyNumberMethods as_number;
    PyMappingMethods as_mapping;
    PySequenceMethods as_sequence;
    PyBufferProcs as_buffer;

318
    BoxedString* ht_name;
Travis Hance's avatar
slots  
Travis Hance committed
319 320
    PyObject* ht_slots;

321
    size_t nslots() { return this->ob_size; }
322

323
    // These functions are the preferred way to construct new types:
324
    static BoxedHeapClass* create(BoxedClass* metatype, BoxedClass* base, gcvisit_func gc_visit, int attrs_offset,
325
                                  int weaklist_offset, int instance_size, bool is_user_defined, BoxedString* name,
Travis Hance's avatar
slots  
Travis Hance committed
326
                                  BoxedTuple* bases, size_t nslots);
327

328 329 330 331
private:
    // These functions are not meant for external callers and will mostly just be called
    // by BoxedHeapClass::create(), but setupRuntime() also needs to do some manual class
    // creation due to bootstrapping issues.
332 333
    BoxedHeapClass(BoxedClass* base, gcvisit_func gc_visit, int attrs_offset, int weaklist_offset, int instance_size,
                   bool is_user_defined, BoxedString* name);
334

335
    friend void setupRuntime();
336
    friend void setupSys();
337
    friend void setupThread();
338 339
};

340
// Assert that our data structures have the same layout as the C API ones with which they need to be interchangeable.
341 342 343 344 345 346 347 348 349
static_assert(sizeof(pyston::Box) == sizeof(struct _object), "");
static_assert(offsetof(pyston::Box, cls) == offsetof(struct _object, ob_type), "");

static_assert(offsetof(pyston::BoxedClass, cls) == offsetof(struct _typeobject, ob_type), "");
static_assert(offsetof(pyston::BoxedClass, tp_name) == offsetof(struct _typeobject, tp_name), "");
static_assert(offsetof(pyston::BoxedClass, attrs) == offsetof(struct _typeobject, _hcls), "");
static_assert(offsetof(pyston::BoxedClass, gc_visit) == offsetof(struct _typeobject, _gcvisit_func), "");
static_assert(sizeof(pyston::BoxedClass) == sizeof(struct _typeobject), "");

350 351 352 353 354 355
static_assert(offsetof(pyston::BoxedHeapClass, as_number) == offsetof(PyHeapTypeObject, as_number), "");
static_assert(offsetof(pyston::BoxedHeapClass, as_mapping) == offsetof(PyHeapTypeObject, as_mapping), "");
static_assert(offsetof(pyston::BoxedHeapClass, as_sequence) == offsetof(PyHeapTypeObject, as_sequence), "");
static_assert(offsetof(pyston::BoxedHeapClass, as_buffer) == offsetof(PyHeapTypeObject, as_buffer), "");
static_assert(sizeof(pyston::BoxedHeapClass) == sizeof(PyHeapTypeObject), "");

Kevin Modzelewski's avatar
Kevin Modzelewski committed
356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382
template <typename B, bool Nullable = false> struct DecrefHandle {
private:
    B* b;

public:
    DecrefHandle(B* b) : b(b) {}
    ~DecrefHandle() {
        if (Nullable)
            Py_XDECREF(b);
        else
            Py_DECREF(b);
    }
    operator B*() { return b; }
};
template <typename B, bool Nullable = false> DecrefHandle<B, Nullable> autoDecref(B* b) {
    return DecrefHandle<B, Nullable>(b);
}

template <typename B> B* incref(B* b) {
    Py_INCREF(b);
    return b;
}
template <typename B> B* xincref(B* b) {
    Py_XINCREF(b);
    return b;
}

383
class BoxedInt : public Box {
384 385
public:
    int64_t n;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
386

387 388
    BoxedInt(int64_t n) __attribute__((visibility("default"))) : n(n) {}

389
    DEFAULT_CLASS_SIMPLE(int_cls);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
390 391
};

392
class BoxedFloat : public Box {
393 394
public:
    double d;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
395

396 397
    BoxedFloat(double d) __attribute__((visibility("default"))) : d(d) {}

398
    DEFAULT_CLASS_SIMPLE(float_cls);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
399
};
400 401
static_assert(sizeof(BoxedFloat) == sizeof(PyFloatObject), "");
static_assert(offsetof(BoxedFloat, d) == offsetof(PyFloatObject, ob_fval), "");
Kevin Modzelewski's avatar
Kevin Modzelewski committed
402

Travis Hance's avatar
Travis Hance committed
403 404 405 406 407
class BoxedComplex : public Box {
public:
    double real;
    double imag;

408 409
    BoxedComplex(double r, double i) __attribute__((visibility("default"))) : real(r), imag(i) {}

410
    DEFAULT_CLASS_SIMPLE(complex_cls);
Travis Hance's avatar
Travis Hance committed
411 412
};

413
class BoxedBool : public BoxedInt {
414
public:
415 416
    BoxedBool(bool b) __attribute__((visibility("default"))) : BoxedInt(b ? 1 : 0) {}

417
    DEFAULT_CLASS_SIMPLE(bool_cls);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
418 419
};

Travis Hance's avatar
slots  
Travis Hance committed
420
class BoxedString : public BoxVar {
421
public:
422 423 424 425
    // llvm::StringRef is basically just a pointer and a length, so with proper compiler
    // optimizations and inlining, creating a new one each time shouldn't have any cost.
    llvm::StringRef s() const { return llvm::StringRef(s_data, ob_size); };

426
    long hash; // -1 means not yet computed
427
    char interned_state;
428

429
    char* data() { return s_data; }
430 431 432 433
    const char* c_str() {
        assert(data()[size()] == '\0');
        return data();
    }
434
    size_t size() { return this->ob_size; }
435

436 437
    // DEFAULT_CLASS_VAR_SIMPLE doesn't work because of the +1 for the null byte
    void* operator new(size_t size, BoxedClass* cls, size_t nitems) __attribute__((visibility("default"))) {
438
        ALLOC_STATS_VAR(str_cls)
439

440 441
        assert(cls->tp_itemsize == sizeof(char));
        return BoxVar::operator new(size, cls, nitems);
442
    }
443
    void* operator new(size_t size, size_t nitems) __attribute__((visibility("default"))) {
444
        ALLOC_STATS_VAR(str_cls)
Kevin Modzelewski's avatar
Kevin Modzelewski committed
445

446 447
        assert(str_cls->tp_alloc == PystonType_GenericAlloc);
        assert(str_cls->tp_itemsize == 1);
448
        assert(str_cls->tp_basicsize == offsetof(BoxedString, s_data) + 1);
449 450
        assert(str_cls->is_pyston_class);
        assert(str_cls->attrs_offset == 0);
451

452 453
        void* mem = gc_alloc(sizeof(BoxedString) + 1 + nitems, gc::GCKind::PYTHON);
        assert(mem);
454

455 456 457
        BoxVar* rtn = static_cast<BoxVar*>(mem);
        rtn->cls = str_cls;
        rtn->ob_size = nitems;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
458
        _Py_NewReference(rtn);
459 460 461
        return rtn;
    }

462
    // these should be private, but str.cpp needs them
463
    BoxedString(const char* s, size_t n) __attribute__((visibility("default")));
464 465 466 467
    explicit BoxedString(size_t n, char c) __attribute__((visibility("default")));
    explicit BoxedString(llvm::StringRef s) __attribute__((visibility("default")));
    explicit BoxedString(llvm::StringRef lhs, llvm::StringRef rhs) __attribute__((visibility("default")));

468 469 470
    // creates an uninitialized string of length n; useful for directly constructing into the string and avoiding
    // copies:
    static BoxedString* createUninitializedString(ssize_t n) { return new (n) BoxedString(n); }
471
    static BoxedString* createUninitializedString(BoxedClass* cls, ssize_t n) { return new (cls, n) BoxedString(n); }
472 473 474 475 476 477

    // Gets a writeable pointer to the contents of a string.
    // Is only meant to be used with something just created from createUninitializedString(), though
    // in theory it might work in more cases.
    char* getWriteableStringContents() { return s_data; }

478 479
private:
    void* operator new(size_t size) = delete;
480

481 482
    BoxedString(size_t n); // non-initializing constructor

483
    char s_data[0];
484 485

    friend void setupRuntime();
Kevin Modzelewski's avatar
Kevin Modzelewski committed
486 487
};

488
extern "C" size_t strHashUnboxed(BoxedString* self);
489
extern "C" int64_t hashUnboxed(Box* obj);
490

491
class BoxedInstanceMethod : public Box {
492
public:
493 494
    Box** in_weakreflist;

495
    // obj is NULL for unbound instancemethod
496
    Box* obj, *func, *im_class;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
497

498 499
    BoxedInstanceMethod(Box* obj, Box* func, Box* im_class) __attribute__((visibility("default")))
    : in_weakreflist(NULL), obj(obj), func(func), im_class(im_class) {}
500

501
    DEFAULT_CLASS_SIMPLE(instancemethod_cls);
502 503

    static void gcHandler(GCVisitor* v, Box* b);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
504 505
};

506
class GCdArray {
507
public:
508 509 510 511
    Box* elts[0];

    void* operator new(size_t size, int capacity) {
        assert(size == sizeof(GCdArray));
512
        return gc_alloc(capacity * sizeof(Box*) + size, gc::GCKind::UNTRACKED);
513
    }
Kevin Modzelewski's avatar
Kevin Modzelewski committed
514

515 516
    void operator delete(void* p) { gc::gc_free(p); }

517
    static GCdArray* realloc(GCdArray* array, int capacity) {
518
        return (GCdArray*)gc::gc_realloc(array, capacity * sizeof(Box*) + sizeof(GCdArray));
519 520
    }
};
Kevin Modzelewski's avatar
Kevin Modzelewski committed
521

522
class BoxedList : public Box {
523 524 525
private:
    void grow(int min_free);

526
public:
Kevin Modzelewski's avatar
Kevin Modzelewski committed
527
    Py_ssize_t size;
528
    GCdArray* elts;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
529
    Py_ssize_t capacity;
530

531
    BoxedList() __attribute__((visibility("default"))) : size(0), capacity(0) {}
Kevin Modzelewski's avatar
Kevin Modzelewski committed
532

533
    void ensure(int min_free);
534 535
    void shrink();
    static const int INITIAL_CAPACITY;
536

537
    DEFAULT_CLASS_SIMPLE(list_cls);
538 539

    static void gcHandler(GCVisitor* v, Box* b);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
540
};
541 542 543 544 545 546
static_assert(sizeof(BoxedList) <= sizeof(PyListObject), "");
static_assert(sizeof(BoxedList) >= sizeof(PyListObject), "");
static_assert(offsetof(BoxedList, size) == offsetof(PyListObject, ob_size), "");
static_assert(offsetof(BoxedList, elts) == offsetof(PyListObject, ob_item), "");
static_assert(offsetof(GCdArray, elts) == 0, "");
static_assert(offsetof(BoxedList, capacity) == offsetof(PyListObject, allocated), "");
Kevin Modzelewski's avatar
Kevin Modzelewski committed
547

Travis Hance's avatar
slots  
Travis Hance committed
548
class BoxedTuple : public BoxVar {
549
public:
550
    static BoxedTuple* create(int64_t size) {
Kevin Modzelewski's avatar
Kevin Modzelewski committed
551 552
        if (size == 0) {
            Py_INCREF(EmptyTuple);
553
            return EmptyTuple;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
554
        }
555 556 557 558
        BoxedTuple* rtn = new (size) BoxedTuple();
        memset(rtn->elts, 0, size * sizeof(Box*)); // TODO not all callers want this (but some do)
        return rtn;
    }
559
    static BoxedTuple* create(int64_t nelts, Box** elts) {
Kevin Modzelewski's avatar
Kevin Modzelewski committed
560 561
        if (nelts == 0) {
            Py_INCREF(EmptyTuple);
562
            return EmptyTuple;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
563
        }
564
        BoxedTuple* rtn = new (nelts) BoxedTuple();
565
        for (int i = 0; i < nelts; i++) {
566
            assert(gc::isValidGCObject(elts[i]));
567 568
            Py_INCREF(elts[i]);
        }
569 570 571
        memmove(&rtn->elts[0], elts, sizeof(Box*) * nelts);
        return rtn;
    }
572
    static BoxedTuple* create1(Box* elt0) {
573
        BoxedTuple* rtn = new (1) BoxedTuple();
574
        Py_INCREF(elt0);
575
        rtn->elts[0] = elt0;
576 577
        for (int i = 0; i < rtn->size(); i++)
            assert(gc::isValidGCObject(rtn->elts[i]));
578 579 580
        return rtn;
    }
    static BoxedTuple* create2(Box* elt0, Box* elt1) {
581
        BoxedTuple* rtn = new (2) BoxedTuple();
582 583
        Py_INCREF(elt0);
        Py_INCREF(elt1);
584 585
        rtn->elts[0] = elt0;
        rtn->elts[1] = elt1;
586 587
        for (int i = 0; i < rtn->size(); i++)
            assert(gc::isValidGCObject(rtn->elts[i]));
588 589 590
        return rtn;
    }
    static BoxedTuple* create3(Box* elt0, Box* elt1, Box* elt2) {
591
        BoxedTuple* rtn = new (3) BoxedTuple();
592 593 594
        Py_INCREF(elt0);
        Py_INCREF(elt1);
        Py_INCREF(elt2);
595 596 597
        rtn->elts[0] = elt0;
        rtn->elts[1] = elt1;
        rtn->elts[2] = elt2;
598 599
        for (int i = 0; i < rtn->size(); i++)
            assert(gc::isValidGCObject(rtn->elts[i]));
600 601
        return rtn;
    }
602
    static BoxedTuple* create4(Box* elt0, Box* elt1, Box* elt2, Box* elt3) {
603
        BoxedTuple* rtn = new (4) BoxedTuple();
604 605 606 607
        Py_INCREF(elt0);
        Py_INCREF(elt1);
        Py_INCREF(elt2);
        Py_INCREF(elt3);
608 609 610 611
        rtn->elts[0] = elt0;
        rtn->elts[1] = elt1;
        rtn->elts[2] = elt2;
        rtn->elts[3] = elt3;
612 613
        for (int i = 0; i < rtn->size(); i++)
            assert(gc::isValidGCObject(rtn->elts[i]));
614 615 616
        return rtn;
    }
    static BoxedTuple* create5(Box* elt0, Box* elt1, Box* elt2, Box* elt3, Box* elt4) {
617
        BoxedTuple* rtn = new (5) BoxedTuple();
618 619 620 621 622
        Py_INCREF(elt0);
        Py_INCREF(elt1);
        Py_INCREF(elt2);
        Py_INCREF(elt3);
        Py_INCREF(elt4);
623 624 625 626 627
        rtn->elts[0] = elt0;
        rtn->elts[1] = elt1;
        rtn->elts[2] = elt2;
        rtn->elts[3] = elt3;
        rtn->elts[4] = elt4;
628 629 630 631
        for (int i = 0; i < rtn->size(); i++)
            assert(gc::isValidGCObject(rtn->elts[i]));
        return rtn;
    }
632 633
    static BoxedTuple* create6(Box* elt0, Box* elt1, Box* elt2, Box* elt3, Box* elt4, Box* elt5) {
        BoxedTuple* rtn = new (6) BoxedTuple();
634 635 636 637 638 639
        Py_INCREF(elt0);
        Py_INCREF(elt1);
        Py_INCREF(elt2);
        Py_INCREF(elt3);
        Py_INCREF(elt4);
        Py_INCREF(elt5);
640 641 642 643 644 645 646 647 648 649
        rtn->elts[0] = elt0;
        rtn->elts[1] = elt1;
        rtn->elts[2] = elt2;
        rtn->elts[3] = elt3;
        rtn->elts[4] = elt4;
        rtn->elts[5] = elt5;
        for (int i = 0; i < rtn->size(); i++)
            assert(gc::isValidGCObject(rtn->elts[i]));
        return rtn;
    }
650 651 652 653 654
    static BoxedTuple* create(std::initializer_list<Box*> members) {
        auto rtn = new (members.size()) BoxedTuple(members);

        for (int i = 0; i < rtn->size(); i++)
            assert(gc::isValidGCObject(rtn->elts[i]));
655 656
        return rtn;
    }
657

658
    static BoxedTuple* create(int64_t size, BoxedClass* cls) {
659
        BoxedTuple* rtn;
660
        if (cls == tuple_cls)
661
            rtn = new (size) BoxedTuple();
662
        else
663 664 665
            rtn = new (cls, size) BoxedTuple();
        memset(rtn->elts, 0, size * sizeof(Box*)); // TODO not all callers want this (but some do)
        return rtn;
666
    }
667
    static BoxedTuple* create(int64_t nelts, Box** elts, BoxedClass* cls) {
668 669
        BoxedTuple* rtn;
        if (cls == tuple_cls)
670
            rtn = new (nelts) BoxedTuple();
671
        else
672
            rtn = new (cls, nelts) BoxedTuple();
673 674 675
        for (int i = 0; i < nelts; i++) {
            Py_INCREF(elts[i]);
        }
676 677 678 679
        memmove(&rtn->elts[0], elts, sizeof(Box*) * nelts);
        return rtn;
    }
    static BoxedTuple* create(std::initializer_list<Box*> members, BoxedClass* cls) {
680 681 682 683
        if (cls == tuple_cls)
            return new (members.size()) BoxedTuple(members);
        else
            return new (cls, members.size()) BoxedTuple(members);
684 685 686 687
    }

    static int Resize(BoxedTuple** pt, size_t newsize) noexcept;

688 689
    Box* const* begin() const { return &elts[0]; }
    Box* const* end() const { return &elts[ob_size]; }
Travis Hance's avatar
slots  
Travis Hance committed
690
    Box*& operator[](size_t index) { return elts[index]; }
691

692
    size_t size() const { return ob_size; }
693

694 695 696 697 698 699 700
    // DEFAULT_CLASS_VAR_SIMPLE doesn't work because of declaring 1 element in 'elts'
    void* operator new(size_t size, BoxedClass* cls, size_t nitems) __attribute__((visibility("default"))) {
        ALLOC_STATS_VAR(tuple_cls)

        assert(cls->tp_itemsize == sizeof(Box*));
        return BoxVar::operator new(size, cls, nitems);
    }
701

702 703 704 705 706 707 708 709 710
    void* operator new(size_t size, size_t nitems) __attribute__((visibility("default"))) {
        ALLOC_STATS_VAR(tuple_cls)

        assert(tuple_cls->tp_alloc == PystonType_GenericAlloc);
        assert(tuple_cls->tp_itemsize == sizeof(Box*));
        assert(tuple_cls->tp_basicsize == offsetof(BoxedTuple, elts));
        assert(tuple_cls->is_pyston_class);
        assert(tuple_cls->attrs_offset == 0);

711
        void* mem = gc_alloc(offsetof(BoxedTuple, elts) + nitems * sizeof(Box*), gc::GCKind::PYTHON);
712 713 714 715 716
        assert(mem);

        BoxVar* rtn = static_cast<BoxVar*>(mem);
        rtn->cls = tuple_cls;
        rtn->ob_size = nitems;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
717
        _Py_NewReference(rtn);
718 719 720
        return rtn;
    }

721 722
    static void gcHandler(GCVisitor* v, Box* b);

723
private:
724
    BoxedTuple() {}
725

726
    BoxedTuple(std::initializer_list<Box*>& members) {
727 728 729
        // by the time we make it here elts[] is big enough to contain members
        Box** p = &elts[0];
        for (auto b : members) {
730
            Py_INCREF(b);
731
            *p++ = b;
732
            assert(gc::isValidGCObject(b));
733 734
        }
    }
735 736

public:
737 738 739
    // CPython declares ob_item (their version of elts) to have 1 element.  We want to
    // copy that behavior so that the sizes of the objects match, but we want to also
    // have a zero-length array in there since we have some extra compiler warnings turned
740
    // on:  _elts[1] will throw an error, but elts[1] will not.
741 742 743 744
    union {
        Box* elts[0];
        Box* _elts[1];
    };
Kevin Modzelewski's avatar
Kevin Modzelewski committed
745
};
746 747 748
static_assert(sizeof(BoxedTuple) == sizeof(PyTupleObject), "");
static_assert(offsetof(BoxedTuple, ob_size) == offsetof(PyTupleObject, ob_size), "");
static_assert(offsetof(BoxedTuple, elts) == offsetof(PyTupleObject, ob_item), "");
749

750
extern BoxedString* characters[UCHAR_MAX + 1];
Kevin Modzelewski's avatar
Kevin Modzelewski committed
751

752
// C++ functor objects that implement Python semantics.
Kevin Modzelewski's avatar
Kevin Modzelewski committed
753
struct PyHasher {
754 755 756 757 758 759 760 761 762
    size_t operator()(Box* b) const {
        if (b->cls == str_cls) {
            auto s = static_cast<BoxedString*>(b);
            if (s->hash != -1)
                return s->hash;
            return strHashUnboxed(s);
        }
        return hashUnboxed(b);
    }
Kevin Modzelewski's avatar
Kevin Modzelewski committed
763 764 765
};

struct PyEq {
766 767 768 769 770 771
    bool operator()(Box* lhs, Box* rhs) const {
        int r = PyObject_RichCompareBool(lhs, rhs, Py_EQ);
        if (r == -1)
            throwCAPIException();
        return (bool)r;
    }
Kevin Modzelewski's avatar
Kevin Modzelewski committed
772 773 774
};

struct PyLt {
775 776 777 778 779 780
    bool operator()(Box* lhs, Box* rhs) const {
        int r = PyObject_RichCompareBool(lhs, rhs, Py_LT);
        if (r == -1)
            throwCAPIException();
        return (bool)r;
    }
Kevin Modzelewski's avatar
Kevin Modzelewski committed
781 782
};

783 784
// llvm::DenseMap doesn't store the original hash values, choosing to instead
// check for equality more often.  This is probably a good tradeoff when the keys
785 786 787 788 789
// are pointers and comparison is cheap, but when the equality function is user-defined
// it can be much faster to avoid Python function invocations by doing some integer
// comparisons.
// This also has a user-visible behavior difference of how many times the hash function
// and equality functions get called.
790 791 792 793 794 795
struct BoxAndHash {
    Box* value;
    size_t hash;

    BoxAndHash(Box* value) : value(value), hash(PyHasher()(value)) {}
    BoxAndHash(Box* value, size_t hash) : value(value), hash(hash) {}
796 797 798 799 800 801 802 803 804 805 806 807 808 809 810

    struct Comparisons {
        static bool isEqual(BoxAndHash lhs, BoxAndHash rhs) {
            if (lhs.value == rhs.value)
                return true;
            if (rhs.value == (Box*)-1 || rhs.value == (Box*)-2)
                return false;
            if (lhs.hash != rhs.hash)
                return false;
            return PyEq()(lhs.value, rhs.value);
        }
        static BoxAndHash getEmptyKey() { return BoxAndHash((Box*)-1, 0); }
        static BoxAndHash getTombstoneKey() { return BoxAndHash((Box*)-2, 0); }
        static unsigned getHashValue(BoxAndHash val) { return val.hash; }
    };
811
};
812

813 814
class BoxedDict : public Box {
public:
815 816
    typedef pyston::DenseMap<BoxAndHash, Box*, BoxAndHash::Comparisons, detail::DenseMapPair<BoxAndHash, Box*>,
                             /* MinSize= */ 8> DictMap;
817 818

    DictMap d;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
819

820 821
    BoxedDict() __attribute__((visibility("default"))) {}

822
    DEFAULT_CLASS_SIMPLE(dict_cls);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
823 824

    Box* getOrNull(Box* k) {
825
        const auto& p = d.find(BoxAndHash(k));
Kevin Modzelewski's avatar
Kevin Modzelewski committed
826 827 828 829
        if (p != d.end())
            return p->second;
        return NULL;
    }
830

831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850
    class iterator {
    private:
        DictMap::iterator it;

    public:
        iterator(DictMap::iterator it) : it(std::move(it)) {}

        bool operator!=(const iterator& rhs) const { return it != rhs.it; }
        bool operator==(const iterator& rhs) const { return it == rhs.it; }
        iterator& operator++() {
            ++it;
            return *this;
        }
        std::pair<Box*, Box*> operator*() const { return std::make_pair(it->first.value, it->second); }
        Box* first() const { return it->first.value; }
    };

    iterator begin() { return iterator(d.begin()); }
    iterator end() { return iterator(d.end()); }

851
    static void gcHandler(GCVisitor* v, Box* b);
852
    static void dealloc(Box* b) noexcept;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
853
};
Kevin Modzelewski's avatar
Kevin Modzelewski committed
854
static_assert(sizeof(BoxedDict) == sizeof(PyDictObject), "");
Kevin Modzelewski's avatar
Kevin Modzelewski committed
855

Travis Hance's avatar
Travis Hance committed
856
class BoxedFunctionBase : public Box {
857
public:
858 859
    Box** in_weakreflist;

860
    FunctionMetadata* md;
861 862 863 864 865

    // TODO these should really go in BoxedFunction but it's annoying because they don't get
    // initializd until after BoxedFunctionBase's constructor is run which means they could have
    // garbage values when the GC is run (BoxedFunctionBase's constructor might call the GC).
    // So ick... needs to be fixed.
Kevin Modzelewski's avatar
Kevin Modzelewski committed
866
    BoxedClosure* closure;
867
    Box* globals;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
868

869 870
    BoxedTuple* defaults;
    bool can_change_defaults;
871

872 873
    ICInvalidator dependent_ics;

874
    // Accessed via member descriptor
875 876
    Box* modname;      // __module__
    BoxedString* name; // __name__ (should be here or in one of the derived classes?)
877
    Box* doc;          // __doc__
878

879 880
    BoxedFunctionBase(FunctionMetadata* md);
    BoxedFunctionBase(FunctionMetadata* md, std::initializer_list<Box*> defaults, BoxedClosure* closure = NULL,
881 882 883
                      Box* globals = NULL, bool can_change_defaults = false);

    ParamReceiveSpec getParamspec() {
884
        return ParamReceiveSpec(md->num_args, defaults ? defaults->size() : 0, md->takes_varargs, md->takes_kwargs);
885
    }
Travis Hance's avatar
Travis Hance committed
886 887 888 889
};

class BoxedFunction : public BoxedFunctionBase {
public:
890 891
    HCAttrs attrs;

892 893
    BoxedFunction(FunctionMetadata* md);
    BoxedFunction(FunctionMetadata* md, std::initializer_list<Box*> defaults, BoxedClosure* closure = NULL,
894
                  Box* globals = NULL, bool can_change_defaults = false);
895 896

    DEFAULT_CLASS(function_cls);
897 898

    static void gcHandler(GCVisitor* v, Box* b);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
899 900
};

Travis Hance's avatar
Travis Hance committed
901 902
class BoxedBuiltinFunctionOrMethod : public BoxedFunctionBase {
public:
903 904
    BoxedBuiltinFunctionOrMethod(FunctionMetadata* f, const char* name, const char* doc = NULL);
    BoxedBuiltinFunctionOrMethod(FunctionMetadata* f, const char* name, std::initializer_list<Box*> defaults,
905
                                 BoxedClosure* closure = NULL, const char* doc = NULL);
Travis Hance's avatar
Travis Hance committed
906 907 908 909

    DEFAULT_CLASS(builtin_function_or_method_cls);
};

910 911 912
class BoxedModule : public Box {
public:
    HCAttrs attrs;
913

Travis Hance's avatar
Travis Hance committed
914
    FutureFlags future_flags;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
915

916
    BoxedModule() {} // noop constructor to disable zero-initialization of cls
917
    std::string name();
918

919
    BoxedString* getStringConstant(llvm::StringRef ast_str, bool intern = false);
920 921 922 923 924 925 926
    Box* getUnicodeConstant(llvm::StringRef ast_str);
    BoxedInt* getIntConstant(int64_t n);
    BoxedFloat* getFloatConstant(double d);
    Box* getPureImaginaryConstant(double d);
    Box* getLongConstant(llvm::StringRef s);

    static void gcHandler(GCVisitor* v, Box* self);
927

928 929 930 931 932 933 934 935
private:
    ContiguousMap<llvm::StringRef, BoxedString*, llvm::StringMap<int>> str_constants;
    ContiguousMap<llvm::StringRef, Box*, llvm::StringMap<int>> unicode_constants;
    // Note: DenseMap doesn't work here since we don't prevent the tombstone/empty
    // keys from reaching it.
    ContiguousMap<int64_t, BoxedInt*, std::unordered_map<int64_t, int>> int_constants;
    // I'm not sure how well it works to use doubles as hashtable keys; thankfully
    // it's not a big deal if we get misses.
936 937
    ContiguousMap<int64_t, BoxedFloat*, std::unordered_map<int64_t, int>> float_constants;
    ContiguousMap<int64_t, Box*, std::unordered_map<int64_t, int>> imaginary_constants;
938
    ContiguousMap<llvm::StringRef, Box*, llvm::StringMap<int>> long_constants;
939 940
    // Other objects that this module needs to keep alive; see getStringConstant.
    llvm::SmallVector<Box*, 8> keep_alive;
941

942
public:
943
    DEFAULT_CLASS(module_cls);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
944 945
};

946
class BoxedSlice : public Box {
947 948
public:
    Box* start, *stop, *step;
949 950
    BoxedSlice(Box* lower, Box* upper, Box* step) : start(lower), stop(upper), step(step) {}

951
    DEFAULT_CLASS_SIMPLE(slice_cls);
952 953

    static void gcHandler(GCVisitor* v, Box* b);
954
};
955 956 957 958
static_assert(sizeof(BoxedSlice) == sizeof(PySliceObject), "");
static_assert(offsetof(BoxedSlice, start) == offsetof(PySliceObject, start), "");
static_assert(offsetof(BoxedSlice, stop) == offsetof(PySliceObject, stop), "");
static_assert(offsetof(BoxedSlice, step) == offsetof(PySliceObject, step), "");
959 960 961 962

class BoxedMemberDescriptor : public Box {
public:
    enum MemberType {
963 964
        BOOL = T_BOOL,
        BYTE = T_BYTE,
965
        INT = T_INT,
966
        OBJECT = T_OBJECT,
967
        OBJECT_EX = T_OBJECT_EX,
968
        FLOAT = T_FLOAT,
969 970 971 972 973 974 975 976 977 978 979 980 981
        SHORT = T_SHORT,
        LONG = T_LONG,
        DOUBLE = T_DOUBLE,
        STRING = T_STRING,
        STRING_INPLACE = T_STRING_INPLACE,
        CHAR = T_CHAR,
        UBYTE = T_UBYTE,
        USHORT = T_USHORT,
        UINT = T_UINT,
        ULONG = T_ULONG,
        LONGLONG = T_LONGLONG,
        ULONGLONG = T_ULONGLONG,
        PYSSIZET = T_PYSSIZET
982 983 984
    } type;

    int offset;
985
    bool readonly;
986

987 988 989 990
    BoxedMemberDescriptor(MemberType type, int offset, bool readonly = true)
        : type(type), offset(offset), readonly(readonly) {}
    BoxedMemberDescriptor(PyMemberDef* member)
        : type((MemberType)member->type), offset(member->offset), readonly(member->flags & READONLY) {}
991

992
    DEFAULT_CLASS_SIMPLE(member_descriptor_cls);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
993 994
};

995 996 997
class BoxedGetsetDescriptor : public Box {
public:
    Box* (*get)(Box*, void*);
998
    void (*set)(Box*, Box*, void*);
999 1000
    void* closure;

1001
    BoxedGetsetDescriptor(Box* (*get)(Box*, void*), void (*set)(Box*, Box*, void*), void* closure)
1002 1003
        : get(get), set(set), closure(closure) {}

1004
    // No DEFAULT_CLASS annotation here -- force callers to explicitly specifiy pyston_getset_cls or capi_getset_cls
1005 1006
};

Travis Hance's avatar
Travis Hance committed
1007 1008 1009 1010 1011 1012
class BoxedProperty : public Box {
public:
    Box* prop_get;
    Box* prop_set;
    Box* prop_del;
    Box* prop_doc;
1013
    bool getter_doc;
Travis Hance's avatar
Travis Hance committed
1014 1015

    BoxedProperty(Box* get, Box* set, Box* del, Box* doc)
1016 1017
        : prop_get(get), prop_set(set), prop_del(del), prop_doc(doc) {}

1018
    DEFAULT_CLASS_SIMPLE(property_cls);
1019 1020

    static void gcHandler(GCVisitor* v, Box* b);
Travis Hance's avatar
Travis Hance committed
1021 1022
};

Travis Hance's avatar
Travis Hance committed
1023 1024 1025 1026
class BoxedStaticmethod : public Box {
public:
    Box* sm_callable;

1027 1028
    BoxedStaticmethod(Box* callable) : sm_callable(callable){};

1029
    DEFAULT_CLASS_SIMPLE(staticmethod_cls);
1030 1031

    static void gcHandler(GCVisitor* v, Box* b);
Travis Hance's avatar
Travis Hance committed
1032 1033 1034 1035 1036 1037
};

class BoxedClassmethod : public Box {
public:
    Box* cm_callable;

1038 1039
    BoxedClassmethod(Box* callable) : cm_callable(callable){};

1040
    DEFAULT_CLASS_SIMPLE(classmethod_cls);
1041 1042

    static void gcHandler(GCVisitor* v, Box* b);
Travis Hance's avatar
Travis Hance committed
1043 1044
};

Travis Hance's avatar
Travis Hance committed
1045
// TODO is there any particular reason to make this a Box, i.e. a python-level object?
Kevin Modzelewski's avatar
Kevin Modzelewski committed
1046 1047 1048
class BoxedClosure : public Box {
public:
    BoxedClosure* parent;
Travis Hance's avatar
Travis Hance committed
1049 1050
    size_t nelts;
    Box* elts[0];
Kevin Modzelewski's avatar
Kevin Modzelewski committed
1051

1052 1053
    BoxedClosure(BoxedClosure* parent) : parent(parent) {}

Travis Hance's avatar
Travis Hance committed
1054 1055 1056 1057 1058 1059 1060 1061 1062
    void* operator new(size_t size, size_t nelts) __attribute__((visibility("default"))) {
        /*
        BoxedClosure* rtn
            = static_cast<BoxedClosure*>(gc_alloc(_PyObject_VAR_SIZE(closure_cls, nelts), gc::GCKind::PYTHON));
            */
        BoxedClosure* rtn
            = static_cast<BoxedClosure*>(gc_alloc(sizeof(BoxedClosure) + nelts * sizeof(Box*), gc::GCKind::PYTHON));
        rtn->nelts = nelts;
        rtn->cls = closure_cls;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
1063
        _Py_NewReference(rtn);
Travis Hance's avatar
Travis Hance committed
1064 1065 1066
        memset((void*)rtn->elts, 0, sizeof(Box*) * nelts);
        return rtn;
    }
1067 1068

    static void gcHandler(GCVisitor* v, Box* b);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
1069 1070
};

Marius Wachtler's avatar
Marius Wachtler committed
1071 1072
class BoxedGenerator : public Box {
public:
1073 1074
    Box** weakreflist;

Travis Hance's avatar
Travis Hance committed
1075
    BoxedFunctionBase* function;
1076 1077
    Box* arg1, *arg2, *arg3;
    GCdArray* args;
Marius Wachtler's avatar
Marius Wachtler committed
1078 1079

    bool entryExited;
1080
    bool running;
Marius Wachtler's avatar
Marius Wachtler committed
1081
    Box* returnValue;
1082
    bool iterated_from__hasnext__;
1083
    ExcInfo exception;
Marius Wachtler's avatar
Marius Wachtler committed
1084

1085
    struct Context* context, *returnContext;
1086
    void* stack_begin;
Marius Wachtler's avatar
Marius Wachtler committed
1087

1088
#if STAT_TIMERS
1089 1090
    StatTimer* prev_stack;
    StatTimer my_timer;
1091 1092
#endif

Travis Hance's avatar
Travis Hance committed
1093
    BoxedGenerator(BoxedFunctionBase* function, Box* arg1, Box* arg2, Box* arg3, Box** args);
1094 1095

    DEFAULT_CLASS(generator_cls);
1096 1097

    static void gcHandler(GCVisitor* v, Box* b);
Marius Wachtler's avatar
Marius Wachtler committed
1098 1099
};

1100 1101 1102 1103 1104 1105 1106
struct wrapper_def {
    const llvm::StringRef name;
    int offset;
    void* function;      // "generic" handler that gets put in the tp_* slot which proxies to the python version
    wrapperfunc wrapper; // "wrapper" that ends up getting called by the Python-visible WrapperDescr
    const llvm::StringRef doc;
    int flags;
1107
    BoxedString* name_strobj;
1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121
};

class BoxedWrapperDescriptor : public Box {
public:
    const wrapper_def* wrapper;
    BoxedClass* type;
    void* wrapped;
    BoxedWrapperDescriptor(const wrapper_def* wrapper, BoxedClass* type, void* wrapped)
        : wrapper(wrapper), type(type), wrapped(wrapped) {}

    DEFAULT_CLASS(wrapperdescr_cls);

    static Box* descr_get(Box* self, Box* inst, Box* owner) noexcept;
    static Box* __call__(BoxedWrapperDescriptor* descr, PyObject* self, BoxedTuple* args, Box** _args);
1122 1123 1124
    template <ExceptionStyle S>
    static Box* tppCall(Box* _self, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* arg3,
                        Box** args, const std::vector<BoxedString*>* keyword_names) noexcept(S == CAPI);
1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138

    static void gcHandler(GCVisitor* v, Box* _o);
};

class BoxedWrapperObject : public Box {
public:
    BoxedWrapperDescriptor* descr;
    Box* obj;

    BoxedWrapperObject(BoxedWrapperDescriptor* descr, Box* obj) : descr(descr), obj(obj) {}

    DEFAULT_CLASS(wrapperobject_cls);

    static Box* __call__(BoxedWrapperObject* self, Box* args, Box* kwds);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
1139
    template <ExceptionStyle S>
1140
    static Box* tppCall(Box* _self, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* arg3,
Kevin Modzelewski's avatar
Kevin Modzelewski committed
1141
                        Box** args, const std::vector<BoxedString*>* keyword_names) noexcept(S == CAPI);
1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153
    static void gcHandler(GCVisitor* v, Box* _o);
};

class BoxedMethodDescriptor : public Box {
public:
    PyMethodDef* method;
    BoxedClass* type;

    BoxedMethodDescriptor(PyMethodDef* method, BoxedClass* type) : method(method), type(type) {}

    DEFAULT_CLASS(method_cls);

Kevin Modzelewski's avatar
Kevin Modzelewski committed
1154
    static Box* descr_get(BoxedMethodDescriptor* self, Box* inst, Box* owner) noexcept;
1155
    static Box* __call__(BoxedMethodDescriptor* self, Box* obj, BoxedTuple* varargs, Box** _args);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
1156
    template <ExceptionStyle S>
1157
    static Box* tppCall(Box* _self, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* arg3,
Kevin Modzelewski's avatar
Kevin Modzelewski committed
1158
                        Box** args, const std::vector<BoxedString*>* keyword_names) noexcept(S == CAPI);
1159 1160 1161
    static void gcHandler(GCVisitor* v, Box* _o);
};

1162
Box* objectSetattr(Box* obj, Box* attr, Box* value);
1163

1164
Box* unwrapAttrWrapper(Box* b);
1165
Box* attrwrapperKeys(Box* b);
1166
void attrwrapperDel(Box* b, llvm::StringRef attr);
1167
BoxedDict* attrwrapperToDict(Box* b);
1168

1169 1170 1171
Box* boxAst(AST* ast);
AST* unboxAst(Box* b);

1172
// Our default for tp_alloc:
1173
extern "C" PyObject* PystonType_GenericAlloc(BoxedClass* cls, Py_ssize_t nitems) noexcept;
1174

Kevin Modzelewski's avatar
Kevin Modzelewski committed
1175 1176 1177 1178 1179 1180 1181 1182
#define fatalOrError(exception, message)                                                                               \
    do {                                                                                                               \
        if (CONTINUE_AFTER_FATAL)                                                                                      \
            PyErr_SetString((exception), (message));                                                                   \
        else                                                                                                           \
            Py_FatalError((message));                                                                                  \
    } while (0)

1183 1184 1185 1186
// A descriptor that you can add to your class to provide instances with a __dict__ accessor.
// Classes created in Python get this automatically, but builtin types (including extension types)
// are supposed to add one themselves.  type_cls and function_cls do this, for example.
extern Box* dict_descr;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
1187 1188

Box* codeForFunction(BoxedFunction*);
1189
Box* codeForFunctionMetadata(FunctionMetadata*);
1190
FunctionMetadata* metadataFromCode(Box* code);
1191 1192

Box* getFrame(int depth);
1193 1194 1195

inline BoxedString* boxString(llvm::StringRef s) {
    if (s.size() <= 1) {
Kevin Modzelewski's avatar
Kevin Modzelewski committed
1196
        BoxedString* r;
1197
        if (s.size() == 0)
Kevin Modzelewski's avatar
Kevin Modzelewski committed
1198 1199 1200 1201 1202
            r = EmptyString;
        else
            r = characters[s.data()[0] & UCHAR_MAX];
        Py_INCREF(r);
        return r;
1203 1204 1205
    }
    return new (s.size()) BoxedString(s);
}
1206 1207 1208 1209 1210

#define NUM_INTERNED_INTS 100
extern BoxedInt* interned_ints[NUM_INTERNED_INTS];
extern "C" inline Box* boxInt(int64_t n) {
    if (0 <= n && n < NUM_INTERNED_INTS) {
Kevin Modzelewski's avatar
Kevin Modzelewski committed
1211 1212 1213
        auto r = interned_ints[n];
        Py_INCREF(r);
        return r;
1214 1215 1216
    }
    return new BoxedInt(n);
}
1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227

// Helper function: fetch an arg from our calling convention
inline Box*& getArg(int idx, Box*& arg1, Box*& arg2, Box*& arg3, Box** args) {
    if (idx == 0)
        return arg1;
    if (idx == 1)
        return arg2;
    if (idx == 2)
        return arg3;
    return args[idx - 3];
}
Kevin Modzelewski's avatar
Kevin Modzelewski committed
1228

Kevin Modzelewski's avatar
Kevin Modzelewski committed
1229
inline BoxedString* getStaticString(llvm::StringRef s) {
Kevin Modzelewski's avatar
Kevin Modzelewski committed
1230 1231 1232 1233
    BoxedString* r = internStringImmortal(s);
    constants.push_back(r);
    return r;
}
Kevin Modzelewski's avatar
Kevin Modzelewski committed
1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245

inline Box* Box::getattrString(const char* attr) {
    // XXX need to auto-decref
    BoxedString* s = internStringMortal(attr);
    try {
        Box* r =  getattr<NOT_REWRITABLE>(s, NULL);
        Py_DECREF(s);
        return r;
    } catch (ExcInfo e) {
        Py_DECREF(s);
        throw e;
    }
Kevin Modzelewski's avatar
Kevin Modzelewski committed
1246
}
1247

Kevin Modzelewski's avatar
Kevin Modzelewski committed
1248 1249
} // namespace pyston

Kevin Modzelewski's avatar
Kevin Modzelewski committed
1250
#endif