types.cpp 152 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
// Licensed under the Apache License, Version 2.0 (the "License");
Travis Hance's avatar
Travis Hance committed
4
// 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
5
//
Kevin Modzelewski's avatar
Kevin Modzelewski committed
6
//    http://www.apache.org/licenses/LICENSE-2.0
Kevin Modzelewski's avatar
Kevin Modzelewski committed
7
//
Kevin Modzelewski's avatar
Kevin Modzelewski committed
8 9 10 11 12 13
// 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.

14 15
#define PY_SSIZE_T_CLEAN

16 17
#include "runtime/types.h"

Kevin Modzelewski's avatar
Kevin Modzelewski committed
18
#include <cassert>
19
#include <cstddef>
Kevin Modzelewski's avatar
Kevin Modzelewski committed
20 21 22
#include <cstdio>
#include <cstdlib>
#include <cstring>
23
#include <stdint.h>
Kevin Modzelewski's avatar
Kevin Modzelewski committed
24

25 26
#include "llvm/Support/raw_ostream.h"

27
#include "analysis/scoping_analysis.h"
28
#include "capi/typeobject.h"
29
#include "capi/types.h"
30
#include "codegen/ast_interpreter.h"
Kevin Modzelewski's avatar
Kevin Modzelewski committed
31
#include "codegen/entry.h"
32
#include "codegen/unwinding.h"
33
#include "core/ast.h"
Kevin Modzelewski's avatar
Kevin Modzelewski committed
34 35 36
#include "core/options.h"
#include "core/stats.h"
#include "core/types.h"
37
#include "runtime/classobj.h"
38
#include "runtime/code.h"
39
#include "runtime/complex.h"
40
#include "runtime/dict.h"
41
#include "runtime/file.h"
42
#include "runtime/hiddenclass.h"
43
#include "runtime/ics.h"
44
#include "runtime/iterobject.h"
Kevin Modzelewski's avatar
Kevin Modzelewski committed
45
#include "runtime/list.h"
46
#include "runtime/long.h"
Kevin Modzelewski's avatar
Kevin Modzelewski committed
47
#include "runtime/objmodel.h"
48
#include "runtime/rewrite_args.h"
Kevin Modzelewski's avatar
Kevin Modzelewski committed
49
#include "runtime/set.h"
50
#include "runtime/super.h"
51
#include "runtime/traceback.h"
Marius Wachtler's avatar
Marius Wachtler committed
52
#include "runtime/util.h"
Kevin Modzelewski's avatar
Kevin Modzelewski committed
53

54
extern "C" void initerrno();
55
extern "C" void init_sha();
56 57
extern "C" void init_sha256();
extern "C" void init_sha512();
58
extern "C" void init_md5();
Marius Wachtler's avatar
Marius Wachtler committed
59
extern "C" void init_random();
60
extern "C" void init_sre();
Marius Wachtler's avatar
Marius Wachtler committed
61
extern "C" void initmath();
62
extern "C" void initoperator();
Kevin Modzelewski's avatar
Kevin Modzelewski committed
63
extern "C" void initbinascii();
64
extern "C" void initpwd();
65
extern "C" void initposix();
66
extern "C" void init_struct();
Kevin Modzelewski's avatar
Kevin Modzelewski committed
67
extern "C" void initdatetime();
Kevin Modzelewski's avatar
Kevin Modzelewski committed
68
extern "C" void init_functools();
69
extern "C" void init_collections();
Kevin Modzelewski's avatar
Kevin Modzelewski committed
70
extern "C" void inititertools();
71
extern "C" void initresource();
Kevin Modzelewski's avatar
Kevin Modzelewski committed
72
extern "C" void initsignal();
73
extern "C" void initselect();
Kevin Modzelewski's avatar
Kevin Modzelewski committed
74
extern "C" void initfcntl();
75
extern "C" void inittime();
Marius Wachtler's avatar
Marius Wachtler committed
76
extern "C" void initarray();
Kevin Modzelewski's avatar
Kevin Modzelewski committed
77
extern "C" void initzlib();
78
extern "C" void init_codecs();
Kevin Modzelewski's avatar
Kevin Modzelewski committed
79
extern "C" void init_socket();
80
extern "C" void _PyUnicode_Init();
81
extern "C" void initunicodedata();
82
extern "C" void init_weakref();
Marius Wachtler's avatar
Marius Wachtler committed
83
extern "C" void initcStringIO();
84
extern "C" void init_io();
85
extern "C" void initzipimport();
Marius Wachtler's avatar
Marius Wachtler committed
86
extern "C" void init_csv();
Marius Wachtler's avatar
Marius Wachtler committed
87
extern "C" void init_ssl();
88
extern "C" void init_sqlite3();
89
extern "C" void PyMarshal_Init();
90
extern "C" void initstrop();
91

Kevin Modzelewski's avatar
Kevin Modzelewski committed
92 93
namespace pyston {

94 95
void setupGC();

96 97
std::vector<BoxedClass*> exception_types;

98
void FrameInfo::gcVisit(GCVisitor* visitor) {
99 100 101 102 103
    visitor->visit(&boxedLocals);
    visitor->visit(&exc.traceback);
    visitor->visit(&exc.type);
    visitor->visit(&exc.value);
    visitor->visit(&frame_obj);
104 105
}

106
// Analogue of PyType_GenericAlloc (default tp_alloc), but should only be used for Pyston classes!
107
extern "C" PyObject* PystonType_GenericAlloc(BoxedClass* cls, Py_ssize_t nitems) noexcept {
108 109
    assert(cls);

110 111
    // See PyType_GenericAlloc for note about the +1 here:
    const size_t size = _PyObject_VAR_SIZE(cls, nitems + 1);
112

113 114 115 116 117 118 119 120 121
#ifndef NDEBUG
#if 0
    assert(cls->tp_bases);
    // TODO this should iterate over all subclasses
    for (auto e : cls->tp_bases->pyElements()) {
        assert(e->cls == type_cls); // what about old style classes?
        assert(static_cast<BoxedClass*>(e)->is_pyston_class);
    }
#endif
122
    if (!cls->tp_mro) {
123 124
        // wrapperdescr_cls is the last class to be set up during bootstrapping:
        ASSERT(!wrapperdescr_cls, "looks like we need to set up the mro for %s manually", cls->tp_name);
125 126 127
    } else {
        assert(cls->tp_mro && "maybe we should just skip these checks if !mro");
        assert(cls->tp_mro->cls == tuple_cls);
128
        for (auto b : *static_cast<BoxedTuple*>(cls->tp_mro)) {
129 130 131
            // old-style classes are always pyston classes:
            if (b->cls == classobj_cls)
                continue;
132
            assert(PyType_Check(b));
133 134 135
            ASSERT(static_cast<BoxedClass*>(b)->is_pyston_class, "%s (%s)", cls->tp_name,
                   static_cast<BoxedClass*>(b)->tp_name);
        }
136 137 138
    }
#endif

139 140 141
    void* mem = gc_alloc(size, gc::GCKind::PYTHON);
    RELEASE_ASSERT(mem, "");

142 143 144 145 146
    // Not sure if we can get away with not initializing this memory.
    // I think there are small optimizations we can do, like not initializing cls (always
    // the first 8 bytes) since it will get written by PyObject_Init.
    memset(mem, '\0', size);

147 148
    Box* rtn = static_cast<Box*>(mem);

Travis Hance's avatar
slots  
Travis Hance committed
149
    if (cls->tp_itemsize != 0)
150
        static_cast<BoxVar*>(rtn)->ob_size = nitems;
Travis Hance's avatar
slots  
Travis Hance committed
151 152

    PyObject_INIT(rtn, cls);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
153
    assert(rtn->cls);
154 155 156 157

    return rtn;
}

158 159
extern "C" PyObject* PyType_GenericAlloc(PyTypeObject* type, Py_ssize_t nitems) noexcept {
    PyObject* obj;
160
    const size_t size = _PyObject_VAR_SIZE(type, nitems + 1);
161 162 163 164
    // I don't understand why there is a +1 in this method; _PyObject_NewVar doesn't do that.
    // CPython has the following comment:
    /* note that we need to add one, for the sentinel */
    // I think that regardless of the reasoning behind them having it, we should do what they do?
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196

    if (PyType_IS_GC(type))
        obj = _PyObject_GC_Malloc(size);
    else
        obj = (PyObject*)PyObject_MALLOC(size);

    if (obj == NULL)
        return PyErr_NoMemory();

    memset(obj, '\0', size);

    if (type->tp_flags & Py_TPFLAGS_HEAPTYPE)
        Py_INCREF(type);

    if (type->tp_itemsize == 0)
        PyObject_INIT(obj, type);
    else
        (void)PyObject_INIT_VAR((PyVarObject*)obj, type, nitems);

    if (PyType_IS_GC(type))
        _PyObject_GC_TRACK(obj);
    return obj;
}

extern "C" PyObject* _PyObject_New(PyTypeObject* tp) noexcept {
    PyObject* op;
    op = (PyObject*)PyObject_MALLOC(_PyObject_SIZE(tp));
    if (op == NULL)
        return PyErr_NoMemory();
    return PyObject_INIT(op, tp);
}

197
// Analogue of PyType_GenericNew
Travis Hance's avatar
Travis Hance committed
198
void* BoxVar::operator new(size_t size, BoxedClass* cls, size_t nitems) {
199 200
    ALLOC_STATS_VAR(cls);

201
    assert(cls);
202
    // See definition of BoxedTuple for some notes on why we need this special case:
203
    ASSERT(cls->tp_basicsize >= size || isSubclass(cls, tuple_cls), "%s", cls->tp_name);
Travis Hance's avatar
Travis Hance committed
204
    assert(cls->tp_itemsize > 0);
205 206
    assert(cls->tp_alloc);

Travis Hance's avatar
slots  
Travis Hance committed
207
    void* mem = cls->tp_alloc(cls, nitems);
208 209 210 211 212
    RELEASE_ASSERT(mem, "");
    return mem;
}

void* Box::operator new(size_t size, BoxedClass* cls) {
213 214
    ALLOC_STATS(cls);

215
    assert(cls);
216
    ASSERT(cls->tp_basicsize >= size, "%s", cls->tp_name);
Travis Hance's avatar
Travis Hance committed
217
    assert(cls->tp_itemsize == 0);
218 219 220 221 222 223 224
    assert(cls->tp_alloc);

    void* mem = cls->tp_alloc(cls, 0);
    RELEASE_ASSERT(mem, "");
    return mem;
}

225
Box* BoxedClass::callHasnextIC(Box* obj, bool null_on_nonexistent) {
226 227
    assert(obj->cls == this);

228 229 230 231 232
    auto ic = hasnext_ic.get();
    if (!ic) {
        ic = new CallattrIC();
        hasnext_ic.reset(ic);
    }
233

234
    static BoxedString* hasnext_str = internStringImmortal("__hasnext__");
235 236 237
    CallattrFlags callattr_flags
        = {.cls_only = true, .null_on_nonexistent = null_on_nonexistent, .argspec = ArgPassSpec(0) };
    return ic->call(obj, hasnext_str, callattr_flags, nullptr, nullptr, nullptr, nullptr, nullptr);
238
}
239

240
extern "C" PyObject* PyIter_Next(PyObject* iter) noexcept {
241 242
    Box* result = NULL;
    if (iter->cls->tp_iternext != slot_tp_iternext)
243
        result = (*iter->cls->tp_iternext)(iter);
244 245 246 247
    else {
        try {
            Box* hasnext = iter->hasnextOrNullIC();
            if (hasnext && !hasnext->nonzeroIC())
248
                return NULL;
249
        } catch (ExcInfo e) {
250
            setCAPIException(e);
251 252 253
            return NULL;
        }
        result = iter->cls->call_nextIC(iter);
254
    }
255 256 257 258

    if (result == NULL && PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_StopIteration))
        PyErr_Clear();
    return result;
259 260
}

261
Box* BoxedClass::call_nextIC(Box* obj) noexcept {
262 263
    assert(obj->cls == this);

264 265 266
    // This would work, but it would have been better to just call tp_iternext
    assert(this->tp_iternext == slot_tp_iternext);

267 268
    auto ic = next_ic.get();
    if (!ic) {
269
        ic = new CallattrCapiIC();
270 271
        next_ic.reset(ic);
    }
272

273
    static BoxedString* next_str = internStringImmortal("next");
274 275
    CallattrFlags callattr_flags{.cls_only = true, .null_on_nonexistent = false, .argspec = ArgPassSpec(0) };
    return ic->call(obj, next_str, callattr_flags, nullptr, nullptr, nullptr, nullptr, nullptr);
276
}
277

278 279 280 281 282 283 284 285 286
Box* BoxedClass::callReprIC(Box* obj) {
    assert(obj->cls == this);

    auto ic = repr_ic.get();
    if (!ic) {
        ic = new CallattrIC();
        repr_ic.reset(ic);
    }

287
    static BoxedString* repr_str = internStringImmortal("__repr__");
288 289
    CallattrFlags callattr_flags{.cls_only = true, .null_on_nonexistent = false, .argspec = ArgPassSpec(0) };
    return ic->call(obj, repr_str, callattr_flags, nullptr, nullptr, nullptr, nullptr, nullptr);
290 291
}

Marius Wachtler's avatar
Marius Wachtler committed
292 293 294 295 296 297 298 299 300 301 302 303 304 305
Box* BoxedClass::callIterIC(Box* obj) {
    assert(obj->cls == this);

    auto ic = iter_ic.get();
    if (!ic) {
        ic = new CallattrIC();
        iter_ic.reset(ic);
    }

    static BoxedString* iter_str = internStringImmortal("__iter__");
    CallattrFlags callattr_flags{.cls_only = true, .null_on_nonexistent = true, .argspec = ArgPassSpec(0) };
    return ic->call(obj, iter_str, callattr_flags, nullptr, nullptr, nullptr, nullptr, nullptr);
}

306
bool BoxedClass::callNonzeroIC(Box* obj) {
307 308
    assert(obj->cls == this);

309 310 311 312 313
    auto ic = nonzero_ic.get();
    if (!ic) {
        ic = new NonzeroIC();
        nonzero_ic.reset(ic);
    }
314 315

    return ic->call(obj);
316 317
}

318 319 320 321 322 323
Box* Box::reprIC() {
    return this->cls->callReprIC(this);
}

BoxedString* Box::reprICAsString() {
    Box* r = this->reprIC();
Kevin Modzelewski's avatar
Kevin Modzelewski committed
324 325 326 327 328

    if (isSubclass(r->cls, unicode_cls)) {
        r = PyUnicode_AsASCIIString(r);
        checkAndThrowCAPIException();
    }
329 330 331 332 333 334 335 336 337 338 339 340 341 342
    if (r->cls != str_cls) {
        raiseExcHelper(TypeError, "__repr__ did not return a string!");
    }
    return static_cast<BoxedString*>(r);
}

bool Box::nonzeroIC() {
    return this->cls->callNonzeroIC(this);
}

Box* Box::hasnextOrNullIC() {
    return this->cls->callHasnextIC(this, true);
}

343 344
void Box::gcHandler(GCVisitor* v, Box* b) {
    if (b->cls) {
345
        v->visit(&b->cls);
346 347 348 349

        if (b->cls->instancesHaveHCAttrs()) {
            HCAttrs* attrs = b->getHCAttrsPtr();

350
            v->visit(&attrs->hcls);
351
            if (attrs->attr_list)
352
                v->visit(&attrs->attr_list);
353 354 355 356 357 358 359 360 361 362
        }

        if (b->cls->instancesHaveDictAttrs()) {
            RELEASE_ASSERT(0, "Shouldn't all of these objects be conservatively scanned?");
        }

        if (b->cls->tp_flags & Py_TPFLAGS_HEAPTYPE) {
            BoxedHeapClass* heap_cls = static_cast<BoxedHeapClass*>(b->cls);
            BoxedHeapClass::SlotOffset* slotOffsets = heap_cls->slotOffsets();
            for (int i = 0; i < heap_cls->nslots(); i++) {
363
                v->visit(&*((Box**)((char*)b + slotOffsets[i])));
364 365 366 367 368 369 370
            }
        }
    } else {
        assert(type_cls == NULL || b == type_cls);
    }
}

371
extern "C" BoxedFunctionBase::BoxedFunctionBase(FunctionMetadata* md)
372
    : in_weakreflist(NULL),
373
      md(md),
374 375 376 377 378 379 380
      closure(NULL),
      defaults(NULL),
      can_change_defaults(false),
      modname(NULL),
      name(NULL),
      doc(NULL) {

381 382 383
    if (md->source) {
        assert(md->source->scoping->areGlobalsFromModule());
        Box* globals_for_name = md->source->parent_module;
384 385 386

        static BoxedString* name_str = internStringImmortal("__name__");
        this->modname = globals_for_name->getattr(name_str);
387
        this->doc = md->source->getDocString();
388
    } else {
389
        this->modname = PyString_InternFromString("__builtin__");
390
        this->doc = None;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
391
    }
392 393
}

394
extern "C" BoxedFunctionBase::BoxedFunctionBase(FunctionMetadata* md, std::initializer_list<Box*> defaults,
395
                                                BoxedClosure* closure, Box* globals, bool can_change_defaults)
396
    : in_weakreflist(NULL),
397
      md(md),
398 399 400
      closure(closure),
      globals(globals),
      defaults(NULL),
401
      can_change_defaults(can_change_defaults),
402 403 404
      modname(NULL),
      name(NULL),
      doc(NULL) {
405
    assert((!globals) == (!md->source || md->source->scoping->areGlobalsFromModule()));
406

Kevin Modzelewski's avatar
Kevin Modzelewski committed
407
    if (defaults.size()) {
408 409 410 411 412 413 414 415 416 417
        // HAX copy+modify the BoxedTuple constructor so that we can put NULLs into the tuple.
        // We are going to separately be careful to make sure that those NULLs don't escape
        // to the user (see functionDefaults)
        this->defaults = BoxedTuple::create(defaults.size());
        int i = 0;
        for (auto e : defaults) {
            assert(!e || gc::isValidGCObject(e));
            this->defaults->elts[i] = e;
            ++i;
        }
Kevin Modzelewski's avatar
Kevin Modzelewski committed
418
    }
419

420
    if (md->source) {
421 422
        Box* globals_for_name = globals;
        if (!globals_for_name) {
423 424
            assert(md->source->scoping->areGlobalsFromModule());
            globals_for_name = md->source->parent_module;
425 426
        }

427
        static BoxedString* name_str = internStringImmortal("__name__");
428
        if (globals_for_name->cls == module_cls) {
429
            this->modname = globals_for_name->getattr(name_str);
430 431 432 433 434
        } else {
            this->modname = PyDict_GetItem(globals_for_name, name_str);
        }
        // It's ok for modname to be NULL

435
        this->doc = md->source->getDocString();
436
    } else {
437
        this->modname = PyString_InternFromString("__builtin__");
438
        this->doc = None;
439 440 441
    }
}

442
BoxedFunction::BoxedFunction(FunctionMetadata* md) : BoxedFunction(md, {}) {
443 444
}

445
BoxedFunction::BoxedFunction(FunctionMetadata* md, std::initializer_list<Box*> defaults, BoxedClosure* closure,
446
                             Box* globals, bool can_change_defaults)
447
    : BoxedFunctionBase(md, defaults, closure, globals, can_change_defaults) {
448

449 450 451
    // TODO eventually we want this to assert(f->source), I think, but there are still
    // some builtin functions that are BoxedFunctions but really ought to be a type that
    // we don't have yet.
452 453
    if (md->source) {
        this->name = static_cast<BoxedString*>(md->source->getName());
454 455 456
    }
}

457
void BoxedFunction::gcHandler(GCVisitor* v, Box* b) {
458
    Box::gcHandler(v, b);
459

460 461 462 463
    BoxedFunction* f = (BoxedFunction*)b;

    // TODO eventually f->name should always be non-NULL, then there'd be no need for this check
    if (f->name)
464
        v->visit(&f->name);
465 466

    if (f->modname)
467
        v->visit(&f->modname);
468

469
    if (f->doc)
470
        v->visit(&f->doc);
471

Kevin Modzelewski's avatar
Kevin Modzelewski committed
472
    if (f->closure)
473
        v->visit(&f->closure);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
474

475
    if (f->globals)
476
        v->visit(&f->globals);
477

478
    v->visit(&f->defaults);
479

480 481
    if (f->md && f->md->source && f->md->source->parent_module)
        v->visit(&f->md->source->parent_module);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
482 483
}

484 485
BoxedBuiltinFunctionOrMethod::BoxedBuiltinFunctionOrMethod(FunctionMetadata* md, const char* name, const char* doc)
    : BoxedBuiltinFunctionOrMethod(md, name, {}) {
486 487 488 489

    this->doc = doc ? boxString(doc) : None;
}

490
BoxedBuiltinFunctionOrMethod::BoxedBuiltinFunctionOrMethod(FunctionMetadata* md, const char* name,
491 492
                                                           std::initializer_list<Box*> defaults, BoxedClosure* closure,
                                                           const char* doc)
493
    : BoxedFunctionBase(md, defaults, closure) {
494 495 496 497 498 499

    assert(name);
    this->name = static_cast<BoxedString*>(boxString(name));
    this->doc = doc ? boxString(doc) : None;
}

500 501 502 503 504 505 506 507
static void functionDtor(Box* b) {
    assert(isSubclass(b->cls, function_cls) || isSubclass(b->cls, builtin_function_or_method_cls));

    BoxedFunctionBase* self = static_cast<BoxedFunctionBase*>(b);
    self->dependent_ics.invalidateAll();
    self->dependent_ics.~ICInvalidator();
}

508
std::string BoxedModule::name() {
509 510
    static BoxedString* name_str = internStringImmortal("__name__");
    Box* name = this->getattr(name_str);
511 512 513
    if (!name || name->cls != str_cls) {
        return "?";
    } else {
514
        BoxedString* sname = static_cast<BoxedString*>(name);
515
        return sname->s();
516 517 518
    }
}

519
BoxedString* BoxedModule::getStringConstant(llvm::StringRef ast_str, bool intern) {
520
    BoxedString*& r = str_constants[ast_str];
521 522 523 524 525 526 527 528 529 530 531 532 533
    if (intern) {
        // If we had previously created a box for this string, we have to create a new
        // string (or at least, be prepared to return a different value that we had already
        // interned).  This is fine, except we have to be careful because we promised
        // that we would keep the previously-created string alive.
        // So, make sure to put it onto the keep_alive list.
        if (r && !PyString_CHECK_INTERNED(r)) {
            keep_alive.push_back(r);
            r = NULL;
        }
        if (!r)
            r = internStringMortal(ast_str);
    } else if (!r)
534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551
        r = boxString(ast_str);
    return r;
}

Box* BoxedModule::getUnicodeConstant(llvm::StringRef ast_str) {
    Box*& r = unicode_constants[ast_str];
    if (!r)
        r = decodeUTF8StringPtr(ast_str);
    return r;
}

BoxedInt* BoxedModule::getIntConstant(int64_t n) {
    BoxedInt*& r = int_constants[n];
    if (!r)
        r = new BoxedInt(n);
    return r;
}

552 553 554 555 556 557 558
static int64_t getDoubleBits(double d) {
    int64_t rtn;
    static_assert(sizeof(rtn) == sizeof(d), "");
    memcpy(&rtn, &d, sizeof(d));
    return rtn;
}

559
BoxedFloat* BoxedModule::getFloatConstant(double d) {
560
    BoxedFloat*& r = float_constants[getDoubleBits(d)];
561 562 563 564 565 566
    if (!r)
        r = static_cast<BoxedFloat*>(boxFloat(d));
    return r;
}

Box* BoxedModule::getPureImaginaryConstant(double d) {
567
    Box*& r = imaginary_constants[getDoubleBits(d)];
568 569 570 571 572 573 574 575 576 577 578
    if (!r)
        r = createPureImaginary(d);
    return r;
}

Box* BoxedModule::getLongConstant(llvm::StringRef ast_str) {
    Box*& r = long_constants[ast_str];
    if (!r)
        r = createLong(ast_str);
    return r;
}
579

580
template <typename A, typename B, typename C> void visitContiguousMap(GCVisitor* v, ContiguousMap<A, B, C>& map) {
581
    v->visitRange(const_cast<B*>(&map.vector()[0]), const_cast<B*>(&map.vector()[map.size()]));
582 583
}

584
void BoxedModule::gcHandler(GCVisitor* v, Box* b) {
585
    Box::gcHandler(v, b);
586 587 588

    BoxedModule* d = (BoxedModule*)b;

589 590 591 592 593 594
    visitContiguousMap(v, d->str_constants);
    visitContiguousMap(v, d->unicode_constants);
    visitContiguousMap(v, d->int_constants);
    visitContiguousMap(v, d->float_constants);
    visitContiguousMap(v, d->imaginary_constants);
    visitContiguousMap(v, d->long_constants);
595
    if (!d->keep_alive.empty())
596
        v->visitRange(&d->keep_alive[0], ((&d->keep_alive[0]) + d->keep_alive.size()));
597 598
}

