forked from rubinius/rubinius
-
Notifications
You must be signed in to change notification settings - Fork 0
/
stack_variables.cpp
103 lines (81 loc) · 2.64 KB
/
stack_variables.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#include "stack_variables.hpp"
#include "builtin/variable_scope.hpp"
#include "vmmethod.hpp"
#include "call_frame.hpp"
namespace rubinius {
VariableScope* StackVariables::create_heap_alias(STATE, CallFrame* call_frame,
bool full)
{
if(on_heap_) return on_heap_;
VMMethod* vmm = call_frame->cm->backend_method();
VariableScope* scope = state->new_object<VariableScope>(G(variable_scope));
if(parent_) {
scope->parent(state, parent_);
} else {
scope->parent(state, nil<VariableScope>());
}
scope->self(state, self_);
scope->block(state, block_);
scope->module(state, module_);
scope->method(state, call_frame->cm);
scope->heap_locals(state, Tuple::create(state, vmm->number_of_locals));
scope->last_match(state, last_match_);
scope->fiber(state, state->vm()->current_fiber.get());
scope->number_of_locals_ = vmm->number_of_locals;
if(full) {
scope->isolated_ = false;
} else {
scope->isolated_ = true;
}
scope->locals_ = locals_;
scope->set_block_as_method(call_frame->block_as_method_p());
on_heap_ = scope;
return scope;
}
void StackVariables::set_last_match(STATE, Object* obj) {
// For closures, get back to the top of the chain and set the
// last_match there. This means that the last_match is shared
// amongst all closures in a method, but thats how it's implemented
// in ruby.
if(parent_) {
VariableScope* scope = parent_;
while(CBOOL(scope->parent())) {
scope = scope->parent();
}
return scope->last_match(state, obj);
}
// Use a heap alias if there is one.
if(on_heap_) {
on_heap_->last_match(state, obj);
// Otherwise, use the local one. This is where a last_match usually
// first appears.
} else {
last_match_ = obj;
}
}
Object* StackVariables::last_match(STATE) {
// For closures, get back to the top of the chain and get that
// last_match.
if(parent_) {
VariableScope* scope = parent_;
while(CBOOL(scope->parent())) {
scope = scope->parent();
}
return scope->last_match();
}
// Otherwise, if this has a heap alias, get the last_match from there.
if(on_heap_) {
return on_heap_->last_match();
// Lastly, use the local one. This is where a last_match begins life.
} else {
return last_match_;
}
}
void StackVariables::flush_to_heap(STATE) {
if(!on_heap_) return;
on_heap_->isolated_ = true;
for(int i = 0; i < on_heap_->number_of_locals_; i++) {
on_heap_->set_local(state, i, locals_[i]);
}
}
}