Skip to content

Commit 7f11ea6

Browse files
committed
Rewrite LOAD_GLOBAL _Unbound to LOAD_IMMEDIATE in frozen modules
This should save some caches and be faster. Ideally we would do this in all Skybison-controlled modules but I don't think we have a good signal for that yet. Partially addresses #395; we still cannot use it as marker in dictionaries because it's still in the globals dict.
1 parent 5215bf6 commit 7f11ea6

File tree

3 files changed

+34
-3
lines changed

3 files changed

+34
-3
lines changed

runtime/bytecode.cpp

+22-3
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,8 @@ struct RewrittenOp {
8989
bool needs_inline_cache;
9090
};
9191

92-
static RewrittenOp rewriteOperation(const Function& function, BytecodeOp op) {
92+
static RewrittenOp rewriteOperation(const Function& function, BytecodeOp op,
93+
bool is_builtin_module) {
9394
auto cached_binop = [](Interpreter::BinaryOp bin_op) {
9495
return RewrittenOp{BINARY_OP_ANAMORPHIC, static_cast<int32_t>(bin_op),
9596
true};
@@ -177,6 +178,20 @@ static RewrittenOp rewriteOperation(const Function& function, BytecodeOp op) {
177178
return cached_inplace(Interpreter::BinaryOp::XOR);
178179
case LOAD_ATTR:
179180
return RewrittenOp{LOAD_ATTR_ANAMORPHIC, op.arg, true};
181+
case LOAD_GLOBAL: {
182+
if (is_builtin_module) {
183+
RawTuple names = Tuple::cast(Code::cast(function.code()).names());
184+
RawStr name = Str::cast(names.at(op.arg));
185+
if (name.equalsCStr("_Unbound")) {
186+
DCHECK(Unbound::object() ==
187+
objectFromOparg(opargFromObject(Unbound::object())),
188+
"Expected to be able to fit _Unbound in a byte");
189+
return RewrittenOp{LOAD_IMMEDIATE, opargFromObject(Unbound::object()),
190+
false};
191+
}
192+
}
193+
break;
194+
}
180195
case LOAD_FAST: {
181196
CHECK(op.arg < Code::cast(function.code()).nlocals(),
182197
"unexpected local number");
@@ -291,7 +306,8 @@ void rewriteBytecode(Thread* thread, const Function& function) {
291306
word num_caches = num_global_caches;
292307
for (word i = 0; i < num_opcodes;) {
293308
BytecodeOp op = nextBytecodeOp(bytecode, &i);
294-
RewrittenOp rewritten = rewriteOperation(function, op);
309+
RewrittenOp rewritten = rewriteOperation(function, op,
310+
/*is_builtin_module=*/false);
295311
if (rewritten.needs_inline_cache) {
296312
num_caches++;
297313
}
@@ -308,10 +324,13 @@ void rewriteBytecode(Thread* thread, const Function& function) {
308324
return;
309325
}
310326
word cache = num_global_caches;
327+
RawObject module = function.moduleObject();
328+
bool is_builtin_module =
329+
module.isModule() && Module::cast(module).isBuiltin();
311330
for (word i = 0; i < num_opcodes;) {
312331
BytecodeOp op = nextBytecodeOp(bytecode, &i);
313332
word previous_index = i - 1;
314-
RewrittenOp rewritten = rewriteOperation(function, op);
333+
RewrittenOp rewritten = rewriteOperation(function, op, is_builtin_module);
315334
if (rewritten.bc == UNUSED_BYTECODE_0) continue;
316335
if (rewritten.needs_inline_cache) {
317336
rewrittenBytecodeOpAtPut(bytecode, previous_index, rewritten.bc);

runtime/modules.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ static RawObject createBuiltinModule(Thread* thread, const Str& name) {
3030
if (builtin_index >= 0) {
3131
const FrozenModule* frozen_module = &kFrozenModules[builtin_index];
3232
Module module(&scope, runtime->newModule(name));
33+
module.setId(module.id() | RawModule::kBuiltinTag);
3334
Object modules(&scope, runtime->modules());
3435
Object result(&scope, objectSetItem(thread, modules, name, module));
3536
if (result.isErrorException()) return *result;

runtime/objects.h

+11
Original file line numberDiff line numberDiff line change
@@ -2683,13 +2683,20 @@ class RawModule : public RawAttributeDict {
26832683
word id() const;
26842684
void setId(word id) const;
26852685

2686+
// Return true if the module is built-in; if so, the high bit of id is
2687+
// tagged.
2688+
bool isBuiltin() const;
2689+
26862690
// Layout.
26872691
static const int kNameOffset = RawAttributeDict::kSize;
26882692
static const int kDefOffset = kNameOffset + kPointerSize;
26892693
static const int kStateOffset = kDefOffset + kPointerSize;
26902694
static const int kModuleProxyOffset = kStateOffset + kPointerSize;
26912695
static const int kSize = kModuleProxyOffset + kPointerSize;
26922696

2697+
static const uword kBuiltinTag = uword{1} << sizeof(uword);
2698+
static const uword kBuiltinTagMask = ~kBuiltinTag;
2699+
26932700
// Constants.
26942701
static const word kMaxModuleId = RawHeader::kHashCodeMask;
26952702

@@ -7060,6 +7067,10 @@ inline void RawModule::setId(word id) const {
70607067
setHeader(header().withHashCode(id));
70617068
}
70627069

7070+
inline bool RawModule::isBuiltin() const {
7071+
return id() & kBuiltinTagMask;
7072+
}
7073+
70637074
// RawModuleProxy
70647075

70657076
inline RawObject RawModuleProxy::module() const {

0 commit comments

Comments
 (0)