599 600
// This mustn't throw; our IR generator generates calls to it without "invoke" even when there are exception handlers /
// finally-blocks in scope.
601
extern "C" Box* createFunctionFromMetadata(FunctionMetadata* md, BoxedClosure* closure, Box* globals,
602
                                           std::initializer_list<Box*> defaults) noexcept {
603
    STAT_TIMER(t0, "us_timer_createfunctionfrommetadata", 10);
604

Kevin Modzelewski's avatar
Kevin Modzelewski committed
605 606 607
    if (closure)
        assert(closure->cls == closure_cls);

608
    return new BoxedFunction(md, defaults, closure, globals, /* can_change_defaults = */ true);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
609 610
}

611 612
extern "C" FunctionMetadata* getFunctionMetadata(Box* b) {
    assert(isSubclass(b->cls, function_cls) || isSubclass(b->cls, builtin_function_or_method_cls));
613
    return static_cast<BoxedFunction*>(b)->md;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
614 615
}

616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644
static PyObject* cpython_type_call(PyTypeObject* type, PyObject* args, PyObject* kwds) noexcept {
    PyObject* obj;

    if (type->tp_new == NULL) {
        PyErr_Format(PyExc_TypeError, "cannot create '%.100s' instances", type->tp_name);
        return NULL;
    }

    obj = type->tp_new(type, args, kwds);
    if (obj != NULL) {
        /* Ugly exception: when the call was type(something),
         *            don't call tp_init on the result. */
        if (type == &PyType_Type && PyTuple_Check(args) && PyTuple_GET_SIZE(args) == 1
            && (kwds == NULL || (PyDict_Check(kwds) && PyDict_Size(kwds) == 0)))
            return obj;
        /* If the returned object is not an instance of type,
         *            it won't be initialized. */
        if (!PyType_IsSubtype(obj->cls, type))
            return obj;
        type = obj->cls;
        if (PyType_HasFeature(type, Py_TPFLAGS_HAVE_CLASS) && type->tp_init != NULL
            && type->tp_init(obj, args, kwds) < 0) {
            Py_DECREF(obj);
            obj = NULL;
        }
    }
    return obj;
}

645
template <ExceptionStyle S>
646
static Box* typeCallInner(CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* arg3,
647
                          Box** args, const std::vector<BoxedString*>* keyword_names) noexcept(S == CAPI);
648

649
template <ExceptionStyle S>
650
static Box* typeTppCall(Box* self, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* arg3,
651
                        Box** args, const std::vector<BoxedString*>* keyword_names) noexcept(S == CAPI) {
652 653
    int npassed_args = argspec.totalPassed();

654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672
    // Common CAPI path call this function with *args, **kw.
    if (argspec == ArgPassSpec(0, 0, true, false) || argspec == ArgPassSpec(0, 0, true, true)) {
        // Wouldn't be able to rewrite anyway:
        assert(!rewrite_args || !rewrite_args->out_success);

        arg1 = PySequence_Tuple(arg1);
        if (!arg1) {
            if (S == CAPI)
                return NULL;
            else
                throwCAPIException();
        }

        Box* r = cpython_type_call(static_cast<BoxedClass*>(self), arg1, argspec.has_kwargs ? arg2 : NULL);
        if (S == CXX && !r)
            throwCAPIException();
        return r;
    }

673
    if (argspec.has_starargs || argspec.has_kwargs) {
674 675 676 677
        // This would fail in typeCallInner
        rewrite_args = NULL;
    }

678 679 680
    Box** new_args = NULL;
    if (npassed_args >= 3) {
        new_args = (Box**)alloca(sizeof(Box*) * (npassed_args + 1 - 3));
681
    }
682

683 684 685 686 687 688 689 690 691
    RewriterVar* r_bind_obj = NULL;
    if (rewrite_args) {
        r_bind_obj = rewrite_args->obj;
        rewrite_args->obj = NULL;
    }

    ArgPassSpec new_argspec
        = bindObjIntoArgs(self, r_bind_obj, rewrite_args, argspec, arg1, arg2, arg3, args, new_args);

692
    return typeCallInner<S>(rewrite_args, new_argspec, arg1, arg2, arg3, new_args, keyword_names);
693 694 695 696 697 698 699 700 701 702
}

static Box* typeCallInternal(BoxedFunctionBase* f, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1,
                             Box* arg2, Box* arg3, Box** args, const std::vector<BoxedString*>* keyword_names) {
    if (rewrite_args)
        assert(rewrite_args->func_guarded);

    static StatCounter slowpath_typecall("slowpath_typecall");
    slowpath_typecall.log();

703 704 705
    if (argspec.has_starargs || argspec.num_args == 0) {
        // Get callFunc to expand the arguments.
        // TODO: update this to use rearrangeArguments instead.
706
        return callFunc<CXX>(f, rewrite_args, argspec, arg1, arg2, arg3, args, keyword_names);
707
    }
708

709
    return typeCallInner<CXX>(rewrite_args, argspec, arg1, arg2, arg3, args, keyword_names);
710 711 712 713 714 715 716 717 718
}

// For use on __init__ return values
static void assertInitNone(Box* obj) {
    if (obj != None) {
        raiseExcHelper(TypeError, "__init__() should return None, not '%s'", getTypeName(obj));
    }
}

719 720 721 722 723 724 725
static PyObject* cpythonTypeCall(BoxedClass* type, PyObject* args, PyObject* kwds) {
    Box* r = cpython_type_call(type, args, kwds);
    if (!r)
        throwCAPIException();
    return r;
}

726 727 728
static Box* unicodeNewHelper(BoxedClass* type, Box* string, Box* encoding_obj, Box** _args) {
    Box* errors_obj = _args[0];

729 730
    assert(isSubclass(type, unicode_cls));
    assert(type->tp_new == unicode_cls->tp_new);
731 732 733 734 735 736 737 738 739 740

    char* encoding = NULL;
    char* errors = NULL;
    if (encoding_obj)
        if (!PyArg_ParseSingle(encoding_obj, 1, "unicode", "s", &encoding))
            throwCAPIException();
    if (errors_obj)
        if (!PyArg_ParseSingle(errors_obj, 1, "unicode", "s", &errors))
            throwCAPIException();

741
    Box* r = unicode_new_inner(type, string, encoding, errors);
742 743
    if (!r)
        throwCAPIException();
744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778

    if (type == unicode_cls) {
        if (r->cls == unicode_cls) // no init
            return r;
        if (!PyUnicode_Check(r)) // skip init
            return r;
    } else {
        if (!isSubclass(r->cls, type)) // skip init
            return r;
    }

    // Call tp_init:

    if (r->cls->tp_init == object_cls->tp_init)
        return r;

    if (!string)
        assert(!encoding_obj);
    if (!encoding_obj)
        assert(!errors_obj);

    Box* args;
    if (!string)
        args = EmptyTuple;
    else if (!encoding_obj)
        args = BoxedTuple::create1(string);
    else if (!errors_obj)
        args = BoxedTuple::create2(string, encoding_obj);
    else
        args = BoxedTuple::create3(string, encoding_obj, errors_obj);

    int init_code = r->cls->tp_init(r, args, NULL);
    if (init_code == -1)
        throwCAPIException();

779 780 781
    return r;
}

782
static Box* objectNewNoArgs(BoxedClass* cls) noexcept {
783
    assert(PyType_Check(cls));
784 785 786
#ifndef NDEBUG
    static BoxedString* new_str = internStringImmortal("__new__");
    static BoxedString* init_str = internStringImmortal("__init__");
787 788
    assert(typeLookup(cls, new_str) == typeLookup(object_cls, new_str)
           && typeLookup(cls, init_str) != typeLookup(object_cls, init_str));
789 790 791 792 793
#endif
    return new (cls) Box();
}

template <ExceptionStyle S>
794
static Box* typeCallInner(CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* arg3,
795
                          Box** args, const std::vector<BoxedString*>* keyword_names) noexcept(S == CAPI) {
796
    int npassed_args = argspec.totalPassed();
797
    int npositional = argspec.num_args;
798

799
    // We need to know what the class is.  We could potentially call rearrangeArguments here
800 801 802
    assert(argspec.num_args >= 1);
    Box* _cls = arg1;

803
    if (!PyType_Check(_cls)) {
804 805 806 807 808 809
        if (S == CAPI)
            PyErr_Format(TypeError, "descriptor '__call__' requires a 'type' object but received an '%s'",
                         getTypeName(_cls));
        else
            raiseExcHelper(TypeError, "descriptor '__call__' requires a 'type' object but received an '%s'",
                           getTypeName(_cls));
810 811 812 813
    }

    BoxedClass* cls = static_cast<BoxedClass*>(_cls);

814 815
    // Special-case unicode for now, maybe there's something about this that can eventually be generalized:
    if (cls->tp_new == unicode_cls->tp_new) {
816 817 818 819 820 821 822 823 824 825
        // TODO: implement
        if (S == CAPI) {
            try {
                return typeCallInner<CXX>(NULL, argspec, arg1, arg2, arg3, args, keyword_names);
            } catch (ExcInfo e) {
                setCAPIException(e);
                return NULL;
            }
        }

826 827
        assert(S == CXX && "implement me");

828 829 830 831 832 833
        if (rewrite_args) {
            rewrite_args->arg1->addGuard((intptr_t)cls);
        }

        ParamReceiveSpec paramspec(4, 3, false, false);
        bool rewrite_success = false;
834
        static ParamNames param_names({ "", "string", "encoding", "errors" }, "", "");
835 836 837 838
        static Box* defaults[3] = { NULL, NULL, NULL };
        Box* oargs[1];

        rearrangeArguments(paramspec, &param_names, "unicode", defaults, rewrite_args, rewrite_success, argspec, arg1,
839 840
                           arg2, arg3, args, oargs, keyword_names);
        assert(arg1 == cls);
841 842 843 844 845 846 847 848 849 850 851

        if (!rewrite_success)
            rewrite_args = NULL;

        if (rewrite_args) {
            rewrite_args->out_rtn
                = rewrite_args->rewriter->call(true, (void*)unicodeNewHelper, rewrite_args->arg1, rewrite_args->arg2,
                                               rewrite_args->arg3, rewrite_args->args);
            rewrite_args->out_success = true;
        }

852
        return unicodeNewHelper(cls, arg2, arg3, oargs);
853 854
    }

855
    if (cls->tp_new != object_cls->tp_new && cls->tp_new != slot_tp_new && cls->tp_new != BaseException->tp_new
856
        && cls->tp_new != type_cls->tp_new && S == CXX) {
857 858 859
        // Looks like we're calling an extension class and we're not going to be able to
        // separately rewrite the new + init calls.  But we can rewrite the fact that we
        // should just call the cpython version, which will end up working pretty well.
860 861 862

        assert(S == CXX && "implement me");

863 864
        ParamReceiveSpec paramspec(1, false, true, true);
        bool rewrite_success = false;
865
        Box** oargs = NULL;
866
        rearrangeArguments(paramspec, NULL, "", NULL, rewrite_args, rewrite_success, argspec, arg1, arg2, arg3, args,
867 868
                           oargs, keyword_names);
        assert(arg1 == cls);
869 870 871 872 873 874 875 876 877 878

        if (!rewrite_success)
            rewrite_args = NULL;

        if (rewrite_args) {
            rewrite_args->out_rtn = rewrite_args->rewriter->call(true, (void*)cpythonTypeCall, rewrite_args->arg1,
                                                                 rewrite_args->arg2, rewrite_args->arg3);
            rewrite_args->out_success = true;
        }

879
        return cpythonTypeCall(cls, arg2, arg3);
880 881
    }

882 883 884
    if (argspec.has_starargs || argspec.has_kwargs)
        rewrite_args = NULL;

885 886 887
    RewriterVar* r_ccls = NULL;
    RewriterVar* r_new = NULL;
    RewriterVar* r_init = NULL;
888
    Box* new_attr, * init_attr = NULL;
889 890
    if (rewrite_args) {
        assert(!argspec.has_starargs);
891
        assert(!argspec.has_kwargs);
892 893 894
        assert(argspec.num_args > 0);

        r_ccls = rewrite_args->arg1;
895 896 897
        // Guard on the requested class.  We could potentially support multiple classes in a rewrite,
        // but there are parts of this function's rewrite that currently take advantage of the fact
        // that the requested class is fixed.
898
        r_ccls->addGuard((intptr_t)arg1 /* = _cls */);
899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917


        if (!rewrite_args->args_guarded) {
            // TODO should know which args don't need to be guarded, ex if we're guaranteed that they
            // already fit, either since the type inferencer could determine that,
            // or because they only need to fit into an UNKNOWN slot.

            if (npassed_args >= 1)
                rewrite_args->arg1->addAttrGuard(offsetof(Box, cls), (intptr_t)arg1->cls);
            if (npassed_args >= 2)
                rewrite_args->arg2->addAttrGuard(offsetof(Box, cls), (intptr_t)arg2->cls);
            if (npassed_args >= 3)
                rewrite_args->arg3->addAttrGuard(offsetof(Box, cls), (intptr_t)arg3->cls);
            for (int i = 3; i < npassed_args; i++) {
                RewriterVar* v = rewrite_args->args->getAttr((i - 3) * sizeof(Box*), Location::any());
                v->addAttrGuard(offsetof(Box, cls), (intptr_t)args[i - 3]->cls);
            }
            rewrite_args->args_guarded = true;
        }
918 919
    }

920
    static BoxedString* new_str = internStringImmortal("__new__");
921 922 923 924
    if (rewrite_args) {
        GetattrRewriteArgs grewrite_args(rewrite_args->rewriter, r_ccls, rewrite_args->destination);
        // TODO: if tp_new != Py_CallPythonNew, call that instead?
        new_attr = typeLookup(cls, new_str, &grewrite_args);
925
        assert(new_attr);
926

927
        if (!grewrite_args.isSuccessful())
928 929
            rewrite_args = NULL;
        else {
930
            r_new = grewrite_args.getReturn(ReturnConvention::HAS_RETURN);
931 932 933 934 935
            r_new->addGuard((intptr_t)new_attr);
        }

        // Special-case functions to allow them to still rewrite:
        if (new_attr->cls != function_cls) {
936 937 938 939 940 941 942 943 944 945 946 947
            try {
                Box* descr_r = processDescriptorOrNull(new_attr, None, cls);
                if (descr_r) {
                    new_attr = descr_r;
                    rewrite_args = NULL;
                }
            } catch (ExcInfo e) {
                if (S == CAPI) {
                    setCAPIException(e);
                    return NULL;
                } else
                    throw e;
948 949 950
            }
        }
    } else {
951
        new_attr = typeLookup(cls, new_str);
952
        try {
Kevin Modzelewski's avatar
Kevin Modzelewski committed
953 954
            if (new_attr->cls != function_cls) // optimization
                new_attr = processDescriptor(new_attr, None, cls);
955 956 957 958 959 960 961
        } catch (ExcInfo e) {
            if (S == CAPI) {
                setCAPIException(e);
                return NULL;
            } else
                throw e;
        }
962 963 964 965 966
    }
    assert(new_attr && "This should always resolve");

    // typeCall is tricky to rewrite since it has complicated behavior: we are supposed to
    // call the __init__ method of the *result of the __new__ call*, not of the original
967 968
    // class.  (And only if the result is an instance of the original class (or a subclass),
    // but that's not even the tricky part here.)
969 970 971
    //
    // By the time we know the type of the result of __new__(), it's too late to add traditional
    // guards.  So, instead of doing that, we're going to add a guard that makes sure that __new__
972 973 974 975 976 977 978 979 980 981 982 983
    // has the property that it will always return an instance where we know what __init__ has to be
    // called on it.  There are a couple cases:
    // - Some __new__ functions, such as object.__new__, always return an instance of the requested class.
    //   We can whitelist these __new__ functions.
    // - There are cls+arg pairs such that cls(arg) always returns an instance of cls.  For example,
    //   str() of an int is always a str, but str of arbitrary types does not necessarily return a str
    //   (could return a subtype of str)
    // - There are cls+arg pairs where we know that we don't have to call an __init__, despite the return
    //   value having variable type.  For instance, int(float) can return a long on overflow, but in either
    //   case no __init__ should be called.
    // - There's a final special case that type(obj) does not call __init__ even if type.__new__(type, obj)
    //   happens to return a subclass of type.  This is a special case in cpython's code that we have as well.
984 985
    //

986
    // For debugging, keep track of why we think we can rewrite this:
987
    enum { UNKNOWN, MAKES_CLS, NO_INIT, TYPE_NEW_SPECIAL_CASE, } which_init = UNKNOWN;
988 989 990 991 992 993 994 995

    // These are __new__ functions that have the property that __new__(kls) always returns an instance of kls.
    // These are ok to call regardless of what type was requested.
    //
    // TODO what if an extension type defines a tp_alloc that returns something that's not an instance of that
    // type?  then object.__new__ would not be able to be here:
    //
    // this array is ok with not using StlCompatAllocator since we will manually register these objects with the GC
996 997
    static std::vector<Box*> class_making_news;
    if (class_making_news.empty()) {
998
        for (BoxedClass* allowed_cls : { object_cls, enumerate_cls, xrange_cls, tuple_cls, list_cls, dict_cls }) {
999
            auto new_obj = typeLookup(allowed_cls, new_str);
1000
            gc::registerPermanentRoot(new_obj, /* allow_duplicates= */ true);
1001
            class_making_news.push_back(new_obj);
1002 1003 1004 1005
        }
    }

    if (rewrite_args) {
1006
        for (auto b : class_making_news) {
1007
            if (b == new_attr) {
1008
                which_init = MAKES_CLS;
1009 1010 1011 1012
                break;
            }
        }

1013
        if (cls->tp_new == BaseException->tp_new)
1014
            which_init = MAKES_CLS;
1015

1016 1017 1018 1019 1020
        bool know_first_arg = !argspec.has_starargs && !argspec.has_kwargs && argspec.num_keywords == 0;

        if (know_first_arg) {
            if (argspec.num_args == 1
                && (cls == int_cls || cls == float_cls || cls == long_cls || cls == str_cls || cls == unicode_cls))
1021
                which_init = MAKES_CLS;
1022 1023 1024 1025

            if (argspec.num_args == 2 && (cls == int_cls || cls == float_cls || cls == long_cls)
                && (arg2->cls == int_cls || arg2->cls == str_cls || arg2->cls == float_cls
                    || arg2->cls == unicode_cls)) {
1026
                which_init = NO_INIT;
1027 1028
                rewrite_args->arg2->addAttrGuard(offsetof(Box, cls), (intptr_t)arg2->cls);
            }
1029 1030 1031

            // str(obj) can return str-subtypes, but for builtin types it won't:
            if (argspec.num_args == 2 && cls == str_cls && (arg2->cls == int_cls || arg2->cls == float_cls)) {
1032
                which_init = MAKES_CLS;
1033 1034 1035 1036 1037
                rewrite_args->arg2->addAttrGuard(offsetof(Box, cls), (intptr_t)arg2->cls);
            }

            // int(str, base) can only return int/long
            if (argspec.num_args == 3 && cls == int_cls) {
1038
                which_init = NO_INIT;
1039 1040 1041
            }

#if 0
1042
            if (which_init == NOT_ALLOWED) {
1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053
                std::string per_name_stat_name = "zzz_norewrite_" + std::string(cls->tp_name);
                if (argspec.num_args == 1)
                    per_name_stat_name += "_1arg";
                else if (argspec.num_args == 2)
                    per_name_stat_name += "_" + std::string(arg2->cls->tp_name);
                else
                    per_name_stat_name += "_narg";
                uint64_t* counter = Stats::getStatCounter(per_name_stat_name);
                Stats::log(counter);
            }
#endif
1054 1055
        }

1056
        if (cls == type_cls && argspec == ArgPassSpec(2))
1057
            which_init = TYPE_NEW_SPECIAL_CASE;
1058 1059
    }

1060
    static BoxedString* init_str = internStringImmortal("__init__");
1061 1062 1063
    if (cls->tp_init == slot_tp_init) {
        // If there's a Python-level tp_init, try getting it, since calling it might be faster than calling
        // tp_init if we can manage to rewrite it.
1064
        if (rewrite_args && which_init != UNKNOWN) {
1065 1066
            GetattrRewriteArgs grewrite_args(rewrite_args->rewriter, r_ccls, rewrite_args->destination);
            init_attr = typeLookup(cls, init_str, &grewrite_args);
1067

1068
            if (!grewrite_args.isSuccessful())
1069 1070 1071
                rewrite_args = NULL;
            else {
                if (init_attr) {
1072
                    r_init = grewrite_args.getReturn(ReturnConvention::HAS_RETURN);
1073
                    r_init->addGuard((intptr_t)init_attr);
1074
                } else {
1075
                    grewrite_args.assertReturnConvention(ReturnConvention::NO_RETURN);
1076
                }
1077
            }
1078
        } else {
1079
            init_attr = typeLookup(cls, init_str);
1080 1081 1082 1083 1084 1085 1086 1087
        }
    }

    Box* made;
    RewriterVar* r_made = NULL;

    ArgPassSpec new_argspec = argspec;

1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101
    if (S == CAPI && cls->tp_new != object_cls->tp_new && cls->tp_init != object_cls->tp_init) {
        // If there's a custom new and custom init, in CAPI mode we don't have any way of handling
        // any exceptions thrown by the new.
        rewrite_args = NULL;
    }

    if (S == CAPI && cls->tp_init != object_cls->tp_init) {
        // If there's a custom init, in CAPI mode we don't have any way of handling the exception that
        // we assertInitNone might have to throw from the init returning non-None.
        // TODO actually looks we only have to be doing that check for Python-level objects; ie in CPython
        // that check is done in slot_tp_init
        rewrite_args = NULL;
    }

1102 1103 1104 1105 1106 1107 1108 1109 1110 1111
    if (rewrite_args) {
        if (cls->tp_new == object_cls->tp_new && cls->tp_init != object_cls->tp_init) {
            // Fast case: if we are calling object_new, we normally doesn't look at the arguments at all.
            // (Except in the case when init_attr != object_init, in which case object_new looks at the number
            // of arguments and throws an exception.)
            //
            // Another option is to rely on rewriting to make this fast, which would probably require adding
            // a custom internal callable to object.__new__
            made = objectNewNoArgs(cls);
            r_made = rewrite_args->rewriter->call(true, (void*)objectNewNoArgs, r_ccls);
1112
            assert(made);
1113 1114
        } else {
            CallRewriteArgs srewrite_args(rewrite_args->rewriter, r_new, rewrite_args->destination);
1115
            srewrite_args.args_guarded = rewrite_args->args_guarded;
1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128
            srewrite_args.func_guarded = true;

            int new_npassed_args = new_argspec.totalPassed();

            if (new_npassed_args >= 1)
                srewrite_args.arg1 = r_ccls;
            if (new_npassed_args >= 2)
                srewrite_args.arg2 = rewrite_args->arg2;
            if (new_npassed_args >= 3)
                srewrite_args.arg3 = rewrite_args->arg3;
            if (new_npassed_args >= 4)
                srewrite_args.args = rewrite_args->args;

1129 1130
            made = runtimeCallInternal<S, REWRITABLE>(new_attr, &srewrite_args, new_argspec, cls, arg2, arg3, args,
                                                      keyword_names);
1131 1132
            if (!made) {
                assert(S == CAPI);
1133

1134
                if (srewrite_args.out_success && which_init == NO_INIT) {
1135 1136 1137 1138
                    rewrite_args->out_rtn = srewrite_args.out_rtn;
                    rewrite_args->out_success = true;
                }

1139 1140
                return NULL;
            }
1141 1142 1143 1144 1145 1146 1147 1148

            if (!srewrite_args.out_success) {
                rewrite_args = NULL;
            } else {
                r_made = srewrite_args.out_rtn;
            }
        }
    } else {
1149
        if (cls->tp_new == object_cls->tp_new && cls->tp_init != object_cls->tp_init) {
1150
            made = objectNewNoArgs(cls);
1151 1152
            assert(made);
        } else
1153 1154
            made = runtimeCallInternal<S, NOT_REWRITABLE>(new_attr, NULL, new_argspec, cls, arg2, arg3, args,
                                                          keyword_names);
1155 1156 1157 1158 1159

        if (!made) {
            assert(S == CAPI);
            return NULL;
        }
1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172
    }

    assert(made);

    // Special-case (also a special case in CPython): if we just called type.__new__(arg), don't call __init__
    if (cls == type_cls && argspec == ArgPassSpec(2)) {
        if (rewrite_args) {
            rewrite_args->out_success = true;
            rewrite_args->out_rtn = r_made;
        }
        return made;
    }

1173 1174
    bool skip_init = false;

1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226
    // For __new__ functions that we have no information about, try to rewrite to a helper.
    if (rewrite_args && which_init == UNKNOWN) {
        // TODO this whole block is very similar to the call-tpinit block a bit farther down.
        // The later block is slightly different since it can know what the tp_init function
        // will be, whereas this block can't; I'm not sure how to merge the functionality.  That's
        // probably just evidence of the overall convolutedness of this function.

        // TODO: instead of rewriting to the capi-format, maybe we should do the rearrangearguments
        // inside the helper?
        bool rewrite_success = false;
        try {
            rearrangeArguments(ParamReceiveSpec(1, 0, true, true), NULL, "", NULL, rewrite_args, rewrite_success,
                               argspec, made, arg2, arg3, args, NULL, keyword_names);
        } catch (ExcInfo e) {
            if (S == CAPI) {
                setCAPIException(e);
                return NULL;
            } else
                throw e;
        }

        if (!rewrite_success)
            rewrite_args = NULL;

        class InitHelper {
        public:
            static Box* call(Box* made, BoxedClass* cls, Box* args, Box* kwargs) noexcept(S == CAPI) {
                if (!isSubclass(made->cls, cls))
                    return made;

                int err = made->cls->tp_init(made, args, kwargs);
                if (err == -1) {
                    if (S == CAPI)
                        return NULL;
                    else
                        throwCAPIException();
                }
                return made;
            }
        };

        assert(arg2->cls == tuple_cls);
        assert(!arg3 || arg3->cls == dict_cls);

        if (rewrite_args) {
            rewrite_args->out_rtn = rewrite_args->rewriter->call(true, (void*)InitHelper::call, r_made, r_ccls,
                                                                 rewrite_args->arg2, rewrite_args->arg3);
            rewrite_args->out_success = true;
        }
        return InitHelper::call(made, cls, arg2, arg3);
    }

1227 1228 1229
    // If __new__ returns a subclass, supposed to call that subclass's __init__.
    // If __new__ returns a non-subclass, not supposed to call __init__.
    if (made->cls != cls) {
1230
        assert(which_init != MAKES_CLS);
1231 1232

        if (!isSubclass(made->cls, cls)) {
1233
            skip_init = true;
1234
        } else {
1235 1236 1237 1238
            if (init_attr) {
                // Getting here means the init_attr is wrong; set it to NULL so that we don't use it.
                init_attr = NULL;
            }
1239 1240 1241
        }
    }

1242 1243
    assert(!rewrite_args || !skip_init || (which_init == NO_INIT && made->cls->tp_init == object_cls->tp_init));

1244
    if (!skip_init && made->cls->tp_init != object_cls->tp_init) {
1245
        Box* initrtn;
1246 1247 1248 1249
        // If there's a Python-level __init__ function, try calling it.
        if (init_attr && init_attr->cls == function_cls) {
            if (rewrite_args) {
                // We are going to rewrite as a call to cls.init:
1250
                assert(which_init == MAKES_CLS);
1251 1252
                assert(made->cls == cls);
            }
1253

1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266
            // Note: this code path includes the descriptor logic
            if (rewrite_args) {
                CallRewriteArgs srewrite_args(rewrite_args->rewriter, r_init, rewrite_args->destination);
                srewrite_args.arg1 = r_made;
                if (npassed_args >= 2)
                    srewrite_args.arg2 = rewrite_args->arg2;
                if (npassed_args >= 3)
                    srewrite_args.arg3 = rewrite_args->arg3;
                if (npassed_args >= 4)
                    srewrite_args.args = rewrite_args->args;
                srewrite_args.args_guarded = rewrite_args->args_guarded;
                srewrite_args.func_guarded = true;

1267 1268
                initrtn = runtimeCallInternal<S, REWRITABLE>(init_attr, &srewrite_args, argspec, made, arg2, arg3, args,
                                                             keyword_names);
1269 1270 1271 1272 1273 1274 1275 1276

                if (!srewrite_args.out_success) {
                    rewrite_args = NULL;
                } else {
                    assert(S == CXX && "this need to be converted");
                    rewrite_args->rewriter->call(true, (void*)assertInitNone, srewrite_args.out_rtn);
                }
            } else {
1277 1278
                initrtn = runtimeCallInternal<S, NOT_REWRITABLE>(init_attr, NULL, argspec, made, arg2, arg3, args,
                                                                 keyword_names);
1279
            }
1280 1281 1282 1283 1284

            if (!initrtn) {
                assert(S == CAPI);
                return NULL;
            }
1285

1286 1287 1288 1289 1290 1291 1292 1293 1294
            assert(initrtn);

            if (S == CAPI) {
                if (initrtn != None) {
                    PyErr_Format(TypeError, "__init__() should return None, not '%s'", getTypeName(initrtn));
                    return NULL;
                }
            } else
                assertInitNone(initrtn);
1295
        } else {
1296 1297 1298 1299 1300 1301 1302
            // Otherwise, just call tp_init.  This will work out well for extension classes, and no worse
            // than failing the rewrite for Python non-extension non-functions (when does that happen?).

            initproc tpinit = made->cls->tp_init;

            if (rewrite_args) {
                // This is the only case that should get here:
1303
                assert(which_init == MAKES_CLS && made->cls == cls);
1304 1305 1306 1307
                // We're going to emit a call to cls->tp_init, but really we should be calling made->cls->tp_init,
                // but the MAKES_CLS condition tells us that made->cls is cls so the two tp_inits are the same.
                assert(tpinit == cls->tp_init);
            }
1308

1309
            bool rewrite_success = false;
1310
            try {
1311 1312
                rearrangeArguments(ParamReceiveSpec(1, 0, true, true), NULL, "", NULL, rewrite_args, rewrite_success,
                                   argspec, made, arg2, arg3, args, NULL, keyword_names);
1313 1314 1315 1316 1317 1318 1319
            } catch (ExcInfo e) {
                if (S == CAPI) {
                    setCAPIException(e);
                    return NULL;
                } else
                    throw e;
            }
1320

1321 1322
            if (!rewrite_success)
                rewrite_args = NULL;
1323

1324 1325
            assert(arg2->cls == tuple_cls);
            assert(!arg3 || arg3->cls == dict_cls);
1326

1327 1328 1329 1330 1331 1332
            int err = tpinit(made, arg2, arg3);
            if (err == -1) {
                if (S == CAPI)
                    return NULL;
                else
                    throwCAPIException();
1333 1334
            }

1335 1336 1337 1338 1339 1340 1341
            if (rewrite_args) {
                auto r_err
                    = rewrite_args->rewriter->call(true, (void*)tpinit, r_made, rewrite_args->arg2, rewrite_args->arg3);

                assert(S == CXX && "this need to be converted");
                rewrite_args->rewriter->checkAndThrowCAPIException(r_err, -1);
            }
1342 1343 1344 1345
        }
    } else {
        if (new_attr == NULL && npassed_args != 1) {
            // TODO not npassed args, since the starargs or kwargs could be null
1346 1347 1348 1349
            if (S == CAPI) {
                PyErr_SetString(TypeError, objectNewParameterTypeErrorMsg());
                return NULL;
            } else
1350
                raiseExcHelper(TypeError, "%s", objectNewParameterTypeErrorMsg());
1351 1352 1353 1354 1355 1356 1357 1358
        }
    }

    if (rewrite_args) {
        rewrite_args->out_rtn = r_made;
        rewrite_args->out_success = true;
    }

1359
    assert(made);
1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386
    return made;
}

