this repo has no description
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com)
2#include "frame.h"
3
4#include <cstring>
5
6#include "dict-builtins.h"
7#include "handles.h"
8#include "objects.h"
9#include "runtime.h"
10
11namespace py {
12
13const char* Frame::isInvalid() {
14 if (!at(kPreviousFrameOffset).isSmallInt()) {
15 return "bad previousFrame field";
16 }
17 if (!isSentinel() && !(locals() + kFunctionOffsetFromLocals)->isFunction()) {
18 return "bad function";
19 }
20 return nullptr;
21}
22
23RawObject frameLocals(Thread* thread, Frame* frame) {
24 HandleScope scope(thread);
25 Function function(&scope, frame->function());
26 if (!function.hasOptimizedOrNewlocals()) {
27 Object implicit_globals(&scope, frame->implicitGlobals());
28 if (implicit_globals.isNoneType()) {
29 Module module(&scope, function.moduleObject());
30 return module.moduleProxy();
31 }
32 return *implicit_globals;
33 }
34
35 Code code(&scope, function.code());
36 Runtime* runtime = thread->runtime();
37 Tuple empty_tuple(&scope, runtime->emptyTuple());
38 Tuple var_names(&scope,
39 code.varnames().isTuple() ? code.varnames() : *empty_tuple);
40 Tuple freevar_names(
41 &scope, code.freevars().isTuple() ? code.freevars() : *empty_tuple);
42 Tuple cellvar_names(
43 &scope, code.cellvars().isTuple() ? code.cellvars() : *empty_tuple);
44
45 word var_names_length = var_names.length();
46 word freevar_names_length = freevar_names.length();
47 word cellvar_names_length = cellvar_names.length();
48
49 DCHECK(function.totalLocals() ==
50 var_names_length + freevar_names_length + cellvar_names_length,
51 "numbers of local variables do not match");
52
53 Dict result(&scope, runtime->newDict());
54 Str name(&scope, Str::empty());
55 Object value(&scope, NoneType::object());
56 for (word i = 0; i < var_names_length; ++i) {
57 name = var_names.at(i);
58 value = frame->local(i);
59 // TODO(T89882231) Remove check when we can verify locals have been
60 // initialized
61 if (value.isInternal()) continue;
62 dictAtPutByStr(thread, result, name, value);
63 }
64 for (word i = 0, j = var_names_length; i < freevar_names_length; ++i, ++j) {
65 name = freevar_names.at(i);
66 DCHECK(frame->local(j).isCell(), "freevar must be Cell");
67 value = Cell::cast(frame->local(j)).value();
68 // TODO(T89882231) Remove check when we can verify locals have been
69 // initialized
70 if (value.isInternal()) continue;
71 dictAtPutByStr(thread, result, name, value);
72 }
73 for (word i = 0, j = var_names_length + freevar_names_length;
74 i < cellvar_names_length; ++i, ++j) {
75 name = cellvar_names.at(i);
76 DCHECK(frame->local(j).isCell(), "cellvar must be Cell");
77 value = Cell::cast(frame->local(j)).value();
78 // TODO(T89882231) Remove check when we can verify locals have been
79 // initialized
80 if (value.isInternal()) continue;
81 dictAtPutByStr(thread, result, name, value);
82 }
83 return *result;
84}
85
86} // namespace py