-
Notifications
You must be signed in to change notification settings - Fork 33
/
vm_fwd.h
131 lines (109 loc) · 3.12 KB
/
vm_fwd.h
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#ifndef IV_LV5_RAILGUN_VM_FWD_H_
#define IV_LV5_RAILGUN_VM_FWD_H_
#include <iv/arith.h>
#include <iv/lv5/arguments.h>
#include <iv/lv5/jsval.h>
#include <iv/lv5/railgun/fwd.h>
#include <iv/lv5/railgun/operation.h>
#include <iv/lv5/railgun/stack.h>
#include <iv/lv5/railgun/direct_threading.h>
#include <iv/lv5/railgun/statistics.h>
#include <iv/lv5/breaker/fwd.h>
namespace iv {
namespace lv5 {
namespace railgun {
class Context;
class VM : private Operation {
public:
friend class breaker::Compiler;
static const int32_t kJumpFromSubroutine = 0;
static const int32_t kJumpFromReturn = 1;
static const int32_t kJumpFromFinally = 2;
JSVal Run(Code* code, Error* e);
JSVal RunEval(Code* code,
JSEnv* variable_env, JSEnv* lexical_env,
JSVal this_binding, Error* e);
JSVal Execute(Arguments* args, JSVMFunction* func, Error* e);
// normal pass
explicit VM(lv5::Context* ctx)
: Operation(ctx),
stack_(),
statistics_() {
}
template<OP::Type op>
static bool IsOP(const Instruction& inst) {
#if defined(IV_LV5_RAILGUN_USE_DIRECT_THREADED_CODE)
return GetLabel<op>() == inst.label;
#else
return op == inst.u32[0];
#endif
}
Stack* stack() {
return &stack_;
}
const Stack* stack() const {
return &stack_;
}
void DumpStatistics() const {
statistics_.Dump();
}
static std::size_t StackOffset() {
return IV_OFFSETOF(VM, stack_);
}
#if defined(IV_LV5_RAILGUN_USE_DIRECT_THREADED_CODE)
private:
// dispatch table get pass
explicit VM(DispatchTableTag tag)
: Operation(nullptr),
stack_(tag),
direct_threading_dispatch_table_(nullptr) {
Execute(nullptr, nullptr);
}
static LabelOPTable CreateLabelTable() {
LabelOPTable result;
const DirectThreadingDispatchTable& table = VM::DispatchTable();
std::size_t index = 0;
for (DirectThreadingDispatchTable::const_iterator it = table.begin(),
last = table.end(); it != last; ++it, ++index) {
result.insert(std::make_pair(*it, static_cast<OP::Type>(index)));
}
return result;
}
public:
// opcode to label table
static const DirectThreadingDispatchTable& DispatchTable() {
static const VM vm(DIRECT_THREADED_DISPATCH_TABLE);
return *vm.direct_threading_dispatch_table_;
}
// label to opcode table
static const LabelOPTable& LabelTable() {
static const LabelOPTable table(CreateLabelTable());
return table;
}
template<OP::Type op>
static const void* GetLabel() {
return DispatchTable()[op];
}
#endif
Context* ctx() const;
private:
// internal Execute
// VM main routine
JSVal Execute(Frame* frame, Error* e);
static void VerifyDynamicEnvironment(Frame* frame) {
JSEnv* env = frame->lexical_env()->outer();
for (; env; env = env->outer()) {
if (frame->variable_env() == env) {
break;
}
}
assert(env == frame->variable_env());
}
Stack stack_;
Statistics statistics_;
#if defined(IV_LV5_RAILGUN_USE_DIRECT_THREADED_CODE)
const DirectThreadingDispatchTable* direct_threading_dispatch_table_;
#endif
};
} } } // namespace iv::lv5::railgun
#endif // IV_LV5_RAILGUN_VM_FWD_H_