Box* typeCall(Box* obj, BoxedTuple* vararg, BoxedDict* kwargs) {
    assert(vararg->cls == tuple_cls);

    bool pass_kwargs = (kwargs && kwargs->d.size());

    int n = vararg->size();
    int args_to_pass = n + 1 + (pass_kwargs ? 1 : 0); // 1 for obj, 1 for kwargs

    Box** args = NULL;
    if (args_to_pass > 3)
        args = (Box**)alloca(sizeof(Box*) * (args_to_pass - 3));

    Box* arg1, *arg2, *arg3;
    arg1 = obj;
    for (int i = 0; i < n; i++) {
        getArg(i + 1, arg1, arg2, arg3, args) = vararg->elts[i];
    }

    if (pass_kwargs)
        getArg(n + 1, arg1, arg2, arg3, args) = kwargs;

    return typeCallInternal(NULL, NULL, ArgPassSpec(n + 1, 0, false, pass_kwargs), arg1, arg2, arg3, args, NULL);
}

1387
void BoxedClass::gcHandler(GCVisitor* v, Box* b) {
1388
    Box::gcHandler(v, b);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
1389

1390
    BoxedClass* cls = (BoxedClass*)b;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
1391

1392
    if (cls->tp_base)
1393
        v->visit(&cls->tp_base);
1394
    if (cls->tp_dict)
1395
        v->visit(&cls->tp_dict);
1396
    if (cls->tp_mro)
1397
        v->visit(&cls->tp_mro);
1398
    if (cls->tp_bases)
1399
        v->visit(&cls->tp_bases);
1400
    if (cls->tp_subclasses)
1401
        v->visit(&cls->tp_subclasses);
1402 1403 1404 1405

    if (cls->tp_flags & Py_TPFLAGS_HEAPTYPE) {
        BoxedHeapClass* hcls = static_cast<BoxedHeapClass*>(cls);
        assert(hcls->ht_name);
1406
        v->visit(&hcls->ht_name);
1407
    }
Kevin Modzelewski's avatar
Kevin Modzelewski committed
1408 1409
}

1410
static Box* typeDict(Box* obj, void* context) {
1411 1412 1413 1414 1415 1416
    if (obj->cls->instancesHaveHCAttrs())
        return PyDictProxy_New(obj->getAttrWrapper());
    abort();
}

static Box* typeSubDict(Box* obj, void* context) {
1417
    if (obj->cls->instancesHaveHCAttrs())
1418
        return obj->getAttrWrapper();
1419 1420 1421 1422 1423
    if (obj->cls->instancesHaveDictAttrs())
        return obj->getDict();
    abort();
}

1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437
void Box::setDictBacked(Box* val) {
    assert(this->cls->instancesHaveHCAttrs());

    RELEASE_ASSERT(val->cls == dict_cls || val->cls == attrwrapper_cls, "");

    auto new_attr_list = (HCAttrs::AttrList*)gc_alloc(sizeof(HCAttrs::AttrList) + sizeof(Box*), gc::GCKind::PRECISE);
    new_attr_list->attrs[0] = val;

    HCAttrs* hcattrs = this->getHCAttrsPtr();

    hcattrs->hcls = HiddenClass::dict_backed;
    hcattrs->attr_list = new_attr_list;
}

1438
static void typeSubSetDict(Box* obj, Box* val, void* context) {
1439 1440 1441 1442 1443 1444 1445
    if (obj->cls->instancesHaveDictAttrs()) {
        RELEASE_ASSERT(val->cls == dict_cls, "");
        obj->setDict(static_cast<BoxedDict*>(val));
        return;
    }

    if (obj->cls->instancesHaveHCAttrs()) {
1446 1447 1448 1449 1450 1451 1452 1453 1454 1455
        RELEASE_ASSERT(PyDict_Check(val) || val->cls == attrwrapper_cls, "%s", val->cls->tp_name);

        auto new_attr_list
            = (HCAttrs::AttrList*)gc_alloc(sizeof(HCAttrs::AttrList) + sizeof(Box*), gc::GCKind::PRECISE);
        new_attr_list->attrs[0] = val;

        HCAttrs* hcattrs = obj->getHCAttrsPtr();

        hcattrs->hcls = HiddenClass::dict_backed;
        hcattrs->attr_list = new_attr_list;
1456 1457 1458 1459 1460
        return;
    }

    // This should have thrown an exception rather than get here:
    abort();
1461 1462
}

1463 1464 1465 1466 1467
extern "C" void PyType_SetDict(PyTypeObject* type, PyObject* dict) {
    typeSubSetDict(type, dict, NULL);
    type->tp_dict = dict;
}

1468 1469
Box* dict_descr = NULL;

1470
void BoxedInstanceMethod::gcHandler(GCVisitor* v, Box* b) {
1471
    Box::gcHandler(v, b);
1472

1473
    BoxedInstanceMethod* im = (BoxedInstanceMethod*)b;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
1474

1475 1476 1477
    v->visit(&im->obj);
    v->visit(&im->func);
    v->visit(&im->im_class);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
1478 1479
}

1480
void BoxedProperty::gcHandler(GCVisitor* v, Box* b) {
1481
    Box::gcHandler(v, b);
1482

1483 1484 1485
    BoxedProperty* prop = (BoxedProperty*)b;

    if (prop->prop_get)
1486
        v->visit(&prop->prop_get);
1487
    if (prop->prop_set)
1488
        v->visit(&prop->prop_set);
1489
    if (prop->prop_del)
1490
        v->visit(&prop->prop_del);
1491
    if (prop->prop_doc)
1492
        v->visit(&prop->prop_doc);
1493 1494
}

1495
void BoxedStaticmethod::gcHandler(GCVisitor* v, Box* b) {
1496
    Box::gcHandler(v, b);
1497

1498 1499 1500
    BoxedStaticmethod* sm = (BoxedStaticmethod*)b;

    if (sm->sm_callable)
1501
        v->visit(&sm->sm_callable);
1502 1503
}

1504
void BoxedClassmethod::gcHandler(GCVisitor* v, Box* b) {
1505
    Box::gcHandler(v, b);
1506

1507 1508 1509
    BoxedClassmethod* cm = (BoxedClassmethod*)b;

    if (cm->cm_callable)
1510
        v->visit(&cm->cm_callable);
1511 1512
}

1513 1514
void BoxedSlice::gcHandler(GCVisitor* v, Box* b) {
    assert(b->cls == slice_cls);
1515

1516
    Box::gcHandler(v, b);
1517

1518
    BoxedSlice* sl = static_cast<BoxedSlice*>(b);
1519

1520 1521 1522
    v->visit(&sl->start);
    v->visit(&sl->stop);
    v->visit(&sl->step);
1523 1524
}

1525 1526 1527
static int call_gc_visit(PyObject* val, void* arg) {
    if (val) {
        GCVisitor* v = static_cast<GCVisitor*>(arg);
1528
        v->visit(&val);
1529 1530 1531 1532 1533
    }
    return 0;
}

static void proxy_to_tp_traverse(GCVisitor* v, Box* b) {
1534
    Box::gcHandler(v, b);
1535 1536

    assert(b->cls->tp_traverse);
1537 1538 1539
    b->cls->tp_traverse(b, call_gc_visit, v);
}

1540 1541
void BoxedClosure::gcHandler(GCVisitor* v, Box* b) {
    assert(isSubclass(b->cls, closure_cls));
Kevin Modzelewski's avatar
Kevin Modzelewski committed
1542

1543
    Box::gcHandler(v, b);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
1544

1545
    BoxedClosure* c = (BoxedClosure*)b;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
1546
    if (c->parent)
1547
        v->visit(&c->parent);
Travis Hance's avatar
Travis Hance committed
1548 1549 1550

    for (int i = 0; i < c->nelts; i++) {
        if (c->elts[i])
1551
            v->visit(&c->elts[i]);
Travis Hance's avatar
Travis Hance committed
1552
    }
Kevin Modzelewski's avatar
Kevin Modzelewski committed
1553 1554
}

Kevin Modzelewski's avatar
Kevin Modzelewski committed
1555
extern "C" {
1556 1557
BoxedClass* object_cls, *type_cls, *none_cls, *bool_cls, *int_cls, *float_cls,
    * str_cls = NULL, *function_cls, *instancemethod_cls, *list_cls, *slice_cls, *module_cls, *dict_cls, *tuple_cls,
1558 1559 1560
      *file_cls, *member_descriptor_cls, *closure_cls, *generator_cls, *null_importer_cls, *complex_cls,
      *basestring_cls, *property_cls, *staticmethod_cls, *classmethod_cls, *attrwrapper_cls, *pyston_getset_cls,
      *capi_getset_cls, *builtin_function_or_method_cls, *attrwrapperiter_cls, *set_cls, *frozenset_cls;
1561 1562

BoxedTuple* EmptyTuple;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
1563 1564
}

1565
extern "C" Box* createUserClass(BoxedString* name, Box* _bases, Box* _attr_dict) {
1566
    ASSERT(_attr_dict->cls == dict_cls, "%s", getTypeName(_attr_dict));
1567 1568
    BoxedDict* attr_dict = static_cast<BoxedDict*>(_attr_dict);

Kevin Modzelewski's avatar
Kevin Modzelewski committed
1569 1570
    assert(_bases->cls == tuple_cls);
    BoxedTuple* bases = static_cast<BoxedTuple*>(_bases);
1571

Kevin Modzelewski's avatar
Kevin Modzelewski committed
1572
    Box* metaclass = NULL;
1573
    metaclass = attr_dict->getOrNull(boxString("__metaclass__"));
1574

Kevin Modzelewski's avatar
Kevin Modzelewski committed
1575
    if (metaclass != NULL) {
1576
    } else if (bases->size() > 0) {
Kevin Modzelewski's avatar
Kevin Modzelewski committed
1577 1578 1579
        // TODO Apparently this is supposed to look up __class__, and if that throws
        // an error, then look up ob_type (aka cls)
        metaclass = bases->elts[0]->cls;
1580
    } else {
1581 1582
        Box* gl = getGlobalsDict();
        metaclass = PyDict_GetItemString(gl, "__metaclass__");
1583

Kevin Modzelewski's avatar
Kevin Modzelewski committed
1584
        if (!metaclass) {
1585
            metaclass = classobj_cls;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
1586
        }
1587
    }
Kevin Modzelewski's avatar
Kevin Modzelewski committed
1588
    assert(metaclass);
1589

Kevin Modzelewski's avatar
Kevin Modzelewski committed
1590
    try {
1591
        Box* r = runtimeCall(metaclass, ArgPassSpec(3), name, _bases, _attr_dict, NULL, NULL);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
1592 1593
        RELEASE_ASSERT(r, "");
        return r;
1594 1595
    } catch (ExcInfo e) {
        RELEASE_ASSERT(e.matches(BaseException), "");
Kevin Modzelewski's avatar
Kevin Modzelewski committed
1596

1597 1598 1599
        Box* msg = e.value;
        assert(msg);
        // TODO this is an extra Pyston check and I don't think we should have to do it:
1600
        if (isSubclass(e.value->cls, BaseException)) {
1601
            static BoxedString* message_str = internStringImmortal("message");
1602 1603
            msg = getattr(e.value, message_str);
        }
1604

1605
        if (PyString_Check(msg)) {
1606 1607 1608 1609 1610 1611
            auto newmsg = PyString_FromFormat("Error when calling the metaclass bases\n"
                                              "    %s",
                                              PyString_AS_STRING(msg));
            if (newmsg)
                e.value = newmsg;
        }
Kevin Modzelewski's avatar
Kevin Modzelewski committed
1612

1613
        // Go through these routines since they do some normalization:
Kevin Modzelewski's avatar
Kevin Modzelewski committed
1614
        PyErr_Restore(e.type, e.value, e.traceback);
1615
        throwCAPIException();
Kevin Modzelewski's avatar
Kevin Modzelewski committed
1616
    }
Kevin Modzelewski's avatar
Kevin Modzelewski committed
1617 1618
}

1619
extern "C" Box* boxInstanceMethod(Box* obj, Box* func, Box* type) {
Kevin Modzelewski's avatar
Kevin Modzelewski committed
1620 1621 1622
    static StatCounter num_ims("num_instancemethods");
    num_ims.log();

1623
    return new BoxedInstanceMethod(obj, func, type);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
1624 1625
}

1626 1627
extern "C" Box* boxUnboundInstanceMethod(Box* func, Box* type) {
    return new BoxedInstanceMethod(NULL, func, type);
1628 1629
}

1630
extern "C" Box* none_repr(Box* v) noexcept {
1631
    return boxString("None");
Kevin Modzelewski's avatar
Kevin Modzelewski committed
1632 1633
}

1634
extern "C" Box* noneNonzero(Box* v) {
Kevin Modzelewski's avatar
Kevin Modzelewski committed
1635
    Py_RETURN_FALSE;
1636 1637
}

Travis Hance's avatar
Travis Hance committed
1638
extern "C" BoxedString* builtinFunctionOrMethodRepr(BoxedBuiltinFunctionOrMethod* v) {
1639 1640
    if (v->name != NULL)
        return (BoxedString*)PyString_FromFormat("<built-in function %s>", PyString_AsString(v->name));
Travis Hance's avatar
Travis Hance committed
1641 1642 1643
    RELEASE_ASSERT(false, "builtinFunctionOrMethodRepr not properly implemented");
}

1644 1645 1646 1647 1648
static Box* builtinFunctionOrMethodCall(BoxedBuiltinFunctionOrMethod* self, Box* args, Box* kwargs) {
    return runtimeCallInternal<CXX, NOT_REWRITABLE>(self, NULL, ArgPassSpec(0, 0, true, true), args, kwargs, NULL, NULL,
                                                    NULL);
}

Travis Hance's avatar
Travis Hance committed
1649
extern "C" BoxedString* functionRepr(BoxedFunction* v) {
1650 1651
    if (!v->name)
        return (BoxedString*)PyString_FromFormat("<function <name_missing?> at %p>", v);
1652
    return (BoxedString*)PyString_FromFormat("<function %s at %p>", PyString_AsString(v->name), v);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
1653 1654
}

1655 1656 1657 1658
static Box* functionGet(BoxedFunction* self, Box* inst, Box* owner) {
    RELEASE_ASSERT(self->cls == function_cls, "");

    if (inst == None)
1659 1660
        inst = NULL;
    return new BoxedInstanceMethod(inst, self, owner);
1661 1662
}

1663 1664 1665 1666 1667 1668 1669 1670
static Box* function_descr_get(Box* self, Box* inst, Box* owner) noexcept {
    RELEASE_ASSERT(self->cls == function_cls, "");

    if (inst == None)
        inst = NULL;
    return new BoxedInstanceMethod(inst, self, owner);
}

Kevin Modzelewski's avatar
Kevin Modzelewski committed
1671
static Box* functionCall(BoxedFunction* self, Box* args, Box* kwargs) {
1672
    RELEASE_ASSERT(self->cls == function_cls, "%s", getTypeName(self));
Kevin Modzelewski's avatar
Kevin Modzelewski committed
1673 1674 1675 1676 1677 1678 1679

    // This won't work if you subclass from function_cls, since runtimeCall will
    // just call back into this function.
    // Fortunately, CPython disallows subclassing FunctionType; we don't currently
    // disallow it but it's good to know.

    assert(args->cls == tuple_cls);
1680
    assert(!kwargs || kwargs->cls == dict_cls);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
1681 1682 1683
    return runtimeCall(self, ArgPassSpec(0, 0, true, true), args, kwargs, NULL, NULL, NULL);
}

1684
static Box* funcName(Box* b, void*) {
1685 1686
    assert(b->cls == function_cls);
    BoxedFunction* func = static_cast<BoxedFunction*>(b);
1687 1688
    if (func->name == NULL)
        return boxString("<unknown function name>");
1689
    return func->name;
1690 1691
}

1692
static void funcSetName(Box* b, Box* v, void*) {
1693 1694 1695 1696 1697 1698 1699 1700
    assert(b->cls == function_cls);
    BoxedFunction* func = static_cast<BoxedFunction*>(b);

    if (v == NULL || !PyString_Check(v)) {
        raiseExcHelper(TypeError, "__name__ must be set to a string object");
    }

    func->name = static_cast<BoxedString*>(v);
1701 1702
}

1703
static Box* builtinFunctionOrMethodName(Box* b, void*) {
1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714
    // In CPython, these guys just store char*, and it gets wrapped here
    // But we already share the BoxedString* field with BoxedFunctions...
    // so it's more convenient to just use that, which is what we do here.
    // Is there any advantage to using the char* way, here?

    assert(b->cls == builtin_function_or_method_cls);
    BoxedBuiltinFunctionOrMethod* func = static_cast<BoxedBuiltinFunctionOrMethod*>(b);
    assert(func->name);
    return func->name;
}

1715 1716 1717 1718 1719 1720
static Box* functionCode(Box* self, void*) {
    assert(self->cls == function_cls);
    BoxedFunction* func = static_cast<BoxedFunction*>(self);
    return codeForFunction(func);
}

1721 1722 1723 1724 1725 1726 1727 1728 1729
extern "C" PyObject* PyFunction_GetCode(PyObject* func) noexcept {
    try {
        return functionCode((Box*)func, NULL);
    } catch (ExcInfo e) {
        setCAPIException(e);
        return NULL;
    }
}

1730 1731 1732 1733 1734 1735 1736 1737 1738
static void functionSetCode(Box* self, Box* v, void*) {
    assert(self->cls == function_cls);

    if (v == NULL || !PyCode_Check(v))
        raiseExcHelper(TypeError, "__code__ must be set to a code object");

    BoxedFunction* func = static_cast<BoxedFunction*>(self);
    BoxedCode* code = static_cast<BoxedCode*>(v);

1739
    RELEASE_ASSERT(func->md->source && code->f->source, "__code__ can only be set on python functions");
1740

1741
    RELEASE_ASSERT(!func->md->internal_callable.get<CXX>() && !func->md->internal_callable.get<CAPI>(),
1742 1743
                   "this could cause invalidation issues");

1744
    func->md = code->f;
1745 1746 1747
    func->dependent_ics.invalidateAll();
}

1748 1749 1750
static Box* functionDefaults(Box* self, void*) {
    assert(self->cls == function_cls);
    BoxedFunction* func = static_cast<BoxedFunction*>(self);
1751
    if (!func->defaults)
1752
        return None;
1753 1754 1755 1756
    for (auto e : *func->defaults) {
        RELEASE_ASSERT(e, "this function's defaults should not be available");
    }
    return func->defaults;
1757 1758
}

1759 1760 1761 1762
static Box* functionGlobals(Box* self, void*) {
    assert(self->cls == function_cls);
    BoxedFunction* func = static_cast<BoxedFunction*>(self);
    if (func->globals) {
1763
        assert(!func->md->source || !func->md->source->scoping->areGlobalsFromModule());
1764 1765
        return func->globals;
    }
1766 1767
    assert(func->md->source);
    assert(func->md->source->scoping->areGlobalsFromModule());
1768

1769
    static BoxedString* dict_str = internStringImmortal("__dict__");
1770
    return getattr(func->md->source->parent_module, dict_str);
1771 1772
}

1773 1774 1775 1776
static void functionSetDefaults(Box* b, Box* v, void*) {
    assert(b->cls == function_cls);
    BoxedFunction* func = static_cast<BoxedFunction*>(b);

1777 1778 1779 1780 1781 1782
    // I guess this could happen if the user tried to do something like `min.__defaults__ = ()`.
    // In CPython that would be an AttributeError, but I think we might allow it to get to this point.
    // The better way to handle this would be to not add the __defaults__ descriptor to the
    // builtin_function_or_method_cls so that it would be an AttributeError to try to access it,
    // and leave this assert.
    RELEASE_ASSERT(func->can_change_defaults, "trying to change the defaults on a non-defaults-changable function.");
1783

1784 1785 1786
    if (v == None)
        v = NULL;
    else if (v && !PyTuple_Check(v)) {
1787 1788 1789 1790 1791
        raiseExcHelper(TypeError, "__defaults__ must be set to a tuple object");
    }

    BoxedTuple* t = static_cast<BoxedTuple*>(v);

1792 1793
    func->defaults = t;
    func->dependent_ics.invalidateAll();
1794 1795
}

Kevin Modzelewski's avatar
Kevin Modzelewski committed
1796
static Box* functionNonzero(BoxedFunction* self) {
Kevin Modzelewski's avatar
Kevin Modzelewski committed
1797
    Py_RETURN_TRUE;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
1798 1799
}

Kevin Modzelewski's avatar
Kevin Modzelewski committed
1800
extern "C" {
1801 1802 1803 1804 1805 1806 1807 1808 1809
Box* None = NULL;
Box* NotImplemented = NULL;
Box* repr_obj = NULL;
Box* len_obj = NULL;
Box* hash_obj = NULL;
Box* abs_obj = NULL;
Box* min_obj = NULL;
Box* max_obj = NULL;
Box* open_obj = NULL;
1810
Box* id_obj = NULL;
1811
Box* chr_obj = NULL;
1812
Box* ord_obj = NULL;
1813 1814
Box* trap_obj = NULL;
Box* range_obj = NULL;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
1815 1816
}

1817
HiddenClass* root_hcls;
1818
HiddenClass* HiddenClass::dict_backed;
1819

Kevin Modzelewski's avatar
Kevin Modzelewski committed
1820
extern "C" Box* createSlice(Box* start, Box* stop, Box* step) {
1821
    BoxedSlice* rtn = new BoxedSlice(start, stop, step);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
1822 1823 1824
    return rtn;
}

Travis Hance's avatar
Travis Hance committed
1825
extern "C" BoxedClosure* createClosure(BoxedClosure* parent_closure, size_t n) {
Kevin Modzelewski's avatar
Kevin Modzelewski committed
1826 1827
    if (parent_closure)
        assert(parent_closure->cls == closure_cls);
Travis Hance's avatar
Travis Hance committed
1828 1829 1830
    BoxedClosure* closure = new (n) BoxedClosure(parent_closure);
    assert(closure->cls == closure_cls);
    return closure;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
1831 1832
}

1833 1834
extern "C" Box* sliceNew(Box* cls, Box* start, Box* stop, Box** args) {
    RELEASE_ASSERT(cls == slice_cls, "");
1835
    Box* step = args[0];
1836 1837 1838

    if (stop == NULL)
        return createSlice(None, start, None);
1839 1840 1841
    return createSlice(start, stop, step);
}

Kevin Modzelewski's avatar
Kevin Modzelewski committed
1842
static Box* instancemethodCall(BoxedInstanceMethod* self, Box* args, Box* kwargs) {
1843
    // Not the most effficient, but it works:
1844 1845
    return runtimeCallInternal<CXX, NOT_REWRITABLE>(self, NULL, ArgPassSpec(0, 0, true, true), args, kwargs, NULL, NULL,
                                                    NULL);
1846
    // TODO add a tpp_call
Kevin Modzelewski's avatar
Kevin Modzelewski committed
1847 1848
}

1849 1850 1851 1852 1853 1854 1855
Box* instancemethodGet(BoxedInstanceMethod* self, Box* obj, Box* type) {
    RELEASE_ASSERT(self->cls == instancemethod_cls, "");

    if (self->obj != NULL) {
        return self;
    }

1856 1857 1858
    if (!PyObject_IsSubclass(type, self->im_class)) {
        return self;
    }
1859

1860 1861 1862
    if (obj == None)
        obj = NULL;

1863
    return new BoxedInstanceMethod(obj, self->func, self->im_class);
1864 1865
}

1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879
Box* instancemethodNew(BoxedClass* cls, Box* func, Box* self, Box** args) {
    Box* classObj = args[0];

    if (!PyCallable_Check(func)) {
        PyErr_SetString(PyExc_TypeError, "first argument must be callable");
        return NULL;
    }
    if (self == Py_None)
        self = NULL;
    if (self == NULL && classObj == NULL) {
        PyErr_SetString(PyExc_TypeError, "unbound methods must have non-NULL im_class");
        return NULL;
    }

1880
    return new BoxedInstanceMethod(self, func, classObj);
1881 1882
}

1883 1884 1885 1886 1887 1888 1889 1890 1891 1892
// Modified from cpython, Objects/object.c, instancemethod_repr
static Box* instancemethodRepr(Box* b) {
    assert(isSubclass(b->cls, instancemethod_cls));
    BoxedInstanceMethod* a = static_cast<BoxedInstanceMethod*>(b);
    Box* self = a->obj;
    Box* func = a->func;
    Box* klass = a->im_class;
    Box* funcname = NULL, * klassname = NULL, * result = NULL;
    const char* sfuncname = "?", * sklassname = "?";

1893
    static BoxedString* name_str = internStringImmortal("__name__");
1894
    funcname = getattrInternal<CXX>(func, name_str);
1895

1896 1897 1898 1899 1900 1901 1902 1903 1904 1905
    if (funcname != NULL) {
        if (!PyString_Check(funcname)) {
            funcname = NULL;
        } else
            sfuncname = PyString_AS_STRING(funcname);
    }

    if (klass == NULL) {
        klassname = NULL;
    } else {
1906
        klassname = getattrInternal<CXX>(klass, name_str);
1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924
        if (klassname != NULL) {
            if (!PyString_Check(klassname)) {
                klassname = NULL;
            } else {
                sklassname = PyString_AS_STRING(klassname);
            }
        }
    }

    if (self == NULL)
        result = PyString_FromFormat("<unbound method %s.%s>", sklassname, sfuncname);
    else {
        // This was a CPython comment: /* XXX Shouldn't use repr() here! */
        Box* selfrepr = repr(self);
        assert(PyString_Check(selfrepr));
        result = PyString_FromFormat("<bound method %s.%s of %s>", sklassname, sfuncname, PyString_AS_STRING(selfrepr));
    }
    return result;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
1925 1926
}

1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937
Box* instancemethodEq(BoxedInstanceMethod* self, Box* rhs) {
    if (rhs->cls != instancemethod_cls) {
        return boxBool(false);
    }

    BoxedInstanceMethod* rhs_im = static_cast<BoxedInstanceMethod*>(rhs);
    if (self->func == rhs_im->func) {
        if (self->obj == NULL && rhs_im->obj == NULL) {
            return boxBool(true);
        } else {
            if (self->obj != NULL && rhs_im->obj != NULL) {
1938
                return compareInternal<NOT_REWRITABLE>(self->obj, rhs_im->obj, AST_TYPE::Eq, NULL);
1939 1940 1941 1942 1943 1944 1945 1946 1947
            } else {
                return boxBool(false);
            }
        }
    } else {
        return boxBool(false);
    }
}

Kevin Modzelewski's avatar
Kevin Modzelewski committed
1948
Box* sliceRepr(BoxedSlice* self) {
1949 1950 1951
    BoxedString* start = static_cast<BoxedString*>(repr(self->start));
    BoxedString* stop = static_cast<BoxedString*>(repr(self->stop));
    BoxedString* step = static_cast<BoxedString*>(repr(self->step));
1952
    return boxStringTwine(llvm::Twine("slice(") + start->s() + ", " + stop->s() + ", " + step->s() + ")");
Kevin Modzelewski's avatar
Kevin Modzelewski committed
1953 1954
}

1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996
Box* sliceHash(BoxedSlice* self) {
    raiseExcHelper(TypeError, "unhashable type");
    return boxLong(-1l);
}

Box* sliceReduce(BoxedSlice* self) {
    return Py_BuildValue("O(OOO)", self->cls, self->start, self->stop, self->step);
}

Box* sliceIndices(BoxedSlice* self, Box* len) {
    Py_ssize_t ilen, start, stop, step, slicelength;

    ilen = PyNumber_AsSsize_t(len, PyExc_OverflowError);

    if (ilen == -1 && PyErr_Occurred()) {
        throwCAPIException();
    }

    if (PySlice_GetIndicesEx((PySliceObject*)self, ilen, &start, &stop, &step, &slicelength) < 0) {
        throwCAPIException();
    }
    return BoxedTuple::create({ boxInt(start), boxInt(stop), boxInt(step) });
}

static int slice_compare(PySliceObject* v, PySliceObject* w) noexcept {
    int result = 0;

    if (v == w)
        return 0;

    if (PyObject_Cmp(v->start, w->start, &result) < 0)
        return -2;
    if (result != 0)
        return result;
    if (PyObject_Cmp(v->stop, w->stop, &result) < 0)
        return -2;
    if (result != 0)
        return result;
    if (PyObject_Cmp(v->step, w->step, &result) < 0)
        return -2;
    return result;
}
1997
extern "C" int PySlice_GetIndices(PySliceObject* r, Py_ssize_t length, Py_ssize_t* start, Py_ssize_t* stop,
1998
                                  Py_ssize_t* step) noexcept {
1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031
    /* XXX support long ints */
    if (r->step == Py_None) {
        *step = 1;
    } else {
        if (!PyInt_Check(r->step) && !PyLong_Check(r->step))
            return -1;
        *step = PyInt_AsSsize_t(r->step);
    }
    if (r->start == Py_None) {
        *start = *step < 0 ? length - 1 : 0;
    } else {
        if (!PyInt_Check(r->start) && !PyLong_Check(r->step))
            return -1;
        *start = PyInt_AsSsize_t(r->start);
        if (*start < 0)
            *start += length;
    }
    if (r->stop == Py_None) {
        *stop = *step < 0 ? -1 : length;
    } else {
        if (!PyInt_Check(r->stop) && !PyLong_Check(r->step))
            return -1;
        *stop = PyInt_AsSsize_t(r->stop);
        if (*stop < 0)
            *stop += length;
    }
    if (*stop > length)
        return -1;
    if (*start >= length)
        return -1;
    if (*step == 0)
        return -1;
    return 0;
2032 2033
}

Marius Wachtler's avatar
Marius Wachtler committed
2034
extern "C" int PySlice_GetIndicesEx(PySliceObject* _r, Py_ssize_t length, Py_ssize_t* start, Py_ssize_t* stop,
2035
                                    Py_ssize_t* step, Py_ssize_t* slicelength) noexcept {
2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080
    BoxedSlice* r = (BoxedSlice*)_r;
    RELEASE_ASSERT(r->cls == slice_cls, "");

    /* this is harder to get right than you might think */

    Py_ssize_t defstart, defstop;

    if (r->step == Py_None) {
        *step = 1;
    } else {
        if (!_PyEval_SliceIndex(r->step, step))
            return -1;
        if (*step == 0) {
            PyErr_SetString(PyExc_ValueError, "slice step cannot be zero");
            return -1;
        }
    }

    defstart = *step < 0 ? length - 1 : 0;
    defstop = *step < 0 ? -1 : length;

    if (r->start == Py_None) {
        *start = defstart;
    } else {
        if (!_PyEval_SliceIndex(r->start, start))
            return -1;
        if (*start < 0)
            *start += length;
        if (*start < 0)
            *start = (*step < 0) ? -1 : 0;
        if (*start >= length)
            *start = (*step < 0) ? length - 1 : length;
    }

    if (r->stop == Py_None) {
        *stop = defstop;
    } else {
        if (!_PyEval_SliceIndex(r->stop, stop))
            return -1;
        if (*stop < 0)
            *stop += length;
        if (*stop < 0)
            *stop = (*step < 0) ? -1 : 0;
        if (*stop >= length)
            *stop = (*step < 0) ? length - 1 : length;
Marius Wachtler's avatar
Marius Wachtler committed
2081
    }
2082 2083 2084

    if ((*step < 0 && *stop >= *start) || (*step > 0 && *start >= *stop)) {
        *slicelength = 0;
2085 2086
    } else if (*step == 1) { // Pyston change: added this branch to make the common step==1 case avoid the div:
        *slicelength = (*stop - *start - 1) + 1;
2087 2088 2089 2090 2091 2092
    } else if (*step < 0) {
        *slicelength = (*stop - *start + 1) / (*step) + 1;
    } else {
        *slicelength = (*stop - *start - 1) / (*step) + 1;
    }

Marius Wachtler's avatar
Marius Wachtler committed
2093
    return 0;
2094 2095
}

2096 2097 2098 2099 2100 2101 2102 2103 2104 2105
extern "C" PyObject* PySlice_New(PyObject* start, PyObject* stop, PyObject* step) noexcept {
    if (step == NULL)
        step = Py_None;
    if (start == NULL)
        start = Py_None;
    if (stop == NULL)
        stop = Py_None;
    return createSlice(start, stop, step);
}

Kevin Modzelewski's avatar
Kevin Modzelewski committed
2106
Box* typeRepr(BoxedClass* self) {
2107 2108 2109
    std::string O("");
    llvm::raw_string_ostream os(O);

2110
    if ((self->tp_flags & Py_TPFLAGS_HEAPTYPE) && self->is_user_defined)
Kevin Modzelewski's avatar
Kevin Modzelewski committed
2111
        os << "<class '";
Kevin Modzelewski's avatar
Kevin Modzelewski committed
2112 2113
    else
        os << "<type '";
Kevin Modzelewski's avatar
Kevin Modzelewski committed
2114

2115 2116
    static BoxedString* module_str = internStringImmortal("__module__");
    Box* m = self->getattr(module_str);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
2117 2118
    if (m && m->cls == str_cls) {
        BoxedString* sm = static_cast<BoxedString*>(m);
2119 2120
        if (sm->s() != "__builtin__")
            os << sm->s() << '.';
Kevin Modzelewski's avatar
Kevin Modzelewski committed
2121
    }
Kevin Modzelewski's avatar
Kevin Modzelewski committed
2122

2123
    os << self->tp_name;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
2124

Kevin Modzelewski's avatar
Kevin Modzelewski committed
2125
    os << "'>";
Kevin Modzelewski's avatar
Kevin Modzelewski committed
2126

Kevin Modzelewski's avatar
Kevin Modzelewski committed
2127
    return boxString(os.str());
Kevin Modzelewski's avatar
Kevin Modzelewski committed
2128 2129
}

2130 2131 2132 2133 2134 2135
static PyObject* typeModule(Box* _type, void* context) {
    PyTypeObject* type = static_cast<PyTypeObject*>(_type);

    PyObject* mod;
    const char* s;

Kevin Modzelewski's avatar
Kevin Modzelewski committed
2136
    if (type->tp_flags & Py_TPFLAGS_HEAPTYPE && type->is_user_defined) {
2137 2138
        static BoxedString* module_str = internStringImmortal("__module__");
        mod = type->getattr(module_str);
2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161
        if (!mod)
            raiseExcHelper(AttributeError, "__module__");
        return mod;
    } else {
        s = strrchr(type->tp_name, '.');
        if (s != NULL)
            return PyString_FromStringAndSize(type->tp_name, (Py_ssize_t)(s - type->tp_name));
        return PyString_FromString("__builtin__");
    }
}

static void typeSetModule(Box* _type, PyObject* value, void* context) {
    PyTypeObject* type = static_cast<PyTypeObject*>(_type);

    if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) {
        raiseExcHelper(TypeError, "can't set %s.__module__", type->tp_name);
    }
    if (!value) {
        raiseExcHelper(TypeError, "can't delete %s.__module__", type->tp_name);
    }

    PyType_Modified(type);

2162 2163
    static BoxedString* module_str = internStringImmortal("__module__");
    type->setattr(module_str, value, NULL);
2164 2165
}

2166

2167
Box* typeHash(BoxedClass* self) {
2168
    assert(PyType_Check(self));
2169
    return boxInt(_Py_HashPointer(self));
2170 2171
}

2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198
static PyObject* type_subclasses(PyTypeObject* type, PyObject* args_ignored) noexcept {
    PyObject* list, *raw, *ref;
    Py_ssize_t i, n;

    list = PyList_New(0);
    if (list == NULL)
        return NULL;
    raw = type->tp_subclasses;
    if (raw == NULL)
        return list;
    assert(PyList_Check(raw));
    n = PyList_GET_SIZE(raw);
    for (i = 0; i < n; i++) {
        ref = PyList_GET_ITEM(raw, i);
        assert(PyWeakref_CheckRef(ref));
        ref = PyWeakref_GET_OBJECT(ref);
        if (ref != Py_None) {
            if (PyList_Append(list, ref) < 0) {
                Py_DECREF(list);
                return NULL;
            }
        }
    }
    return list;
}

Box* typeSubclasses(BoxedClass* self) {
2199
    assert(PyType_Check(self));
2200 2201 2202 2203 2204
    Box* rtn = type_subclasses(self, 0);
    checkAndThrowCAPIException();
    return rtn;
}

2205
Box* typeMro(BoxedClass* self) {
2206
    assert(PyType_Check(self));
2207 2208 2209 2210 2211 2212 2213

    Box* r = mro_external(self);
    if (!r)
        throwCAPIException();
    return r;
}

2214
Box* moduleInit(BoxedModule* self, Box* name, Box* doc) {
2215
    RELEASE_ASSERT(PyModule_Check(self), "");
2216
    RELEASE_ASSERT(name->cls == str_cls, "");
2217 2218 2219
    RELEASE_ASSERT(!doc || doc->cls == str_cls || doc->cls == unicode_cls, "");

    doc = doc ? doc : None;
2220

2221 2222
    HCAttrs* attrs = self->getHCAttrsPtr();

2223 2224 2225 2226 2227 2228 2229 2230 2231
    if (attrs->hcls->attributeArraySize() == 0) {
        attrs->hcls = HiddenClass::makeSingleton();

        self->giveAttr("__name__", name);
        self->giveAttr("__doc__", doc);
    } else {
        self->setattr(internStringMortal("__name__"), name, NULL);
        self->setattr(internStringMortal("__doc__"), doc, NULL);
    }
2232 2233

    return None;
2234 2235
}

Kevin Modzelewski's avatar
Kevin Modzelewski committed
2236
Box* moduleRepr(BoxedModule* m) {
2237
    RELEASE_ASSERT(PyModule_Check(m), "");
Kevin Modzelewski's avatar
Kevin Modzelewski committed
2238

2239 2240 2241
    std::string O("");
    llvm::raw_string_ostream os(O);

2242
    os << "<module '" << m->name() << "' ";
Kevin Modzelewski's avatar
Kevin Modzelewski committed
2243

2244 2245 2246 2247
    const char* filename = PyModule_GetFilename((PyObject*)m);
    // TODO(kmod): builtin modules are not supposed to have a __file__ attribute
    if (!filename || !strcmp(filename, "__builtin__")) {
        PyErr_Clear();
2248
        os << "(built-in)>";
2249
    } else {
2250
        os << "from '" << filename << "'>";
2251
    }
Kevin Modzelewski's avatar
Kevin Modzelewski committed
2252 2253 2254
    return boxString(os.str());
}

Kevin Modzelewski's avatar
Kevin Modzelewski committed
2255 2256 2257 2258 2259 2260
class AttrWrapper;
class AttrWrapperIter : public Box {
private:
    // Iterating over the an attrwrapper (~=dict) just gives the keys, which
    // just depends on the hidden class of the object.  Let's store only that:
    HiddenClass* hcls;
2261
    llvm::DenseMap<BoxedString*, int>::const_iterator it;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
2262 2263 2264 2265 2266 2267 2268

public:
    AttrWrapperIter(AttrWrapper* aw);

    DEFAULT_CLASS(attrwrapperiter_cls);

    static void gcHandler(GCVisitor* v, Box* b) {
2269
        Box::gcHandler(v, b);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
2270 2271

        AttrWrapperIter* self = (AttrWrapperIter*)b;
2272
        v->visit(&self->hcls);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
2273 2274 2275 2276
    }

    static Box* hasnext(Box* _self);
    static Box* next(Box* _self);
2277
    static Box* next_capi(Box* _self) noexcept;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
2278 2279
};

2280 2281 2282 2283 2284 2285 2286
// A dictionary-like wrapper around the attributes array.
// Not sure if this will be enough to satisfy users who expect __dict__
// or PyModule_GetDict to return real dicts.
class AttrWrapper : public Box {
private:
    Box* b;

2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308
    void convertToDictBacked() {
        HCAttrs* attrs = this->b->getHCAttrsPtr();
        if (attrs->hcls->type == HiddenClass::DICT_BACKED)
            return;

        BoxedDict* d = new BoxedDict();

        RELEASE_ASSERT(attrs->hcls->type == HiddenClass::NORMAL || attrs->hcls->type == HiddenClass::SINGLETON, "");
        for (const auto& p : attrs->hcls->getStrAttrOffsets()) {
            d->d[p.first] = attrs->attr_list->attrs[p.second];
        }

        b->setDictBacked(d);
    }

    bool isDictBacked() { return b->getHCAttrsPtr()->hcls->type == HiddenClass::DICT_BACKED; }

    Box* getDictBacking() {
        assert(isDictBacked());
        return b->getHCAttrsPtr()->attr_list->attrs[0];
    }

2309
public:
2310 2311 2312 2313 2314 2315 2316 2317
    AttrWrapper(Box* b) : b(b) {
        assert(b->cls->instancesHaveHCAttrs());

        // We currently don't support creating an attrwrapper around a dict-backed object,
        // so try asserting that here.
        // This check doesn't cover all cases, since an attrwrapper could be created around
        // a normal object which then becomes dict-backed, so we RELEASE_ASSERT later
        // that that doesn't happen.
2318 2319
        assert(b->getHCAttrsPtr()->hcls->type == HiddenClass::NORMAL
               || b->getHCAttrsPtr()->hcls->type == HiddenClass::SINGLETON);
2320
    }
2321 2322

    DEFAULT_CLASS(attrwrapper_cls);
2323

Kevin Modzelewski's avatar
Kevin Modzelewski committed
2324
    Box* getUnderlying() { return b; }
2325

2326
    static void gcHandler(GCVisitor* v, Box* b) {
2327
        Box::gcHandler(v, b);
2328 2329

        AttrWrapper* aw = (AttrWrapper*)b;
2330
        v->visit(&aw->b);
2331 2332 2333 2334 2335 2336
    }

    static Box* setitem(Box* _self, Box* _key, Box* value) {
        RELEASE_ASSERT(_self->cls == attrwrapper_cls, "");
        AttrWrapper* self = static_cast<AttrWrapper*>(_self);

2337 2338
        if (_key->cls != str_cls)
            self->convertToDictBacked();
2339

2340 2341
        if (self->isDictBacked()) {
            static BoxedString* setitem_str = internStringImmortal("__setitem__");
2342 2343
            return callattrInternal<CXX, NOT_REWRITABLE>(self->getDictBacking(), setitem_str, LookupScope::CLASS_ONLY,
                                                         NULL, ArgPassSpec(2), _key, value, NULL, NULL, NULL);
2344 2345 2346
        }

        assert(_key->cls == str_cls);
2347
        BoxedString* key = static_cast<BoxedString*>(_key);
2348 2349 2350
        internStringMortalInplace(key);

        self->b->setattr(key, value, NULL);
2351 2352 2353
        return None;
    }

2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369
    static int ass_sub(PyDictObject* mp, PyObject* v, PyObject* w) noexcept {
        try {
            Box* res;
            if (w == NULL) {
                res = AttrWrapper::delitem((Box*)mp, v);
            } else {
                res = AttrWrapper::setitem((Box*)mp, v, w);
            }
            assert(res == None);
        } catch (ExcInfo e) {
            setCAPIException(e);
            return -1;
        }
        return 0;
    }

Kevin Modzelewski's avatar
Kevin Modzelewski committed
2370 2371 2372 2373
    static Box* setdefault(Box* _self, Box* _key, Box* value) {
        RELEASE_ASSERT(_self->cls == attrwrapper_cls, "");
        AttrWrapper* self = static_cast<AttrWrapper*>(_self);

2374 2375
        if (_key->cls != str_cls)
            self->convertToDictBacked();
Kevin Modzelewski's avatar
Kevin Modzelewski committed
2376

2377 2378
        if (self->isDictBacked()) {
            static BoxedString* setdefault_str = internStringImmortal("setdefault");
2379 2380 2381
            return callattrInternal<CXX, NOT_REWRITABLE>(self->getDictBacking(), setdefault_str,
                                                         LookupScope::CLASS_ONLY, NULL, ArgPassSpec(2), _key, value,
                                                         NULL, NULL, NULL);
2382 2383 2384
        }

        assert(_key->cls == str_cls);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
2385
        BoxedString* key = static_cast<BoxedString*>(_key);
2386 2387 2388
        internStringMortalInplace(key);

        Box* cur = self->b->getattr(key);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
2389 2390
        if (cur)
            return cur;
2391
        self->b->setattr(key, value, NULL);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
2392 2393 2394
        return value;
    }

2395 2396 2397 2398
    static Box* get(Box* _self, Box* _key, Box* def) {
        RELEASE_ASSERT(_self->cls == attrwrapper_cls, "");
        AttrWrapper* self = static_cast<AttrWrapper*>(_self);

2399
        _key = coerceUnicodeToStr<CXX>(_key);
2400

2401 2402
        RELEASE_ASSERT(_key->cls == str_cls, "");
        BoxedString* key = static_cast<BoxedString*>(_key);
2403 2404 2405
        internStringMortalInplace(key);

        Box* r = self->b->getattr(key);
2406 2407 2408 2409 2410
        if (!r)
            return def;
        return r;
    }

2411
    template <ExceptionStyle S> static Box* getitem(Box* _self, Box* _key) noexcept(S == CAPI) {
2412 2413 2414
        RELEASE_ASSERT(_self->cls == attrwrapper_cls, "");
        AttrWrapper* self = static_cast<AttrWrapper*>(_self);

2415 2416 2417
        _key = coerceUnicodeToStr<S>(_key);
        if (S == CAPI && !_key)
            return NULL;
2418

2419
        RELEASE_ASSERT(_key->cls == str_cls, "");
2420
        BoxedString* key = static_cast<BoxedString*>(_key);
2421 2422 2423
        internStringMortalInplace(key);

        Box* r = self->b->getattr(key);
2424 2425 2426 2427 2428 2429
        if (!r) {
            if (S == CXX)
                raiseExcHelper(KeyError, "'%s'", key->data());
            else
                PyErr_Format(KeyError, "'%s'", key->data());
        }
Kevin Modzelewski's avatar
Kevin Modzelewski committed
2430
        return r;
2431 2432
    }

Kevin Modzelewski's avatar
Kevin Modzelewski committed
2433 2434 2435 2436
    static Box* pop(Box* _self, Box* _key, Box* default_) {
        RELEASE_ASSERT(_self->cls == attrwrapper_cls, "");
        AttrWrapper* self = static_cast<AttrWrapper*>(_self);

2437
        _key = coerceUnicodeToStr<CXX>(_key);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
2438 2439 2440

        RELEASE_ASSERT(_key->cls == str_cls, "");
        BoxedString* key = static_cast<BoxedString*>(_key);
2441 2442 2443
        internStringMortalInplace(key);

        Box* r = self->b->getattr(key);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
2444
        if (r) {
2445
            self->b->delattr(key, NULL);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
2446 2447 2448 2449 2450 2451 2452 2453
            return r;
        } else {
            if (default_)
                return default_;
            raiseExcHelper(KeyError, "'%s'", key->data());
        }
    }

2454 2455 2456 2457
    static Box* delitem(Box* _self, Box* _key) {
        RELEASE_ASSERT(_self->cls == attrwrapper_cls, "");
        AttrWrapper* self = static_cast<AttrWrapper*>(_self);

2458
        _key = coerceUnicodeToStr<CXX>(_key);
2459

2460
        RELEASE_ASSERT(_key->cls == str_cls, "");
2461
        BoxedString* key = static_cast<BoxedString*>(_key);
2462 2463 2464 2465
        internStringMortalInplace(key);

        if (self->b->getattr(key))
            self->b->delattr(key, NULL);
2466
        else
2467
            raiseExcHelper(KeyError, "'%s'", key->data());
2468 2469 2470
        return None;
    }

2471 2472 2473 2474
    static Box* str(Box* _self) {
        RELEASE_ASSERT(_self->cls == attrwrapper_cls, "");
        AttrWrapper* self = static_cast<AttrWrapper*>(_self);

2475 2476 2477
        std::string O("");
        llvm::raw_string_ostream os(O);

2478 2479
        os << "attrwrapper({";

2480
        HCAttrs* attrs = self->b->getHCAttrsPtr();
2481
        RELEASE_ASSERT(attrs->hcls->type == HiddenClass::NORMAL || attrs->hcls->type == HiddenClass::SINGLETON, "");
2482
        bool first = true;
2483
        for (const auto& p : attrs->hcls->getStrAttrOffsets()) {
2484 2485 2486 2487
            if (!first)
                os << ", ";
            first = false;

2488
            BoxedString* v = attrs->attr_list->attrs[p.second]->reprICAsString();
2489
            os << p.first->s() << ": " << v->s();
2490 2491 2492 2493
        }
        os << "})";
        return boxString(os.str());
    }
Kevin Modzelewski's avatar
Kevin Modzelewski committed
2494

2495
    template <ExceptionStyle S> static Box* contains(Box* _self, Box* _key) noexcept(S == CAPI) {
Kevin Modzelewski's avatar
Kevin Modzelewski committed
2496 2497 2498
        RELEASE_ASSERT(_self->cls == attrwrapper_cls, "");
        AttrWrapper* self = static_cast<AttrWrapper*>(_self);

2499 2500 2501
        _key = coerceUnicodeToStr<S>(_key);
        if (S == CAPI && !_key)
            return NULL;
2502

Kevin Modzelewski's avatar
Kevin Modzelewski committed
2503 2504
        RELEASE_ASSERT(_key->cls == str_cls, "");
        BoxedString* key = static_cast<BoxedString*>(_key);
2505 2506 2507
        internStringMortalInplace(key);

        Box* r = self->b->getattr(key);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
2508 2509
        return r ? True : False;
    }
Kevin Modzelewski's avatar
Kevin Modzelewski committed
2510

2511 2512 2513 2514 2515 2516 2517
    static int sq_contains(Box* _self, Box* _key) noexcept {
        Box* rtn = contains<CAPI>(_self, _key);
        if (!rtn)
            return -1;
        return rtn == True;
    }

2518 2519 2520 2521 2522 2523 2524
    static Box* keys(Box* _self) {
        RELEASE_ASSERT(_self->cls == attrwrapper_cls, "");
        AttrWrapper* self = static_cast<AttrWrapper*>(_self);

        BoxedList* rtn = new BoxedList();

        HCAttrs* attrs = self->b->getHCAttrsPtr();
2525
        RELEASE_ASSERT(attrs->hcls->type == HiddenClass::NORMAL || attrs->hcls->type == HiddenClass::SINGLETON, "");
2526
        for (const auto& p : attrs->hcls->getStrAttrOffsets()) {
2527
            listAppend(rtn, p.first);
2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538
        }
        return rtn;
    }

    static Box* values(Box* _self) {
        RELEASE_ASSERT(_self->cls == attrwrapper_cls, "");
        AttrWrapper* self = static_cast<AttrWrapper*>(_self);

        BoxedList* rtn = new BoxedList();

        HCAttrs* attrs = self->b->getHCAttrsPtr();
2539
        RELEASE_ASSERT(attrs->hcls->type == HiddenClass::NORMAL || attrs->hcls->type == HiddenClass::SINGLETON, "");
2540
        for (const auto& p : attrs->hcls->getStrAttrOffsets()) {
2541 2542 2543 2544 2545
            listAppend(rtn, attrs->attr_list->attrs[p.second]);
        }
        return rtn;
    }

Kevin Modzelewski's avatar
Kevin Modzelewski committed
2546 2547 2548 2549 2550 2551
    static Box* items(Box* _self) {
        RELEASE_ASSERT(_self->cls == attrwrapper_cls, "");
        AttrWrapper* self = static_cast<AttrWrapper*>(_self);

        BoxedList* rtn = new BoxedList();

2552
        HCAttrs* attrs = self->b->getHCAttrsPtr();
2553
        RELEASE_ASSERT(attrs->hcls->type == HiddenClass::NORMAL || attrs->hcls->type == HiddenClass::SINGLETON, "");
2554
        for (const auto& p : attrs->hcls->getStrAttrOffsets()) {
2555
            BoxedTuple* t = BoxedTuple::create({ p.first, attrs->attr_list->attrs[p.second] });
Kevin Modzelewski's avatar
Kevin Modzelewski committed
2556 2557 2558 2559
            listAppend(rtn, t);
        }
        return rtn;
    }
2560

2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575
    static Box* iterkeys(Box* _self) {
        Box* r = AttrWrapper::keys(_self);
        return getiter(r);
    }

    static Box* itervalues(Box* _self) {
        Box* r = AttrWrapper::values(_self);
        return getiter(r);
    }

    static Box* iteritems(Box* _self) {
        Box* r = AttrWrapper::items(_self);
        return getiter(r);
    }

Kevin Modzelewski's avatar
Kevin Modzelewski committed
2576 2577 2578 2579 2580 2581 2582
    static Box* copy(Box* _self) {
        RELEASE_ASSERT(_self->cls == attrwrapper_cls, "");
        AttrWrapper* self = static_cast<AttrWrapper*>(_self);

        BoxedDict* rtn = new BoxedDict();

        HCAttrs* attrs = self->b->getHCAttrsPtr();
2583
        RELEASE_ASSERT(attrs->hcls->type == HiddenClass::NORMAL || attrs->hcls->type == HiddenClass::SINGLETON, "");
2584
        for (const auto& p : attrs->hcls->getStrAttrOffsets()) {
2585
            rtn->d[p.first] = attrs->attr_list->attrs[p.second];
Kevin Modzelewski's avatar
Kevin Modzelewski committed
2586 2587 2588 2589
        }
        return rtn;
    }

Marius Wachtler's avatar
Marius Wachtler committed
2590 2591 2592 2593 2594 2595 2596
    static Box* clear(Box* _self) {
        RELEASE_ASSERT(_self->cls == attrwrapper_cls, "");
        AttrWrapper* self = static_cast<AttrWrapper*>(_self);

        HCAttrs* attrs = self->b->getHCAttrsPtr();
        RELEASE_ASSERT(attrs->hcls->type == HiddenClass::NORMAL || attrs->hcls->type == HiddenClass::SINGLETON, "");

2597 2598 2599 2600 2601 2602
        // Clear the attrs array:
        new ((void*)attrs) HCAttrs(root_hcls);
        // Add the existing attrwrapper object (ie self) back as the attrwrapper:
        self->b->appendNewHCAttr(self, NULL);
        attrs->hcls = attrs->hcls->getAttrwrapperChild();

Marius Wachtler's avatar
Marius Wachtler committed
2603 2604 2605
        return None;
    }

2606 2607 2608 2609 2610
    static Box* len(Box* _self) {
        RELEASE_ASSERT(_self->cls == attrwrapper_cls, "");
        AttrWrapper* self = static_cast<AttrWrapper*>(_self);

        HCAttrs* attrs = self->b->getHCAttrsPtr();
2611
        RELEASE_ASSERT(attrs->hcls->type == HiddenClass::NORMAL || attrs->hcls->type == HiddenClass::SINGLETON, "");
2612
        return boxInt(attrs->hcls->getStrAttrOffsets().size());
2613
    }
Marius Wachtler's avatar
Marius Wachtler committed
2614

Kevin Modzelewski's avatar
Kevin Modzelewski committed
2615
    static Box* update(Box* _self, BoxedTuple* args, BoxedDict* kwargs) {
Marius Wachtler's avatar
Marius Wachtler committed
2616 2617 2618
        RELEASE_ASSERT(_self->cls == attrwrapper_cls, "");
        AttrWrapper* self = static_cast<AttrWrapper*>(_self);

Kevin Modzelewski's avatar
Kevin Modzelewski committed
2619
        assert(args->cls == tuple_cls);
2620
        assert(!kwargs || kwargs->cls == dict_cls);
Marius Wachtler's avatar
Marius Wachtler committed
2621

Kevin Modzelewski's avatar
Kevin Modzelewski committed
2622 2623 2624 2625 2626 2627
        RELEASE_ASSERT(args->size() <= 1, ""); // should throw a TypeError

        auto handle = [&](Box* _container) {
            if (_container->cls == attrwrapper_cls) {
                AttrWrapper* container = static_cast<AttrWrapper*>(_container);
                HCAttrs* attrs = container->b->getHCAttrsPtr();
Kevin Modzelewski's avatar
Kevin Modzelewski committed
2628

Kevin Modzelewski's avatar
Kevin Modzelewski committed
2629 2630 2631
                RELEASE_ASSERT(attrs->hcls->type == HiddenClass::NORMAL || attrs->hcls->type == HiddenClass::SINGLETON,
                               "");
                for (const auto& p : attrs->hcls->getStrAttrOffsets()) {
2632
                    self->b->setattr(p.first, attrs->attr_list->attrs[p.second], NULL);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
2633
                }
2634 2635 2636 2637
            } else {
                // The update rules are too complicated to be worth duplicating here;
                // just create a new dict object and defer to dictUpdate.
                // Hopefully this does not happen very often.
2638
                if (!PyDict_Check(_container)) {
2639 2640 2641 2642
                    BoxedDict* new_container = new BoxedDict();
                    dictUpdate(new_container, BoxedTuple::create({ _container }), new BoxedDict());
                    _container = new_container;
                }
2643
                assert(PyDict_Check(_container));
Kevin Modzelewski's avatar
Kevin Modzelewski committed
2644 2645
                BoxedDict* container = static_cast<BoxedDict*>(_container);

2646
                for (const auto& p : *container) {
Kevin Modzelewski's avatar
Kevin Modzelewski committed
2647 2648
                    AttrWrapper::setitem(self, p.first, p.second);
                }
Kevin Modzelewski's avatar
Kevin Modzelewski committed
2649
            }
Kevin Modzelewski's avatar
Kevin Modzelewski committed
2650 2651 2652 2653
        };

        for (auto e : *args) {
            handle(e);
Marius Wachtler's avatar
Marius Wachtler committed
2654
        }
2655 2656
        if (kwargs)
            handle(kwargs);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
2657

Marius Wachtler's avatar
Marius Wachtler committed
2658 2659
        return None;
    }
Kevin Modzelewski's avatar
Kevin Modzelewski committed
2660

2661
    static Box* iter(Box* _self) noexcept {
Kevin Modzelewski's avatar
Kevin Modzelewski committed
2662 2663 2664
        RELEASE_ASSERT(_self->cls == attrwrapper_cls, "");
        AttrWrapper* self = static_cast<AttrWrapper*>(_self);

2665 2666
        if (self->isDictBacked()) {
            static BoxedString* iter_str = internStringImmortal("__iter__");
2667 2668
            return callattrInternal<CXX, NOT_REWRITABLE>(self->getDictBacking(), iter_str, LookupScope::CLASS_ONLY,
                                                         NULL, ArgPassSpec(0), NULL, NULL, NULL, NULL, NULL);
2669 2670
        }

Kevin Modzelewski's avatar
Kevin Modzelewski committed
2671 2672 2673
        return new AttrWrapperIter(self);
    }

2674 2675 2676 2677 2678 2679 2680
    static Box* eq(Box* _self, Box* _other) {
        RELEASE_ASSERT(_self->cls == attrwrapper_cls, "");
        AttrWrapper* self = static_cast<AttrWrapper*>(_self);

        // In order to not have to reimplement dict cmp: just create a real dict for now and us it.
        BoxedDict* dict = (BoxedDict*)AttrWrapper::copy(_self);
        assert(dict->cls == dict_cls);
2681
        static BoxedString* eq_str = internStringImmortal("__eq__");
2682 2683
        return callattrInternal<CXX, NOT_REWRITABLE>(dict, eq_str, LookupScope::CLASS_ONLY, NULL, ArgPassSpec(1),
                                                     _other, NULL, NULL, NULL, NULL);
2684 2685 2686 2687
    }

    static Box* ne(Box* _self, Box* _other) { return eq(_self, _other) == True ? False : True; }

Kevin Modzelewski's avatar
Kevin Modzelewski committed
2688
    friend class AttrWrapperIter;
2689 2690
};

Kevin Modzelewski's avatar
Kevin Modzelewski committed
2691 2692 2693
AttrWrapperIter::AttrWrapperIter(AttrWrapper* aw) {
    hcls = aw->b->getHCAttrsPtr()->hcls;
    assert(hcls);
2694
    RELEASE_ASSERT(hcls->type == HiddenClass::NORMAL || hcls->type == HiddenClass::SINGLETON, "");
2695
    it = hcls->getStrAttrOffsets().begin();
Kevin Modzelewski's avatar
Kevin Modzelewski committed
2696 2697 2698 2699 2700
}

Box* AttrWrapperIter::hasnext(Box* _self) {
    RELEASE_ASSERT(_self->cls == attrwrapperiter_cls, "");
    AttrWrapperIter* self = static_cast<AttrWrapperIter*>(_self);
2701
    RELEASE_ASSERT(self->hcls->type == HiddenClass::NORMAL || self->hcls->type == HiddenClass::SINGLETON, "");
Kevin Modzelewski's avatar
Kevin Modzelewski committed
2702

2703
    return boxBool(self->it != self->hcls->getStrAttrOffsets().end());
Kevin Modzelewski's avatar
Kevin Modzelewski committed
2704 2705 2706 2707 2708
}

Box* AttrWrapperIter::next(Box* _self) {
    RELEASE_ASSERT(_self->cls == attrwrapperiter_cls, "");
    AttrWrapperIter* self = static_cast<AttrWrapperIter*>(_self);
2709
    RELEASE_ASSERT(self->hcls->type == HiddenClass::NORMAL || self->hcls->type == HiddenClass::SINGLETON, "");
Kevin Modzelewski's avatar
Kevin Modzelewski committed
2710

2711
    assert(self->it != self->hcls->getStrAttrOffsets().end());
2712
    Box* r = self->it->first;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
2713 2714 2715 2716
    ++self->it;
    return r;
}

2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728
Box* AttrWrapperIter::next_capi(Box* _self) noexcept {
    RELEASE_ASSERT(_self->cls == attrwrapperiter_cls, "");
    AttrWrapperIter* self = static_cast<AttrWrapperIter*>(_self);
    RELEASE_ASSERT(self->hcls->type == HiddenClass::NORMAL || self->hcls->type == HiddenClass::SINGLETON, "");

    if (self->it == self->hcls->getStrAttrOffsets().end())
        return NULL;
    Box* r = self->it->first;
    ++self->it;
    return r;
}

2729 2730 2731 2732 2733 2734 2735
Box* Box::getAttrWrapper() {
    assert(cls->instancesHaveHCAttrs());
    HCAttrs* attrs = getHCAttrsPtr();
    HiddenClass* hcls = attrs->hcls;

    if (hcls->type == HiddenClass::DICT_BACKED) {
        return attrs->attr_list->attrs[0];
2736 2737
    }

2738 2739 2740
    int offset = hcls->getAttrwrapperOffset();
    if (offset == -1) {
        Box* aw = new AttrWrapper(this);
2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751
        if (hcls->type == HiddenClass::NORMAL) {
            auto new_hcls = hcls->getAttrwrapperChild();
            appendNewHCAttr(aw, NULL);
            attrs->hcls = new_hcls;
            return aw;
        } else {
            assert(hcls->type == HiddenClass::SINGLETON);
            appendNewHCAttr(aw, NULL);
            hcls->appendAttrwrapper();
            return aw;
        }
2752 2753
    }
    return attrs->attr_list->attrs[offset];
2754 2755
}

2756 2757 2758 2759
extern "C" PyObject* PyObject_GetAttrWrapper(PyObject* obj) noexcept {
    return obj->getAttrWrapper();
}

2760 2761 2762 2763 2764
Box* unwrapAttrWrapper(Box* b) {
    assert(b->cls == attrwrapper_cls);
    return static_cast<AttrWrapper*>(b)->getUnderlying();
}

2765 2766 2767 2768
Box* attrwrapperKeys(Box* b) {
    return AttrWrapper::keys(b);
}

2769
void attrwrapperDel(Box* b, llvm::StringRef attr) {
2770
    AttrWrapper::delitem(b, boxString(attr));
2771 2772
}

2773 2774 2775 2776 2777 2778 2779
BoxedDict* attrwrapperToDict(Box* b) {
    assert(b->cls == attrwrapper_cls);
    Box* d = AttrWrapper::copy(static_cast<AttrWrapper*>(b));
    assert(d->cls == dict_cls);
    return static_cast<BoxedDict*>(d);
}

2780 2781 2782
static int excess_args(PyObject* args, PyObject* kwds) noexcept {
    return PyTuple_GET_SIZE(args) || (kwds && PyDict_Check(kwds) && PyDict_Size(kwds));
}
2783

2784
static PyObject* object_new(PyTypeObject* type, PyObject* args, PyObject* kwds) noexcept;
2785

2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797
static int object_init(PyObject* self, PyObject* args, PyObject* kwds) noexcept {
    int err = 0;
    if (excess_args(args, kwds)) {
        PyTypeObject* type = Py_TYPE(self);
        if (type->tp_init != object_init && type->tp_new != object_new) {
            err = PyErr_WarnEx(PyExc_DeprecationWarning, "object.__init__() takes no parameters", 1);
        } else if (type->tp_init != object_init || type->tp_new == object_new) {
            PyErr_SetString(PyExc_TypeError, "object.__init__() takes no parameters");
            err = -1;
        }
    }
    return err;
2798 2799
}

2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818
static PyObject* object_new(PyTypeObject* type, PyObject* args, PyObject* kwds) noexcept {
    int err = 0;
    if (excess_args(args, kwds)) {
        if (type->tp_new != object_new && type->tp_init != object_init) {
            err = PyErr_WarnEx(PyExc_DeprecationWarning, "object() takes no parameters", 1);
        } else if (type->tp_new != object_new || type->tp_init == object_init) {
            PyErr_SetString(PyExc_TypeError, "object() takes no parameters");
            err = -1;
        }
    }
    if (err < 0)
        return NULL;

    if (type->tp_flags & Py_TPFLAGS_IS_ABSTRACT) {
        // I don't know what this is or when it happens, but
        // CPython does something special with it
        Py_FatalError("unimplemented");
    }
    return type->tp_alloc(type, 0);
2819 2820
}

2821 2822 2823 2824 2825 2826 2827 2828 2829
static Box* typeName(Box* b, void*);
Box* objectRepr(Box* self) {
    BoxedClass* type = self->cls;
    Box* mod = NULL;
    try {
        mod = typeModule(type, NULL);
        if (!PyString_Check(mod))
            mod = NULL;
    } catch (ExcInfo) {
2830
    }
2831 2832 2833 2834 2835

    Box* name = typeName(type, NULL);
    if (mod != NULL && strcmp(PyString_AS_STRING(mod), "__builtin__"))
        return PyString_FromFormat("<%s.%s object at %p>", PyString_AS_STRING(mod), PyString_AS_STRING(name), self);
    return PyString_FromFormat("<%s object at %p>", type->tp_name, self);
2836 2837
}

2838 2839 2840 2841 2842 2843 2844
static Box* object_str(Box* obj) noexcept {
    try {
        return obj->reprIC();
    } catch (ExcInfo e) {
        setCAPIException(e);
        return NULL;
    }
2845 2846
}

2847 2848 2849 2850
Box* objectHash(Box* obj) {
    return boxInt(_Py_HashPointer(obj));
}

2851
Box* objectSetattr(Box* obj, Box* attr, Box* value) {
2852
    attr = coerceUnicodeToStr<CXX>(attr);
2853 2854 2855 2856 2857
    if (attr->cls != str_cls) {
        raiseExcHelper(TypeError, "attribute name must be string, not '%s'", attr->cls->tp_name);
    }

    BoxedString* attr_str = static_cast<BoxedString*>(attr);
2858
    setattrGeneric<NOT_REWRITABLE>(obj, attr_str, value, NULL);
2859 2860 2861
    return None;
}

2862 2863 2864 2865
Box* objectSubclasshook(Box* cls, Box* a) {
    return NotImplemented;
}

2866 2867 2868 2869
static PyObject* import_copyreg(void) noexcept {
    static PyObject* copyreg_str;

    if (!copyreg_str) {
2870 2871
        // this is interned in cpython:
        copyreg_str = PyGC_AddRoot(PyString_FromString("copy_reg"));
2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952
        if (copyreg_str == NULL)
            return NULL;
    }

    return PyImport_Import(copyreg_str);
}

static PyObject* slotnames(PyObject* cls) noexcept {
    PyObject* clsdict;
    PyObject* copyreg;
    PyObject* slotnames;

    if (!PyType_Check(cls)) {
        Py_INCREF(Py_None);
        return Py_None;
    }

    clsdict = ((PyTypeObject*)cls)->tp_dict;
    slotnames = PyDict_GetItemString(clsdict, "__slotnames__");
    if (slotnames != NULL && PyList_Check(slotnames)) {
        Py_INCREF(slotnames);
        return slotnames;
    }

    copyreg = import_copyreg();
    if (copyreg == NULL)
        return NULL;

    slotnames = PyObject_CallMethod(copyreg, "_slotnames", "O", cls);
    Py_DECREF(copyreg);
    if (slotnames != NULL && slotnames != Py_None && !PyList_Check(slotnames)) {
        PyErr_SetString(PyExc_TypeError, "copy_reg._slotnames didn't return a list or None");
        Py_DECREF(slotnames);
        slotnames = NULL;
    }

    return slotnames;
}

static PyObject* reduce_2(PyObject* obj) noexcept {
    PyObject* cls, *getnewargs;
    PyObject* args = NULL, * args2 = NULL;
    PyObject* getstate = NULL, * state = NULL, * names = NULL;
    PyObject* slots = NULL, * listitems = NULL, * dictitems = NULL;
    PyObject* copyreg = NULL, * newobj = NULL, * res = NULL;
    Py_ssize_t i, n;

    cls = PyObject_GetAttrString(obj, "__class__");
    if (cls == NULL)
        return NULL;

    getnewargs = PyObject_GetAttrString(obj, "__getnewargs__");
    if (getnewargs != NULL) {
        args = PyObject_CallObject(getnewargs, NULL);
        Py_DECREF(getnewargs);
        if (args != NULL && !PyTuple_Check(args)) {
            PyErr_Format(PyExc_TypeError, "__getnewargs__ should return a tuple, "
                                          "not '%.200s'",
                         Py_TYPE(args)->tp_name);
            goto end;
        }
    } else {
        PyErr_Clear();
        args = PyTuple_New(0);
    }
    if (args == NULL)
        goto end;

    getstate = PyObject_GetAttrString(obj, "__getstate__");
    if (getstate != NULL) {
        state = PyObject_CallObject(getstate, NULL);
        Py_DECREF(getstate);
        if (state == NULL)
            goto end;
    } else {
        PyErr_Clear();
        state = PyObject_GetAttrString(obj, "__dict__");
        if (state == NULL) {
            PyErr_Clear();
            state = Py_None;
            Py_INCREF(state);
2953 2954 2955 2956 2957 2958 2959
        } else {
            // Pyston change: convert attrwrapper to a real dict
            if (state->cls == attrwrapper_cls) {
                PyObject* real_dict = PyDict_New();
                PyDict_Update(real_dict, state);
                state = real_dict;
            }
2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096
        }
        names = slotnames(cls);
        if (names == NULL)
            goto end;
        if (names != Py_None) {
            assert(PyList_Check(names));
            slots = PyDict_New();
            if (slots == NULL)
                goto end;
            n = 0;
            /* Can't pre-compute the list size; the list
               is stored on the class so accessible to other
               threads, which may be run by DECREF */
            for (i = 0; i < PyList_GET_SIZE(names); i++) {
                PyObject* name, *value;
                name = PyList_GET_ITEM(names, i);
                value = PyObject_GetAttr(obj, name);
                if (value == NULL)
                    PyErr_Clear();
                else {
                    int err = PyDict_SetItem(slots, name, value);
                    Py_DECREF(value);
                    if (err)
                        goto end;
                    n++;
                }
            }
            if (n) {
                state = Py_BuildValue("(NO)", state, slots);
                if (state == NULL)
                    goto end;
            }
        }
    }

    if (!PyList_Check(obj)) {
        listitems = Py_None;
        Py_INCREF(listitems);
    } else {
        listitems = PyObject_GetIter(obj);
        if (listitems == NULL)
            goto end;
    }

    if (!PyDict_Check(obj)) {
        dictitems = Py_None;
        Py_INCREF(dictitems);
    } else {
        dictitems = PyObject_CallMethod(obj, "iteritems", "");
        if (dictitems == NULL)
            goto end;
    }

    copyreg = import_copyreg();
    if (copyreg == NULL)
        goto end;
    newobj = PyObject_GetAttrString(copyreg, "__newobj__");
    if (newobj == NULL)
        goto end;

    n = PyTuple_GET_SIZE(args);
    args2 = PyTuple_New(n + 1);
    if (args2 == NULL)
        goto end;
    PyTuple_SET_ITEM(args2, 0, cls);
    cls = NULL;
    for (i = 0; i < n; i++) {
        PyObject* v = PyTuple_GET_ITEM(args, i);
        Py_INCREF(v);
        PyTuple_SET_ITEM(args2, i + 1, v);
    }

    res = PyTuple_Pack(5, newobj, args2, state, listitems, dictitems);

end:
    Py_XDECREF(cls);
    Py_XDECREF(args);
    Py_XDECREF(args2);
    Py_XDECREF(slots);
    Py_XDECREF(state);
    Py_XDECREF(names);
    Py_XDECREF(listitems);
    Py_XDECREF(dictitems);
    Py_XDECREF(copyreg);
    Py_XDECREF(newobj);
    return res;
}

static PyObject* _common_reduce(PyObject* self, int proto) noexcept {
    PyObject* copyreg, *res;

    if (proto >= 2)
        return reduce_2(self);

    copyreg = import_copyreg();
    if (!copyreg)
        return NULL;

    res = PyEval_CallMethod(copyreg, "_reduce_ex", "(Oi)", self, proto);
    Py_DECREF(copyreg);

    return res;
}

static PyObject* object_reduce(PyObject* self, PyObject* args) noexcept {
    int proto = 0;

    if (!PyArg_ParseTuple(args, "|i:__reduce__", &proto))
        return NULL;

    return _common_reduce(self, proto);
}

static PyObject* object_reduce_ex(PyObject* self, PyObject* args) noexcept {
    PyObject* reduce, *res;
    int proto = 0;

    if (!PyArg_ParseTuple(args, "|i:__reduce_ex__", &proto))
        return NULL;

    reduce = PyObject_GetAttrString(self, "__reduce__");
    if (reduce == NULL)
        PyErr_Clear();
    else {
        PyObject* cls, *clsreduce, *objreduce;
        int override;
        cls = PyObject_GetAttrString(self, "__class__");
        if (cls == NULL) {
            Py_DECREF(reduce);
            return NULL;
        }
        clsreduce = PyObject_GetAttrString(cls, "__reduce__");
        Py_DECREF(cls);
        if (clsreduce == NULL) {
            Py_DECREF(reduce);
            return NULL;
        }
3097
        objreduce = PyDict_GetItemString(PyBaseObject_Type.tp_dict, "__reduce__");
3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110
        override = (clsreduce != objreduce);
        Py_DECREF(clsreduce);
        if (override) {
            res = PyObject_CallObject(reduce, NULL);
            Py_DECREF(reduce);
            return res;
        } else
            Py_DECREF(reduce);
    }

    return _common_reduce(self, proto);
}

3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167
/*
   from PEP 3101, this code implements:

   class object:
       def __format__(self, format_spec):
       if isinstance(format_spec, str):
           return format(str(self), format_spec)
       elif isinstance(format_spec, unicode):
           return format(unicode(self), format_spec)
*/
static PyObject* object_format(PyObject* self, PyObject* args) noexcept {
    PyObject* format_spec;
    PyObject* self_as_str = NULL;
    PyObject* result = NULL;
    Py_ssize_t format_len;

    if (!PyArg_ParseTuple(args, "O:__format__", &format_spec))
        return NULL;
#ifdef Py_USING_UNICODE
    if (PyUnicode_Check(format_spec)) {
        format_len = PyUnicode_GET_SIZE(format_spec);
        self_as_str = PyObject_Unicode(self);
    } else if (PyString_Check(format_spec)) {
#else
    if (PyString_Check(format_spec)) {
#endif
        format_len = PyString_GET_SIZE(format_spec);
        self_as_str = PyObject_Str(self);
    } else {
        PyErr_SetString(PyExc_TypeError, "argument to __format__ must be unicode or str");
        return NULL;
    }

    if (self_as_str != NULL) {
        /* Issue 7994: If we're converting to a string, we
           should reject format specifications */
        if (format_len > 0) {
            if (PyErr_WarnEx(PyExc_PendingDeprecationWarning, "object.__format__ with a non-empty format "
                                                              "string is deprecated",
                             1) < 0) {
                goto done;
            }
            /* Eventually this will become an error:
            PyErr_Format(PyExc_TypeError,
               "non-empty format string passed to object.__format__");
            goto done;
            */
        }
        result = PyObject_Format(self_as_str, format_spec);
    }

done:
    Py_XDECREF(self_as_str);

    return result;
}

3168 3169 3170 3171 3172 3173
static Box* objectClass(Box* obj, void* context) {
    assert(obj->cls != instance_cls); // should override __class__ in classobj
    return obj->cls;
}

static void objectSetClass(Box* obj, Box* val, void* context) {
3174
    if (!PyType_Check(val))
3175 3176 3177 3178 3179 3180 3181 3182
        raiseExcHelper(TypeError, "__class__ must be set to new-style class, not '%s' object", val->cls->tp_name);

    auto new_cls = static_cast<BoxedClass*>(val);

    // Conservative Pyston checks: make sure that both classes are derived only from Pyston types,
    // and that they don't define any extra C-level fields
    RELEASE_ASSERT(val->cls == type_cls, "");
    RELEASE_ASSERT(obj->cls->cls == type_cls, "");
3183 3184
    for (auto b : *static_cast<BoxedTuple*>(obj->cls->tp_mro)) {
        BoxedClass* base = static_cast<BoxedClass*>(b);
3185 3186
        RELEASE_ASSERT(base->is_pyston_class, "");
    }
3187 3188
    for (auto b : *static_cast<BoxedTuple*>(new_cls->tp_mro)) {
        BoxedClass* base = static_cast<BoxedClass*>(b);
3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208
        RELEASE_ASSERT(base->is_pyston_class, "");
    }

    RELEASE_ASSERT(obj->cls->tp_basicsize == object_cls->tp_basicsize + sizeof(HCAttrs) + sizeof(Box**), "");
    RELEASE_ASSERT(new_cls->tp_basicsize == object_cls->tp_basicsize + sizeof(HCAttrs) + sizeof(Box**), "");
    RELEASE_ASSERT(obj->cls->attrs_offset != 0, "");
    RELEASE_ASSERT(new_cls->attrs_offset != 0, "");
    RELEASE_ASSERT(obj->cls->tp_weaklistoffset != 0, "");
    RELEASE_ASSERT(new_cls->tp_weaklistoffset != 0, "");

    // Normal Python checks.
    // TODO there are more checks to add here, and they should throw errors not asserts
    RELEASE_ASSERT(obj->cls->tp_basicsize == new_cls->tp_basicsize, "");
    RELEASE_ASSERT(obj->cls->tp_dictoffset == new_cls->tp_dictoffset, "");
    RELEASE_ASSERT(obj->cls->tp_weaklistoffset == new_cls->tp_weaklistoffset, "");
    RELEASE_ASSERT(obj->cls->attrs_offset == new_cls->attrs_offset, "");

    obj->cls = new_cls;
}

3209 3210 3211
static PyMethodDef object_methods[] = {
    { "__reduce_ex__", object_reduce_ex, METH_VARARGS, NULL }, //
    { "__reduce__", object_reduce, METH_VARARGS, NULL },       //
3212
    { "__format__", object_format, METH_VARARGS, PyDoc_STR("default object formatter") },
3213 3214
};

3215
static Box* typeName(Box* b, void*) {
3216
    RELEASE_ASSERT(PyType_Check(b), "");
3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231
    BoxedClass* type = static_cast<BoxedClass*>(b);

    if (type->tp_flags & Py_TPFLAGS_HEAPTYPE) {
        BoxedHeapClass* et = static_cast<BoxedHeapClass*>(type);
        return et->ht_name;
    } else {
        const char* s = strrchr(type->tp_name, '.');
        if (s == NULL)
            s = type->tp_name;
        else
            s++;
        return PyString_FromString(s);
    }
}

3232
static void typeSetName(Box* b, Box* v, void*) {
3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252
    assert(b->cls == type_cls);
    BoxedClass* type = static_cast<BoxedClass*>(b);

    // Awkward... in CPython you can only set __name__ for heaptype classes
    // (those with ht_name) but in Pyston right now we have some heaptype classes that
    // aren't heaptype in CPython, and we have to restrict those too.

    // TODO is this predicate right?
    bool is_heaptype = (type->tp_flags & Py_TPFLAGS_HEAPTYPE);
    if (!(is_heaptype && type->is_user_defined)) {
        raiseExcHelper(TypeError, "can't set %s.__name__", type->tp_name);
    }
    if (!v) {
        raiseExcHelper(TypeError, "can't delete %s.__name__", type->tp_name);
    }
    if (!PyString_Check(v)) {
        raiseExcHelper(TypeError, "can only assign string to %s.__name__, not '%s'", type->tp_name, getTypeName(v));
    }

    BoxedString* s = static_cast<BoxedString*>(v);
3253
    if (strlen(s->data()) != s->size()) {
3254 3255 3256 3257 3258
        raiseExcHelper(ValueError, "__name__ must not contain null bytes");
    }

    BoxedHeapClass* ht = static_cast<BoxedHeapClass*>(type);
    ht->ht_name = s;
3259
    ht->tp_name = s->data();
3260 3261
}

3262
static Box* typeBases(Box* b, void*) {
3263
    RELEASE_ASSERT(PyType_Check(b), "");
3264 3265 3266 3267 3268 3269
    BoxedClass* type = static_cast<BoxedClass*>(b);

    assert(type->tp_bases);
    return type->tp_bases;
}

3270
static void typeSetBases(Box* b, Box* v, void* c) {
3271
    RELEASE_ASSERT(PyType_Check(b), "");
3272 3273 3274
    BoxedClass* type = static_cast<BoxedClass*>(b);
    if (type_set_bases(type, v, c) == -1)
        throwCAPIException();
3275 3276
}

3277 3278 3279 3280
// cls should be obj->cls.
// Added as parameter because it should typically be available
inline void initUserAttrs(Box* obj, BoxedClass* cls) {
    assert(obj->cls == cls);
3281 3282
    if (cls->instancesHaveHCAttrs()) {
        HCAttrs* attrs = obj->getHCAttrsPtr();
3283 3284 3285 3286
        attrs = new ((void*)attrs) HCAttrs();
    }
}

3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306
extern "C" void PyObject_InitHcAttrs(HCAttrs* attrs) noexcept {
    new ((void*)attrs) HCAttrs();
}

extern "C" PyObject* PyObject_GetHcAttrString(PyObject* obj, const char* attr) PYSTON_NOEXCEPT {
    return obj->getattr(internStringMortal(attr));
}
extern "C" int PyObject_SetHcAttrString(PyObject* obj, const char* attr, PyObject* val) PYSTON_NOEXCEPT {
    obj->setattr(internStringMortal(attr), val, NULL);
    return 0;
}
extern "C" int PyObject_DelHcAttrString(PyObject* obj, const char* attr) PYSTON_NOEXCEPT {
    BoxedString* attr_str = internStringMortal(attr);
    bool has = obj->hasattr(attr_str);
    if (!has)
        return -1;
    obj->delattr(attr_str, NULL);
    return 0;
}

3307
extern "C" PyVarObject* PyObject_InitVar(PyVarObject* op, PyTypeObject* tp, Py_ssize_t size) noexcept {
3308 3309
    assert(op);
    assert(tp);
3310

3311 3312
    assert(gc::isValidGCMemory(op));
    assert(gc::isValidGCObject(tp));
3313 3314 3315

    Py_TYPE(op) = tp;
    op->ob_size = size;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
3316
    _Py_NewReference(op);
3317

3318 3319
    gc::registerPythonObject(op);

3320 3321 3322
    return op;
}

3323
extern "C" PyObject* PyObject_Init(PyObject* op, PyTypeObject* tp) noexcept {
3324 3325 3326
    if (op == NULL)
        return PyErr_NoMemory();

3327 3328
    assert(tp);

3329
    assert(gc::isValidGCMemory(op));
3330 3331 3332
    assert(gc::isValidGCObject(tp));

    Py_TYPE(op) = tp;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
3333
    _Py_NewReference(op);
3334

3335 3336
    gc::registerPythonObject(op);

3337 3338 3339 3340
    if (PyType_SUPPORTS_WEAKREFS(tp)) {
        *PyObject_GET_WEAKREFS_LISTPTR(op) = NULL;
    }

3341 3342 3343 3344 3345 3346 3347 3348
    // I think CPython defers the dict creation (equivalent of our initUserAttrs) to the
    // first time that an attribute gets set.
    // Our HCAttrs object already includes this optimization of no-allocation-if-empty,
    // but it's nice to initialize the hcls here so we don't have to check it on every getattr/setattr.
    // TODO It does mean that anything not defering to this function will have to call
    // initUserAttrs themselves, though.
    initUserAttrs(op, tp);

3349
#ifndef NDEBUG
Travis Hance's avatar
slots  
Travis Hance committed
3350 3351
    if (tp->tp_flags & Py_TPFLAGS_HEAPTYPE) {
        BoxedHeapClass* heap_cls = static_cast<BoxedHeapClass*>(tp);
3352
        if (heap_cls->nslots() > 0) {
Travis Hance's avatar
slots  
Travis Hance committed
3353
            BoxedHeapClass::SlotOffset* slotOffsets = heap_cls->slotOffsets();
3354 3355 3356 3357
            for (int i = 0; i < heap_cls->nslots(); i++) {
                // This should be set to 0 on allocation:
                // (If it wasn't, we would need to initialize it to 0 here.)
                assert(*(Box**)((char*)op + slotOffsets[i]) == NULL);
Travis Hance's avatar
slots  
Travis Hance committed
3358 3359 3360
            }
        }
    }
3361
#endif
Travis Hance's avatar
slots  
Travis Hance committed
3362

3363 3364 3365
    return op;
}

3366 3367 3368 3369
Box* decodeUTF8StringPtr(llvm::StringRef s) {
    Box* rtn = PyUnicode_DecodeUTF8(s.data(), s.size(), "strict");
    if (!rtn)
        throwCAPIException();
3370 3371 3372 3373
    assert(rtn);
    return rtn;
}

3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430
static PyObject* type_richcompare(PyObject* v, PyObject* w, int op) noexcept {
    PyObject* result;
    Py_uintptr_t vv, ww;
    int c;

    /* Make sure both arguments are types. */
    if (!PyType_Check(v) || !PyType_Check(w) ||
        /* If there is a __cmp__ method defined, let it be called instead
           of our dumb function designed merely to warn.  See bug
           #7491. */
        Py_TYPE(v)->tp_compare || Py_TYPE(w)->tp_compare) {
        result = Py_NotImplemented;
        goto out;
    }

    /* Py3K warning if comparison isn't == or !=  */
    if (Py_Py3kWarningFlag && op != Py_EQ && op != Py_NE
        && PyErr_WarnEx(PyExc_DeprecationWarning, "type inequality comparisons not supported "
                                                  "in 3.x",
                        1) < 0) {
        return NULL;
    }

    /* Compare addresses */
    vv = (Py_uintptr_t)v;
    ww = (Py_uintptr_t)w;
    switch (op) {
        case Py_LT:
            c = vv < ww;
            break;
        case Py_LE:
            c = vv <= ww;
            break;
        case Py_EQ:
            c = vv == ww;
            break;
        case Py_NE:
            c = vv != ww;
            break;
        case Py_GT:
            c = vv > ww;
            break;
        case Py_GE:
            c = vv >= ww;
            break;
        default:
            result = Py_NotImplemented;
            goto out;
    }
    result = c ? Py_True : Py_False;

/* incref and return */
out:
    Py_INCREF(result);
    return result;
}

3431
void unicode_visit(GCVisitor* v, Box* b) {
3432
    Box::gcHandler(v, b);
3433 3434

    PyUnicodeObject* u = (PyUnicodeObject*)b;
3435 3436
    v->visit(&u->str);
    v->visit(&u->defenc);
3437 3438
}

3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453
extern "C" PyUnicodeObject* unicode_empty;
extern "C" PyUnicodeObject* _PyUnicode_New(Py_ssize_t length) noexcept {
    PyUnicodeObject* unicode;

    /* Optimization for empty strings */
    if (length == 0 && unicode_empty != NULL) {
        Py_INCREF(unicode_empty);
        return unicode_empty;
    }

    /* Ensure we won't overflow the size. */
    if (length > ((PY_SSIZE_T_MAX / sizeof(Py_UNICODE)) - 1)) {
        return (PyUnicodeObject*)PyErr_NoMemory();
    }

Kevin Modzelewski's avatar
Kevin Modzelewski committed
3454 3455 3456 3457 3458 3459 3460
    // Pyston change: allocate ->str first, so that if this allocation
    // causes a collection, we don't see a half-created unicode object:
    size_t new_size = sizeof(Py_UNICODE) * ((size_t)length + 1);
    Py_UNICODE* str = (Py_UNICODE*)gc_alloc(new_size, gc::GCKind::UNTRACKED);
    if (!str)
        return (PyUnicodeObject*)PyErr_NoMemory();

3461 3462 3463 3464 3465 3466 3467
#if STAT_ALLOCATIONS
    {
        size_t size = sizeof(PyUnicodeObject);
        ALLOC_STATS(unicode_cls);
    }
#endif

3468 3469 3470
    // Do a bunch of inlining + constant folding of this line of CPython's:
    // unicode = PyObject_New(PyUnicodeObject, &PyUnicode_Type);
    assert(PyUnicode_Type.tp_basicsize == sizeof(PyUnicodeObject)); // use the compile-time constant
3471
    unicode = (PyUnicodeObject*)gc_alloc(sizeof(PyUnicodeObject), gc::GCKind::PYTHON);
3472 3473 3474 3475 3476 3477 3478 3479 3480
    if (unicode == NULL)
        return (PyUnicodeObject*)PyErr_NoMemory();

    // Inline PyObject_INIT:
    assert(!PyType_SUPPORTS_WEAKREFS(&PyUnicode_Type));
    assert(!PyUnicode_Type.instancesHaveHCAttrs());
    assert(!PyUnicode_Type.instancesHaveDictAttrs());
    unicode->ob_type = (struct _typeobject*)&PyUnicode_Type;

Kevin Modzelewski's avatar
Kevin Modzelewski committed
3481
    unicode->str = str;
3482

3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497
    /* Initialize the first element to guard against cases where
     * the caller fails before initializing str -- unicode_resize()
     * reads str[0], and the Keep-Alive optimization can keep memory
     * allocated for str alive across a call to unicode_dealloc(unicode).
     * We don't want unicode_resize to read uninitialized memory in
     * that case.
     */
    unicode->str[0] = 0;
    unicode->str[length] = 0;
    unicode->length = length;
    unicode->hash = -1;
    unicode->defenc = NULL;
    return unicode;
}

3498 3499 3500 3501 3502 3503 3504 3505 3506 3507
// We don't need CPython's version of tp_free since we have GC.
// We still need to set tp_free to something and not a NULL pointer,
// because C extensions might still call tp_free from tp_dealloc.
void default_free(void*) {
}

void dealloc_null(Box* box) {
    assert(box->cls->tp_del == NULL);
}

3508
// Normally we don't call the Python tp_ slots that are present to support
3509
// CPython's reference-counted garbage collection.
3510 3511
static void setTypeGCProxy(BoxedClass* cls) {
    cls->tp_alloc = PystonType_GenericAlloc;
3512
    cls->tp_free = default_free;
3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541
    cls->gc_visit = proxy_to_tp_traverse;
    cls->has_safe_tp_dealloc = true;
    cls->is_pyston_class = true;
}

// By calling this function on a class we assign it Pyston's GC handling
// and no finalizers.
static void setTypeGCNone(BoxedClass* cls) {
    cls->tp_alloc = PystonType_GenericAlloc;
    cls->tp_free = default_free;
    cls->tp_dealloc = dealloc_null;
    cls->has_safe_tp_dealloc = true;
    cls->is_pyston_class = true;
}

static void setupDefaultClassGCParticipation() {
    // some additional setup to ensure weakrefs participate in our GC
    setTypeGCProxy(&_PyWeakref_RefType);
    setTypeGCProxy(&_PyWeakref_ProxyType);
    setTypeGCProxy(&_PyWeakref_CallableProxyType);

    // This is an optimization to speed up the handling of unicode objects,
    // exception objects, regular expression objects, etc in garbage collection.
    // There's no reason to have them part of finalizer ordering.
    //
    // This is important in tests like django-template which allocates
    // hundreds of thousands of unicode strings.
    setTypeGCNone(unicode_cls);
    unicode_cls->gc_visit = unicode_visit;
3542 3543
    unicode_cls->is_constant = true;
    unicode_cls->is_user_defined = false;
3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556

    for (BoxedClass* cls : exception_types) {
        setTypeGCNone(cls);
    }

    for (int i = 0; Itertool_SafeDealloc_Types[i] != NULL; i++) {
        setTypeGCNone(Itertool_SafeDealloc_Types[i]);
    }

    setTypeGCNone(&Scanner_Type);
    setTypeGCNone(&Match_Type);
    setTypeGCNone(&Pattern_Type);
    setTypeGCNone(&PyCallIter_Type);
3557 3558 3559 3560 3561 3562

    // We just changed the has_safe_tp_dealloc field on a few classes, changing
    // them from having an ordered finalizer to an unordered one.
    // If some instances of those classes have already been allocated (e.g.
    // preallocated exceptions), they need to be invalidated.
    gc::invalidateOrderedFinalizerList();
3563 3564
}

Kevin Modzelewski's avatar
Kevin Modzelewski committed
3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596
static Box* getsetGet(Box* self, Box* obj, Box* type) {
    // TODO: should call the full descr_check instead
    if (obj == NULL || obj == None)
        return self;

    BoxedGetsetDescriptor* getset_descr = static_cast<BoxedGetsetDescriptor*>(self);
    if (isSubclass(self->cls, pyston_getset_cls)) {
        return getset_descr->get(obj, getset_descr->closure);
    } else {
        RELEASE_ASSERT(isSubclass(self->cls, capi_getset_cls), "");
        Box* r = getset_descr->get(obj, getset_descr->closure);
        if (!r)
            throwCAPIException();
        return r;
    }
}

static Box* getsetSet(Box* self, Box* obj, Box* val) {
    assert(obj != NULL && obj != None);

    BoxedGetsetDescriptor* getset_descr = static_cast<BoxedGetsetDescriptor*>(self);
    if (isSubclass(self->cls, pyston_getset_cls)) {
        getset_descr->set(obj, val, getset_descr->closure);
        return None;
    } else {
        RELEASE_ASSERT(isSubclass(self->cls, capi_getset_cls), "");
        getset_descr->set(obj, val, getset_descr->closure);
        checkAndThrowCAPIException();
        return None;
    }
}

3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611
static Box* getsetDelete(Box* self, Box* obj) {
    assert(obj != NULL && obj != None);

    BoxedGetsetDescriptor* getset_descr = static_cast<BoxedGetsetDescriptor*>(self);
    if (isSubclass(self->cls, pyston_getset_cls)) {
        getset_descr->set(obj, NULL, getset_descr->closure);
        return None;
    } else {
        RELEASE_ASSERT(isSubclass(self->cls, capi_getset_cls), "");
        getset_descr->set(obj, NULL, getset_descr->closure);
        checkAndThrowCAPIException();
        return None;
    }
}

Kevin Modzelewski's avatar
Kevin Modzelewski committed
3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644
void Box::clearAttrs() {
    if (cls->instancesHaveHCAttrs()) {
        HCAttrs* attrs = getHCAttrsPtr();
        HiddenClass* hcls = attrs->hcls;

        if (unlikely(hcls->type == HiddenClass::DICT_BACKED)) {
            Box* d = attrs->attr_list->attrs[0];
            PyDict_Clear(d);
            return;
        }

        assert(hcls->type == HiddenClass::NORMAL || hcls->type == HiddenClass::SINGLETON);

        for (int i = 0; i < hcls->attributeArraySize(); i++) {
            Py_DECREF(attrs->attr_list->attrs[i]);
        }
        new ((void*)attrs) HCAttrs(root_hcls);
        return;
    }

    if (cls->instancesHaveDictAttrs()) {
        BoxedDict* d = getDict();
        PyDict_Clear(d);
        return;
    }
}

#ifndef Py_REF_DEBUG
#define PRINT_TOTAL_REFS()
#else /* Py_REF_DEBUG */
#define PRINT_TOTAL_REFS() fprintf(stderr, "[%" PY_FORMAT_SIZE_T "d refs]\n", _Py_GetRefTotal())
#endif

Kevin Modzelewski's avatar
Kevin Modzelewski committed
3645 3646
bool TRACK_ALLOCATIONS = false;
void setupRuntime() {
3647

3648
    root_hcls = HiddenClass::makeRoot();
3649
    gc::registerPermanentRoot(root_hcls);
3650 3651
    HiddenClass::dict_backed = HiddenClass::makeDictBacked();
    gc::registerPermanentRoot(HiddenClass::dict_backed);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
3652

3653 3654 3655
    // Disable the GC while we do some manual initialization of the object hierarchy:
    gc::disableGC();

3656 3657 3658
    // We have to do a little dance to get object_cls and type_cls set up, since the normal
    // object-creation routines look at the class to see the allocation size.
    void* mem = gc_alloc(sizeof(BoxedClass), gc::GCKind::PYTHON);
3659 3660 3661 3662
    object_cls = ::new (mem) BoxedClass(NULL, &Box::gcHandler, 0, 0, sizeof(Box), false, "object");
    mem = gc_alloc(sizeof(BoxedClass), gc::GCKind::PYTHON);
    type_cls = ::new (mem) BoxedClass(object_cls, &BoxedClass::gcHandler, offsetof(BoxedClass, attrs),
                                      offsetof(BoxedClass, tp_weaklist), sizeof(BoxedHeapClass), false, "type");
3663
    type_cls->has_safe_tp_dealloc = false;
3664
    type_cls->tp_flags |= Py_TPFLAGS_TYPE_SUBCLASS;
Travis Hance's avatar
slots  
Travis Hance committed
3665
    type_cls->tp_itemsize = sizeof(BoxedHeapClass::SlotOffset);
3666 3667
    PyObject_Init(object_cls, type_cls);
    PyObject_Init(type_cls, type_cls);
3668 3669 3670
    // XXX silly that we have to set this again
    new (&object_cls->attrs) HCAttrs(HiddenClass::makeSingleton());
    new (&type_cls->attrs) HCAttrs(HiddenClass::makeSingleton());
3671
    object_cls->instances_are_nonzero = true;
3672 3673 3674 3675
    object_cls->tp_getattro = PyObject_GenericGetAttr;
    object_cls->tp_setattro = PyObject_GenericSetAttr;
    object_cls->tp_init = object_init;
    object_cls->tp_new = object_new;
3676
    type_cls->tp_getattro = type_getattro;
3677

3678
    none_cls = new (0) BoxedClass(object_cls, NULL, 0, 0, sizeof(Box), false, "NoneType");
3679
    None = new (none_cls) Box();
Kevin Modzelewski's avatar
Kevin Modzelewski committed
3680
    assert(None->cls);
3681
    gc::registerPermanentRoot(None);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
3682

Travis Hance's avatar
Travis Hance committed
3683
    // You can't actually have an instance of basestring
3684
    basestring_cls = new (0) BoxedClass(object_cls, NULL, 0, 0, sizeof(Box), false, "basestring");
Travis Hance's avatar
Travis Hance committed
3685

3686
    // We add 1 to the tp_basicsize of the BoxedString in order to hold the null byte at the end.
3687 3688
    // We use offsetof(BoxedString, s_data) as opposed to sizeof(BoxedString) so that we can
    // use the extra padding bytes at the end of the BoxedString.
3689
    str_cls = new (0) BoxedClass(basestring_cls, NULL, 0, 0, offsetof(BoxedString, s_data) + 1, false, "str");
3690
    str_cls->tp_flags |= Py_TPFLAGS_STRING_SUBCLASS;
3691
    str_cls->tp_itemsize = sizeof(char);
3692

3693 3694
    gc::enableGC();

3695 3696
    // It wasn't safe to add __base__ attributes until object+type+str are set up, so do that now:
    type_cls->giveAttr("__base__", object_cls);
Travis Hance's avatar
Travis Hance committed
3697 3698
    basestring_cls->giveAttr("__base__", object_cls);
    str_cls->giveAttr("__base__", basestring_cls);
3699 3700 3701
    none_cls->giveAttr("__base__", object_cls);
    object_cls->giveAttr("__base__", None);

3702 3703
    // Not sure why CPython defines sizeof(PyTupleObject) to include one element,
    // but we copy that, which means we have to subtract that extra pointer to get the tp_basicsize:
3704 3705
    tuple_cls = new (0)
        BoxedClass(object_cls, &BoxedTuple::gcHandler, 0, 0, sizeof(BoxedTuple) - sizeof(Box*), false, "tuple");
3706
    tuple_cls->tp_flags |= Py_TPFLAGS_TUPLE_SUBCLASS;
3707 3708 3709
    tuple_cls->tp_itemsize = sizeof(Box*);
    tuple_cls->tp_mro = BoxedTuple::create({ tuple_cls, object_cls });
    EmptyTuple = BoxedTuple::create({});
3710
    gc::registerPermanentRoot(EmptyTuple);
3711
    list_cls = new (0) BoxedClass(object_cls, &BoxedList::gcHandler, 0, 0, sizeof(BoxedList), false, "list");
3712
    list_cls->tp_flags |= Py_TPFLAGS_LIST_SUBCLASS;
3713
    pyston_getset_cls = new (0)
3714 3715 3716 3717
        BoxedClass(object_cls, NULL, 0, 0, sizeof(BoxedGetsetDescriptor), false, "getset_descriptor");
    attrwrapper_cls = new (0)
        BoxedClass(object_cls, &AttrWrapper::gcHandler, 0, 0, sizeof(AttrWrapper), false, "attrwrapper");
    dict_cls = new (0) BoxedClass(object_cls, &BoxedDict::gcHandler, 0, 0, sizeof(BoxedDict), false, "dict");
3718
    dict_cls->tp_flags |= Py_TPFLAGS_DICT_SUBCLASS;
3719 3720 3721
    file_cls = new (0) BoxedClass(object_cls, &BoxedFile::gcHandler, 0, offsetof(BoxedFile, weakreflist),
                                  sizeof(BoxedFile), false, "file");
    int_cls = new (0) BoxedClass(object_cls, NULL, 0, 0, sizeof(BoxedInt), false, "int");
3722
    int_cls->tp_flags |= Py_TPFLAGS_INT_SUBCLASS;
3723 3724 3725
    bool_cls = new (0) BoxedClass(int_cls, NULL, 0, 0, sizeof(BoxedBool), false, "bool");
    complex_cls = new (0) BoxedClass(object_cls, NULL, 0, 0, sizeof(BoxedComplex), false, "complex");
    long_cls = new (0) BoxedClass(object_cls, &BoxedLong::gchandler, 0, 0, sizeof(BoxedLong), false, "long");
3726
    long_cls->tp_flags |= Py_TPFLAGS_LONG_SUBCLASS;
3727 3728 3729 3730
    float_cls = new (0) BoxedClass(object_cls, NULL, 0, 0, sizeof(BoxedFloat), false, "float");
    function_cls = new (0)
        BoxedClass(object_cls, &BoxedFunction::gcHandler, offsetof(BoxedFunction, attrs),
                   offsetof(BoxedFunction, in_weakreflist), sizeof(BoxedFunction), false, "function");
3731
    builtin_function_or_method_cls = new (0)
3732 3733
        BoxedClass(object_cls, &BoxedFunction::gcHandler, 0, offsetof(BoxedBuiltinFunctionOrMethod, in_weakreflist),
                   sizeof(BoxedBuiltinFunctionOrMethod), false, "builtin_function_or_method");
3734 3735
    function_cls->tp_dealloc = builtin_function_or_method_cls->tp_dealloc = functionDtor;
    function_cls->has_safe_tp_dealloc = builtin_function_or_method_cls->has_safe_tp_dealloc = true;
3736

Kevin Modzelewski's avatar
wip  
Kevin Modzelewski committed
3737
    // XXX
3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750
    _Py_ReleaseInternedStrings();
    for (auto b : classes)
        b->clearAttrs();
    for (auto b : { (Box*)None, (Box*)EmptyTuple })
        Py_DECREF(b);
    for (auto b : classes) {
        if (b->tp_mro) {
            Py_DECREF(b->tp_mro);
        }
        Py_DECREF(b);
    }
    PRINT_TOTAL_REFS();
    exit(0);
Kevin Modzelewski's avatar
wip  
Kevin Modzelewski committed
3751
    // XXX
3752 3753


3754

3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766
    module_cls = new (0) BoxedClass(object_cls, &BoxedModule::gcHandler, offsetof(BoxedModule, attrs), 0,
                                    sizeof(BoxedModule), false, "module");
    member_descriptor_cls = new (0)
        BoxedClass(object_cls, NULL, 0, 0, sizeof(BoxedMemberDescriptor), false, "member_descriptor");
    capifunc_cls = new (0)
        BoxedClass(object_cls, BoxedCApiFunction::gcHandler, 0, 0, sizeof(BoxedCApiFunction), false, "capifunc");
    method_cls = new (0) BoxedClass(object_cls, BoxedMethodDescriptor::gcHandler, 0, 0, sizeof(BoxedMethodDescriptor),
                                    false, "method_descriptor");
    wrapperobject_cls = new (0) BoxedClass(object_cls, BoxedWrapperObject::gcHandler, 0, 0, sizeof(BoxedWrapperObject),
                                           false, "method-wrapper");
    wrapperdescr_cls = new (0) BoxedClass(object_cls, BoxedWrapperDescriptor::gcHandler, 0, 0,
                                          sizeof(BoxedWrapperDescriptor), false, "wrapper_descriptor");
3767

3768 3769 3770 3771 3772 3773 3774 3775 3776 3777
    EmptyString = new (0) BoxedString("");
    // Call InternInPlace rather than InternFromString since that will
    // probably try to return EmptyString
    PyString_InternInPlace((Box**)&EmptyString);
    for (int i = 0; i <= UCHAR_MAX; i++) {
        char c = (char)i;
        BoxedString* s = new (1) BoxedString(llvm::StringRef(&c, 1));
        PyString_InternInPlace((Box**)&s);
        characters[i] = s;
    }
3778 3779 3780 3781

    // Kind of hacky, but it's easier to manually construct the mro for a couple key classes
    // than try to make the MRO construction code be safe against say, tuple_cls not having
    // an mro (since the mro is stored as a tuple).
3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795
    object_cls->tp_mro = BoxedTuple::create({ object_cls });
    list_cls->tp_mro = BoxedTuple::create({ list_cls, object_cls });
    type_cls->tp_mro = BoxedTuple::create({ type_cls, object_cls });
    pyston_getset_cls->tp_mro = BoxedTuple::create({ pyston_getset_cls, object_cls });
    attrwrapper_cls->tp_mro = BoxedTuple::create({ attrwrapper_cls, object_cls });
    dict_cls->tp_mro = BoxedTuple::create({ dict_cls, object_cls });
    file_cls->tp_mro = BoxedTuple::create({ file_cls, object_cls });
    int_cls->tp_mro = BoxedTuple::create({ int_cls, object_cls });
    bool_cls->tp_mro = BoxedTuple::create({ bool_cls, object_cls });
    complex_cls->tp_mro = BoxedTuple::create({ complex_cls, object_cls });
    long_cls->tp_mro = BoxedTuple::create({ long_cls, object_cls });
    float_cls->tp_mro = BoxedTuple::create({ float_cls, object_cls });
    function_cls->tp_mro = BoxedTuple::create({ function_cls, object_cls });
    builtin_function_or_method_cls->tp_mro = BoxedTuple::create({ builtin_function_or_method_cls, object_cls });
3796
    member_descriptor_cls->tp_mro = BoxedTuple::create({ member_descriptor_cls, object_cls });
3797 3798 3799 3800 3801
    capifunc_cls->tp_mro = BoxedTuple::create({ capifunc_cls, object_cls });
    module_cls->tp_mro = BoxedTuple::create({ module_cls, object_cls });
    method_cls->tp_mro = BoxedTuple::create({ method_cls, object_cls });
    wrapperobject_cls->tp_mro = BoxedTuple::create({ wrapperobject_cls, object_cls });
    wrapperdescr_cls->tp_mro = BoxedTuple::create({ wrapperdescr_cls, object_cls });
3802

3803 3804
    object_cls->tp_hash = (hashfunc)_Py_HashPointer;

3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829
    STR = typeFromClass(str_cls);
    BOXED_INT = typeFromClass(int_cls);
    BOXED_FLOAT = typeFromClass(float_cls);
    BOXED_BOOL = typeFromClass(bool_cls);
    NONE = typeFromClass(none_cls);
    LIST = typeFromClass(list_cls);
    MODULE = typeFromClass(module_cls);
    DICT = typeFromClass(dict_cls);
    BOXED_TUPLE = typeFromClass(tuple_cls);
    LONG = typeFromClass(long_cls);
    BOXED_COMPLEX = typeFromClass(complex_cls);

    True = new BoxedBool(true);
    False = new BoxedBool(false);

    gc::registerPermanentRoot(True);
    gc::registerPermanentRoot(False);

    // Need to initialize interned_ints early:
    setupInt();
    // sys is the first module that needs to be set up, due to modules
    // being tracked in sys.modules:
    setupSys();
    // Weakrefs are used for tp_subclasses:
    init_weakref();
3830

3831 3832
    add_operators(object_cls);

3833 3834 3835 3836 3837 3838 3839
    object_cls->finishInitialization();
    type_cls->finishInitialization();
    basestring_cls->finishInitialization();
    str_cls->finishInitialization();
    none_cls->finishInitialization();
    tuple_cls->finishInitialization();
    list_cls->finishInitialization();
3840
    pyston_getset_cls->finishInitialization();
3841
    attrwrapper_cls->finishInitialization();
3842 3843 3844 3845 3846 3847 3848 3849 3850
    dict_cls->finishInitialization();
    file_cls->finishInitialization();
    int_cls->finishInitialization();
    bool_cls->finishInitialization();
    complex_cls->finishInitialization();
    long_cls->finishInitialization();
    float_cls->finishInitialization();
    function_cls->finishInitialization();
    builtin_function_or_method_cls->finishInitialization();
3851
    member_descriptor_cls->finishInitialization();
3852 3853 3854 3855
    module_cls->finishInitialization();
    capifunc_cls->finishInitialization();
    method_cls->finishInitialization();
    wrapperobject_cls->finishInitialization();
3856 3857
    wrapperdescr_cls->finishInitialization();

3858 3859
    str_cls->tp_flags |= Py_TPFLAGS_HAVE_NEWBUFFER;

3860
    dict_descr = new (pyston_getset_cls) BoxedGetsetDescriptor(typeSubDict, typeSubSetDict, NULL);
3861
    gc::registerPermanentRoot(dict_descr);
3862
    type_cls->giveAttr("__dict__", new (pyston_getset_cls) BoxedGetsetDescriptor(typeDict, NULL, NULL));
3863 3864


3865 3866 3867
    instancemethod_cls = BoxedClass::create(type_cls, object_cls, &BoxedInstanceMethod::gcHandler, 0,
                                            offsetof(BoxedInstanceMethod, in_weakreflist), sizeof(BoxedInstanceMethod),
                                            false, "instancemethod");
3868

3869 3870 3871 3872 3873 3874
    slice_cls
        = BoxedClass::create(type_cls, object_cls, &BoxedSlice::gcHandler, 0, 0, sizeof(BoxedSlice), false, "slice");
    set_cls = BoxedClass::create(type_cls, object_cls, &BoxedSet::gcHandler, 0, offsetof(BoxedSet, weakreflist),
                                 sizeof(BoxedSet), false, "set");
    frozenset_cls = BoxedClass::create(type_cls, object_cls, &BoxedSet::gcHandler, 0, offsetof(BoxedSet, weakreflist),
                                       sizeof(BoxedSet), false, "frozenset");
3875
    capi_getset_cls
3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 3886
        = BoxedClass::create(type_cls, object_cls, NULL, 0, 0, sizeof(BoxedGetsetDescriptor), false, "getset");
    closure_cls = BoxedClass::create(type_cls, object_cls, &BoxedClosure::gcHandler, 0, 0, sizeof(BoxedClosure), false,
                                     "closure");
    property_cls = BoxedClass::create(type_cls, object_cls, &BoxedProperty::gcHandler, 0, 0, sizeof(BoxedProperty),
                                      false, "property");
    staticmethod_cls = BoxedClass::create(type_cls, object_cls, &BoxedStaticmethod::gcHandler, 0, 0,
                                          sizeof(BoxedStaticmethod), false, "staticmethod");
    classmethod_cls = BoxedClass::create(type_cls, object_cls, &BoxedClassmethod::gcHandler, 0, 0,
                                         sizeof(BoxedClassmethod), false, "classmethod");
    attrwrapperiter_cls = BoxedClass::create(type_cls, object_cls, &AttrWrapperIter::gcHandler, 0, 0,
                                             sizeof(AttrWrapperIter), false, "attrwrapperiter");
Kevin Modzelewski's avatar
Kevin Modzelewski committed
3887

3888 3889 3890 3891 3892 3893 3894 3895
    pyston_getset_cls->giveAttr("__get__", new BoxedFunction(FunctionMetadata::create((void*)getsetGet, UNKNOWN, 3)));
    capi_getset_cls->giveAttr("__get__", new BoxedFunction(FunctionMetadata::create((void*)getsetGet, UNKNOWN, 3)));
    pyston_getset_cls->giveAttr("__set__", new BoxedFunction(FunctionMetadata::create((void*)getsetSet, UNKNOWN, 3)));
    capi_getset_cls->giveAttr("__set__", new BoxedFunction(FunctionMetadata::create((void*)getsetSet, UNKNOWN, 3)));
    pyston_getset_cls->giveAttr("__delete__",
                                new BoxedFunction(FunctionMetadata::create((void*)getsetDelete, UNKNOWN, 2)));
    capi_getset_cls->giveAttr("__delete__",
                              new BoxedFunction(FunctionMetadata::create((void*)getsetDelete, UNKNOWN, 2)));
3896 3897 3898
    pyston_getset_cls->freeze();
    capi_getset_cls->freeze();

Kevin Modzelewski's avatar
Kevin Modzelewski committed
3899
    SLICE = typeFromClass(slice_cls);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
3900
    SET = typeFromClass(set_cls);
3901
    FROZENSET = typeFromClass(frozenset_cls);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
3902

3903 3904 3905 3906 3907
    object_cls->giveAttr("__repr__",
                         new BoxedFunction(FunctionMetadata::create((void*)objectRepr, UNKNOWN, 1, false, false)));
    object_cls->giveAttr("__subclasshook__", boxInstanceMethod(object_cls, new BoxedFunction(FunctionMetadata::create(
                                                                               (void*)objectSubclasshook, UNKNOWN, 2)),
                                                               object_cls));
3908
    // __setattr__ was already set to a WrapperDescriptor; it'd be nice to set this to a faster BoxedFunction
3909 3910
    // object_cls->setattr("__setattr__", new BoxedFunction(FunctionMetadata::create((void*)objectSetattr, UNKNOWN, 3)),
    // NULL);
3911 3912
    // but unfortunately that will set tp_setattro to slot_tp_setattro on object_cls and all already-made subclasses!
    // Punting on that until needed; hopefully by then we will have better Pyston slots support.
3913

3914
    auto typeCallObj = FunctionMetadata::create((void*)typeCall, UNKNOWN, 1, true, true);
3915
    typeCallObj->internal_callable.cxx_val = &typeCallInternal;
3916

3917
    type_cls->giveAttr("__name__", new (pyston_getset_cls) BoxedGetsetDescriptor(typeName, typeSetName, NULL));
3918
    type_cls->giveAttr("__bases__", new (pyston_getset_cls) BoxedGetsetDescriptor(typeBases, typeSetBases, NULL));
3919 3920
    type_cls->giveAttr("__call__", new BoxedFunction(typeCallObj));

3921
    type_cls->giveAttr(
3922 3923 3924
        "__new__",
        new BoxedFunction(FunctionMetadata::create((void*)typeNewGeneric, UNKNOWN, 4, false, false), { NULL, NULL }));
    type_cls->giveAttr("__repr__", new BoxedFunction(FunctionMetadata::create((void*)typeRepr, STR, 1)));
3925
    type_cls->tp_hash = (hashfunc)_Py_HashPointer;
3926
    type_cls->giveAttr("__module__", new (pyston_getset_cls) BoxedGetsetDescriptor(typeModule, typeSetModule, NULL));
3927 3928
    type_cls->giveAttr("__mro__",
                       new BoxedMemberDescriptor(BoxedMemberDescriptor::OBJECT, offsetof(BoxedClass, tp_mro)));
3929 3930
    type_cls->giveAttr("__flags__",
                       new BoxedMemberDescriptor(BoxedMemberDescriptor::LONG, offsetof(BoxedClass, tp_flags)));
3931 3932 3933
    type_cls->giveAttr("__subclasses__",
                       new BoxedFunction(FunctionMetadata::create((void*)typeSubclasses, UNKNOWN, 1)));
    type_cls->giveAttr("mro", new BoxedFunction(FunctionMetadata::create((void*)typeMro, UNKNOWN, 1)));
3934 3935
    type_cls->tp_richcompare = type_richcompare;
    add_operators(type_cls);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
3936
    type_cls->freeze();
Rudi Chen's avatar
Rudi Chen committed
3937
    type_cls->tp_new = type_new;
3938 3939
    type_cls->tpp_call.capi_val = &typeTppCall<CAPI>;
    type_cls->tpp_call.cxx_val = &typeTppCall<CXX>;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
3940

3941 3942
    none_cls->giveAttr("__repr__", new BoxedFunction(FunctionMetadata::create((void*)none_repr, STR, 1)));
    none_cls->giveAttr("__nonzero__", new BoxedFunction(FunctionMetadata::create((void*)noneNonzero, BOXED_BOOL, 1)));
3943
    none_cls->giveAttr("__doc__", None);
3944
    none_cls->tp_hash = (hashfunc)_Py_HashPointer;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
3945
    none_cls->freeze();
3946
    none_cls->tp_repr = none_repr;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
3947

3948 3949 3950
    module_cls->giveAttr(
        "__init__", new BoxedFunction(FunctionMetadata::create((void*)moduleInit, UNKNOWN, 3, false, false), { NULL }));
    module_cls->giveAttr("__repr__", new BoxedFunction(FunctionMetadata::create((void*)moduleRepr, STR, 1)));
3951
    module_cls->giveAttr("__dict__", dict_descr);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
3952 3953
    module_cls->freeze();

Kevin Modzelewski's avatar
Kevin Modzelewski committed
3954 3955
    closure_cls->freeze();

3956
    setupUnwinding();
Kevin Modzelewski's avatar
Kevin Modzelewski committed
3957 3958
    setupCAPI();

3959 3960 3961 3962
    // Can't set up object methods until we set up CAPI support:
    for (auto& md : object_methods) {
        object_cls->giveAttr(md.ml_name, new BoxedMethodDescriptor(&md, object_cls));
    }
3963
    object_cls->giveAttr("__class__", new (pyston_getset_cls) BoxedGetsetDescriptor(objectClass, objectSetClass, NULL));
3964 3965 3966 3967

    object_cls->tp_str = object_str;
    add_operators(object_cls);

3968
    object_cls->freeze();
3969

3970 3971
    assert(object_cls->tp_init == object_init);
    assert(object_cls->tp_new == object_new);
3972
    assert(object_cls->tp_str == object_str);
3973

Kevin Modzelewski's avatar
Kevin Modzelewski committed
3974
    setupBool();
3975
    setupLong();
Kevin Modzelewski's avatar
Kevin Modzelewski committed
3976
    setupFloat();
3977
    setupComplex();
Kevin Modzelewski's avatar
Kevin Modzelewski committed
3978 3979 3980
    setupStr();
    setupList();
    setupDict();
Kevin Modzelewski's avatar
Kevin Modzelewski committed
3981
    setupSet();
Kevin Modzelewski's avatar
Kevin Modzelewski committed
3982 3983
    setupTuple();
    setupFile();
3984
    setupGenerator();
3985
    setupIter();
3986
    setupClassobj();
3987
    setupSuper();
3988
    _PyUnicode_Init();
Travis Hance's avatar
Travis Hance committed
3989
    setupDescr();
3990
    setupTraceback();
3991
    setupCode();
3992
    setupFrame();
Kevin Modzelewski's avatar
Kevin Modzelewski committed
3993

3994
    function_cls->giveAttr("__dict__", dict_descr);
3995
    function_cls->giveAttr("__name__", new (pyston_getset_cls) BoxedGetsetDescriptor(funcName, funcSetName, NULL));
3996
    function_cls->giveAttr("__repr__", new BoxedFunction(FunctionMetadata::create((void*)functionRepr, STR, 1)));
3997 3998
    function_cls->giveAttr("__module__", new BoxedMemberDescriptor(BoxedMemberDescriptor::OBJECT,
                                                                   offsetof(BoxedFunction, modname), false));
3999 4000
    function_cls->giveAttr(
        "__doc__", new BoxedMemberDescriptor(BoxedMemberDescriptor::OBJECT, offsetof(BoxedFunction, doc), false));
4001
    function_cls->giveAttr("func_doc", function_cls->getattr(internStringMortal("__doc__")));
4002
    function_cls->giveAttr("__globals__", new (pyston_getset_cls) BoxedGetsetDescriptor(functionGlobals, NULL, NULL));
4003 4004 4005 4006 4007
    function_cls->giveAttr("__get__", new BoxedFunction(FunctionMetadata::create((void*)functionGet, UNKNOWN, 3)));
    function_cls->giveAttr("__call__",
                           new BoxedFunction(FunctionMetadata::create((void*)functionCall, UNKNOWN, 1, true, true)));
    function_cls->giveAttr("__nonzero__",
                           new BoxedFunction(FunctionMetadata::create((void*)functionNonzero, BOXED_BOOL, 1)));
4008 4009
    function_cls->giveAttr("func_code",
                           new (pyston_getset_cls) BoxedGetsetDescriptor(functionCode, functionSetCode, NULL));
4010 4011
    function_cls->giveAttr("__code__", function_cls->getattr(internStringMortal("func_code")));
    function_cls->giveAttr("func_name", function_cls->getattr(internStringMortal("__name__")));
4012
    function_cls->giveAttr("func_defaults",
4013
                           new (pyston_getset_cls) BoxedGetsetDescriptor(functionDefaults, functionSetDefaults, NULL));
4014 4015
    function_cls->giveAttr("__defaults__", function_cls->getattr(internStringMortal("func_defaults")));
    function_cls->giveAttr("func_globals", function_cls->getattr(internStringMortal("__globals__")));
Kevin Modzelewski's avatar
Kevin Modzelewski committed
4016
    function_cls->freeze();
4017
    function_cls->tp_descr_get = function_descr_get;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
4018

Travis Hance's avatar
Travis Hance committed
4019 4020 4021
    builtin_function_or_method_cls->giveAttr(
        "__module__",
        new BoxedMemberDescriptor(BoxedMemberDescriptor::OBJECT, offsetof(BoxedBuiltinFunctionOrMethod, modname)));
4022
    builtin_function_or_method_cls->giveAttr(
4023 4024
        "__call__",
        new BoxedFunction(FunctionMetadata::create((void*)builtinFunctionOrMethodCall, UNKNOWN, 1, true, true)));
4025

Travis Hance's avatar
Travis Hance committed
4026
    builtin_function_or_method_cls->giveAttr(
4027
        "__repr__", new BoxedFunction(FunctionMetadata::create((void*)builtinFunctionOrMethodRepr, STR, 1)));
4028 4029
    builtin_function_or_method_cls->giveAttr(
        "__name__", new (pyston_getset_cls) BoxedGetsetDescriptor(builtinFunctionOrMethodName, NULL, NULL));
4030 4031 4032
    builtin_function_or_method_cls->giveAttr(
        "__doc__",
        new BoxedMemberDescriptor(BoxedMemberDescriptor::OBJECT, offsetof(BoxedBuiltinFunctionOrMethod, doc), false));
Travis Hance's avatar
Travis Hance committed
4033 4034
    builtin_function_or_method_cls->freeze();

4035
    instancemethod_cls->giveAttr(
4036 4037 4038 4039 4040 4041 4042 4043 4044 4045
        "__new__",
        new BoxedFunction(FunctionMetadata::create((void*)instancemethodNew, UNKNOWN, 4, false, false), { NULL }));
    instancemethod_cls->giveAttr("__repr__",
                                 new BoxedFunction(FunctionMetadata::create((void*)instancemethodRepr, STR, 1)));
    instancemethod_cls->giveAttr("__eq__",
                                 new BoxedFunction(FunctionMetadata::create((void*)instancemethodEq, UNKNOWN, 2)));
    instancemethod_cls->giveAttr(
        "__get__", new BoxedFunction(FunctionMetadata::create((void*)instancemethodGet, UNKNOWN, 3, false, false)));
    instancemethod_cls->giveAttr(
        "__call__", new BoxedFunction(FunctionMetadata::create((void*)instancemethodCall, UNKNOWN, 1, true, true)));
4046 4047
    instancemethod_cls->giveAttr(
        "im_func", new BoxedMemberDescriptor(BoxedMemberDescriptor::OBJECT, offsetof(BoxedInstanceMethod, func)));
4048
    instancemethod_cls->giveAttr("__func__", instancemethod_cls->getattr(internStringMortal("im_func")));
4049 4050
    instancemethod_cls->giveAttr(
        "im_self", new BoxedMemberDescriptor(BoxedMemberDescriptor::OBJECT, offsetof(BoxedInstanceMethod, obj)));
4051
    instancemethod_cls->giveAttr("__self__", instancemethod_cls->getattr(internStringMortal("im_self")));
Kevin Modzelewski's avatar
Kevin Modzelewski committed
4052 4053
    instancemethod_cls->freeze();

4054 4055 4056
    instancemethod_cls->giveAttr("im_class", new BoxedMemberDescriptor(BoxedMemberDescriptor::OBJECT,
                                                                       offsetof(BoxedInstanceMethod, im_class), true));

4057 4058 4059 4060 4061 4062 4063
    slice_cls->giveAttr(
        "__new__",
        new BoxedFunction(FunctionMetadata::create((void*)sliceNew, UNKNOWN, 4, false, false), { NULL, None }));
    slice_cls->giveAttr("__repr__", new BoxedFunction(FunctionMetadata::create((void*)sliceRepr, STR, 1)));
    slice_cls->giveAttr("__hash__", new BoxedFunction(FunctionMetadata::create((void*)sliceHash, UNKNOWN, 1)));
    slice_cls->giveAttr("indices", new BoxedFunction(FunctionMetadata::create((void*)sliceIndices, BOXED_TUPLE, 2)));
    slice_cls->giveAttr("__reduce__", new BoxedFunction(FunctionMetadata::create((void*)sliceReduce, BOXED_TUPLE, 1)));
4064 4065 4066
    slice_cls->giveAttr("start", new BoxedMemberDescriptor(BoxedMemberDescriptor::OBJECT, offsetof(BoxedSlice, start)));
    slice_cls->giveAttr("stop", new BoxedMemberDescriptor(BoxedMemberDescriptor::OBJECT, offsetof(BoxedSlice, stop)));
    slice_cls->giveAttr("step", new BoxedMemberDescriptor(BoxedMemberDescriptor::OBJECT, offsetof(BoxedSlice, step)));
Kevin Modzelewski's avatar
Kevin Modzelewski committed
4067
    slice_cls->freeze();
4068
    slice_cls->tp_compare = (cmpfunc)slice_compare;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
4069

4070 4071
    static PyMappingMethods attrwrapper_as_mapping;
    attrwrapper_cls->tp_as_mapping = &attrwrapper_as_mapping;
4072 4073
    static PySequenceMethods attrwrapper_as_sequence;
    attrwrapper_cls->tp_as_sequence = &attrwrapper_as_sequence;
4074 4075 4076 4077 4078
    attrwrapper_cls->giveAttr("__setitem__",
                              new BoxedFunction(FunctionMetadata::create((void*)AttrWrapper::setitem, UNKNOWN, 3)));
    attrwrapper_cls->giveAttr(
        "pop",
        new BoxedFunction(FunctionMetadata::create((void*)AttrWrapper::pop, UNKNOWN, 3, false, false), { NULL }));
Kevin Modzelewski's avatar
Kevin Modzelewski committed
4079
    attrwrapper_cls->giveAttr(
4080 4081 4082
        "__getitem__", new BoxedFunction(FunctionMetadata::create((void*)AttrWrapper::getitem<CXX>, UNKNOWN, 2)));
    attrwrapper_cls->giveAttr("__delitem__",
                              new BoxedFunction(FunctionMetadata::create((void*)AttrWrapper::delitem, UNKNOWN, 2)));
Kevin Modzelewski's avatar
Kevin Modzelewski committed
4083
    attrwrapper_cls->giveAttr("setdefault",
4084
                              new BoxedFunction(FunctionMetadata::create((void*)AttrWrapper::setdefault, UNKNOWN, 3)));
4085
    attrwrapper_cls->giveAttr(
4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101
        "get",
        new BoxedFunction(FunctionMetadata::create((void*)AttrWrapper::get, UNKNOWN, 3, false, false), { None }));
    attrwrapper_cls->giveAttr("__str__",
                              new BoxedFunction(FunctionMetadata::create((void*)AttrWrapper::str, UNKNOWN, 1)));
    attrwrapper_cls->giveAttr(
        "__contains__", new BoxedFunction(FunctionMetadata::create((void*)AttrWrapper::contains<CXX>, UNKNOWN, 2)));
    attrwrapper_cls->giveAttr("__eq__",
                              new BoxedFunction(FunctionMetadata::create((void*)AttrWrapper::eq, UNKNOWN, 2)));
    attrwrapper_cls->giveAttr("__ne__",
                              new BoxedFunction(FunctionMetadata::create((void*)AttrWrapper::ne, UNKNOWN, 2)));
    attrwrapper_cls->giveAttr("keys", new BoxedFunction(FunctionMetadata::create((void*)AttrWrapper::keys, LIST, 1)));
    attrwrapper_cls->giveAttr("values",
                              new BoxedFunction(FunctionMetadata::create((void*)AttrWrapper::values, LIST, 1)));
    attrwrapper_cls->giveAttr("items", new BoxedFunction(FunctionMetadata::create((void*)AttrWrapper::items, LIST, 1)));
    attrwrapper_cls->giveAttr("iterkeys",
                              new BoxedFunction(FunctionMetadata::create((void*)AttrWrapper::iterkeys, UNKNOWN, 1)));
4102
    attrwrapper_cls->giveAttr("itervalues",
4103 4104 4105 4106 4107 4108 4109 4110 4111 4112 4113 4114
                              new BoxedFunction(FunctionMetadata::create((void*)AttrWrapper::itervalues, UNKNOWN, 1)));
    attrwrapper_cls->giveAttr("iteritems",
                              new BoxedFunction(FunctionMetadata::create((void*)AttrWrapper::iteritems, UNKNOWN, 1)));
    attrwrapper_cls->giveAttr("copy",
                              new BoxedFunction(FunctionMetadata::create((void*)AttrWrapper::copy, UNKNOWN, 1)));
    attrwrapper_cls->giveAttr("clear", new BoxedFunction(FunctionMetadata::create((void*)AttrWrapper::clear, NONE, 1)));
    attrwrapper_cls->giveAttr("__len__",
                              new BoxedFunction(FunctionMetadata::create((void*)AttrWrapper::len, BOXED_INT, 1)));
    attrwrapper_cls->giveAttr("__iter__",
                              new BoxedFunction(FunctionMetadata::create((void*)AttrWrapper::iter, UNKNOWN, 1)));
    attrwrapper_cls->giveAttr(
        "update", new BoxedFunction(FunctionMetadata::create((void*)AttrWrapper::update, NONE, 1, true, true)));
4115
    attrwrapper_cls->freeze();
4116
    attrwrapper_cls->tp_iter = AttrWrapper::iter;
4117
    attrwrapper_cls->tp_as_mapping->mp_subscript = (binaryfunc)AttrWrapper::getitem<CAPI>;
4118 4119
    attrwrapper_cls->tp_as_mapping->mp_ass_subscript = (objobjargproc)AttrWrapper::ass_sub;
    attrwrapper_cls->tp_as_sequence->sq_contains = (objobjproc)AttrWrapper::sq_contains;
4120

4121 4122 4123 4124
    attrwrapperiter_cls->giveAttr(
        "__hasnext__", new BoxedFunction(FunctionMetadata::create((void*)AttrWrapperIter::hasnext, UNKNOWN, 1)));
    attrwrapperiter_cls->giveAttr(
        "next", new BoxedFunction(FunctionMetadata::create((void*)AttrWrapperIter::next, UNKNOWN, 1)));
Kevin Modzelewski's avatar
Kevin Modzelewski committed
4125
    attrwrapperiter_cls->freeze();
4126 4127
    attrwrapperiter_cls->tp_iter = PyObject_SelfIter;
    attrwrapperiter_cls->tp_iternext = AttrWrapperIter::next_capi;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
4128

4129
    setupBuiltins();
4130
    _PyExc_Init();
4131
    setupThread();
4132
    setupGC();
4133
    setupImport();
4134
    setupPyston();
4135
    setupAST();
Kevin Modzelewski's avatar
Kevin Modzelewski committed
4136

Marius Wachtler's avatar
Marius Wachtler committed
4137
    PyType_Ready(&PyByteArrayIter_Type);
4138
    PyType_Ready(&PyCapsule_Type);
4139 4140

    PyCallIter_Type.tpp_hasnext = calliter_hasnext;
4141
    PyType_Ready(&PyCallIter_Type);
4142

Kevin Modzelewski's avatar
Kevin Modzelewski committed
4143
    PyType_Ready(&PyCObject_Type);
4144
    PyType_Ready(&PyDictProxy_Type);
4145

4146
    initerrno();
4147
    init_sha();
4148 4149 4150
    init_sha256();
    init_sha512();
    init_md5();
Marius Wachtler's avatar
Marius Wachtler committed
4151
    init_random();
4152
    init_sre();
Marius Wachtler's avatar
Marius Wachtler committed
4153
    initmath();
Travis Hance's avatar
Travis Hance committed
4154
    initoperator();
Kevin Modzelewski's avatar
Kevin Modzelewski committed
4155
    initbinascii();
4156
    initpwd();
4157
    initposix();
4158
    init_struct();
Kevin Modzelewski's avatar
Kevin Modzelewski committed
4159
    initdatetime();
Kevin Modzelewski's avatar
Kevin Modzelewski committed
4160
    init_functools();
4161
    init_collections();
Kevin Modzelewski's avatar
Kevin Modzelewski committed
4162
    inititertools();
4163
    initresource();
Kevin Modzelewski's avatar
Kevin Modzelewski committed
4164
    initsignal();
4165
    initselect();
Kevin Modzelewski's avatar
Kevin Modzelewski committed
4166
    initfcntl();
4167
    inittime();
Marius Wachtler's avatar
Marius Wachtler committed
4168
    initarray();
Kevin Modzelewski's avatar
Kevin Modzelewski committed
4169
    initzlib();
4170
    init_codecs();
Kevin Modzelewski's avatar
Kevin Modzelewski committed
4171
    init_socket();
4172
    initunicodedata();
Marius Wachtler's avatar
Marius Wachtler committed
4173
    initcStringIO();
4174
    init_io();
4175
    initzipimport();
Marius Wachtler's avatar
Marius Wachtler committed
4176
    init_csv();
Marius Wachtler's avatar
Marius Wachtler committed
4177
    init_ssl();
4178
    init_sqlite3();
4179
    PyMarshal_Init();
4180
    initstrop();
4181

4182
    setupDefaultClassGCParticipation();
4183

4184 4185 4186
    assert(object_cls->tp_setattro == PyObject_GenericSetAttr);
    assert(none_cls->tp_setattro == PyObject_GenericSetAttr);

4187 4188 4189 4190
    assert(object_cls->tp_hash == (hashfunc)_Py_HashPointer);
    assert(none_cls->tp_hash == (hashfunc)_Py_HashPointer);
    assert(type_cls->tp_hash == (hashfunc)_Py_HashPointer);

4191 4192
    setupSysEnd();

Kevin Modzelewski's avatar
Kevin Modzelewski committed
4193 4194 4195
    TRACK_ALLOCATIONS = true;
}

4196
BoxedModule* createModule(BoxedString* name, const char* fn, const char* doc) {
Chris Toshok's avatar
Chris Toshok committed
4197
    assert((!fn || strlen(fn)) && "probably wanted to set the fn to <stdin>?");
4198

Kevin Modzelewski's avatar
Kevin Modzelewski committed
4199
    BoxedDict* d = getSysModulesDict();
4200

4201 4202
    // Surprisingly, there are times that we need to return the existing module if
    // one exists:
4203
    Box* existing = d->getOrNull(name);
4204
    if (existing && PyModule_Check(existing)) {
4205
        return static_cast<BoxedModule*>(existing);
4206 4207
    }

4208
    BoxedModule* module = new BoxedModule();
4209
    moduleInit(module, name, boxString(doc ? doc : ""));
4210 4211
    if (fn)
        module->giveAttr("__file__", boxString(fn));
4212

4213 4214
    d->d[name] = module;
    if (name->s() == "__main__")
4215
        module->giveAttr("__builtins__", builtins_module);
4216 4217 4218
    return module;
}

Kevin Modzelewski's avatar
Kevin Modzelewski committed
4219 4220 4221 4222 4223 4224 4225 4226 4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237 4238 4239 4240 4241 4242 4243 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 4256 4257 4258 4259 4260 4261 4262 4263 4264 4265 4266 4267 4268 4269 4270 4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 4281 4282 4283 4284 4285 4286 4287 4288 4289 4290 4291 4292 4293 4294 4295 4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 4324 4325 4326 4327 4328 4329 4330 4331 4332 4333 4334 4335 4336 4337 4338 4339 4340 4341 4342 4343 4344 4345 4346 4347 4348 4349
static void call_sys_exitfunc(void) {
    PyObject* exitfunc = PySys_GetObject("exitfunc");

    if (exitfunc) {
        PyObject* res;
        Py_INCREF(exitfunc);
        PySys_SetObject("exitfunc", (PyObject*)NULL);
        res = PyEval_CallObject(exitfunc, (PyObject*)NULL);
        if (res == NULL) {
            if (!PyErr_ExceptionMatches(PyExc_SystemExit)) {
                PySys_WriteStderr("Error in sys.exitfunc:\n");
            }
            PyErr_Print();
        }
        Py_DECREF(exitfunc);
    }

    if (Py_FlushLine())
        PyErr_Clear();
}

extern "C" void Py_Finalize() noexcept {
    // In the future this will have to wait for non-daemon
    // threads to finish

    // wait_for_thread_shutdown();

    call_sys_exitfunc();
    // initialized = 0;

    // PyOS_FiniInterrupts();

    PyType_ClearCache();

// PyGC_Collect());

// PyImport_Cleanup();
// _PyImport_Fini();

// _PyExc_Fini();

// _PyGILState_Fini();

// TODO it's probably a waste of time to tear these down in non-debugging mode
/*
// clear all the attributes on the base classes before freeing the classes themselves,
// since we will run into problem if we free a class but there is an object somewhere
// else that refers to it.
clearAttrs(bool_cls);
clearAttrs(int_cls);
clearAttrs(float_cls);
clearAttrs(none_cls);
clearAttrs(function_cls);
clearAttrs(instancemethod_cls);
clearAttrs(str_cls);
clearAttrs(list_cls);
clearAttrs(slice_cls);
clearAttrs(type_cls);
clearAttrs(module_cls);
clearAttrs(dict_cls);
clearAttrs(tuple_cls);
clearAttrs(file_cls);

decref(bool_cls);
decref(int_cls);
decref(float_cls);
decref(function_cls);
decref(instancemethod_cls);
decref(str_cls);
decref(list_cls);
decref(slice_cls);
decref(module_cls);
decref(dict_cls);
decref(tuple_cls);
decref(file_cls);

ASSERT(None->nrefs == 1, "%ld", None->nrefs);
decref(None);

decref(none_cls);
decref(type_cls);
*/

#if 0
    /* Delete current thread */
    PyThreadState_Swap(NULL);
    PyInterpreterState_Delete(interp);

    /* Sundry finalizers */
    PyMethod_Fini();
    PyFrame_Fini();
    PyCFunction_Fini();
    PyTuple_Fini();
    PyList_Fini();
    PySet_Fini();
    PyString_Fini();
    PyByteArray_Fini();
    PyInt_Fini();
    PyFloat_Fini();
    PyDict_Fini();

#ifdef Py_USING_UNICODE
    /* Cleanup Unicode implementation */
    _PyUnicode_Fini();
#endif

    /* XXX Still allocated:
     * - various static ad-hoc pointers to interned strings
     * - int and float free list blocks
     * - whatever various modules and libraries allocate
     * */

    PyGrammar_RemoveAccelerators(&_PyParser_Grammar);

#ifdef Py_TRACE_REFS
    /* Display addresses (& refcnts) of all objects still alive.
     * * An address can be used to find the repr of the object, printed
     * * above by _Py_PrintReferences.
     * */
    if (Py_GETENV("PYTHONDUMPREFS"))
        _Py_PrintReferenceAddresses(stderr);
#endif /* Py_TRACE_REFS */
#ifdef PYMALLOC_DEBUG
    if (Py_GETENV("PYTHONMALLOCSTATS"))
        _PyObject_DebugMallocStats();
#endif
#endif

    teardownCodegen();

    PRINT_TOTAL_REFS();
Kevin Modzelewski's avatar
Kevin Modzelewski committed
4350 4351
}
}