js/src/jit/BaselineFrameInfo.cpp

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:03274b1eabd6
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * vim: set ts=8 sts=4 et sw=4 tw=99:
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #include "jit/BaselineFrameInfo.h"
8
9 #ifdef DEBUG
10 # include "jit/BytecodeAnalysis.h"
11 #endif
12
13 using namespace js;
14 using namespace js::jit;
15
16 bool
17 FrameInfo::init(TempAllocator &alloc)
18 {
19 // One slot is always needed for this/arguments type checks.
20 size_t nstack = Max(script->nslots() - script->nfixed(), size_t(1));
21 if (!stack.init(alloc, nstack))
22 return false;
23
24 return true;
25 }
26
27 void
28 FrameInfo::sync(StackValue *val)
29 {
30 switch (val->kind()) {
31 case StackValue::Stack:
32 break;
33 case StackValue::LocalSlot:
34 masm.pushValue(addressOfLocal(val->localSlot()));
35 break;
36 case StackValue::ArgSlot:
37 masm.pushValue(addressOfArg(val->argSlot()));
38 break;
39 case StackValue::ThisSlot:
40 masm.pushValue(addressOfThis());
41 break;
42 case StackValue::Register:
43 masm.pushValue(val->reg());
44 break;
45 case StackValue::Constant:
46 masm.pushValue(val->constant());
47 break;
48 default:
49 MOZ_ASSUME_UNREACHABLE("Invalid kind");
50 }
51
52 val->setStack();
53 }
54
55 void
56 FrameInfo::syncStack(uint32_t uses)
57 {
58 JS_ASSERT(uses <= stackDepth());
59
60 uint32_t depth = stackDepth() - uses;
61
62 for (uint32_t i = 0; i < depth; i++) {
63 StackValue *current = &stack[i];
64 sync(current);
65 }
66 }
67
68 uint32_t
69 FrameInfo::numUnsyncedSlots()
70 {
71 // Start at the bottom, find the first value that's not synced.
72 uint32_t i = 0;
73 for (; i < stackDepth(); i++) {
74 if (peek(-int32_t(i + 1))->kind() == StackValue::Stack)
75 break;
76 }
77 return i;
78 }
79
80 void
81 FrameInfo::popValue(ValueOperand dest)
82 {
83 StackValue *val = peek(-1);
84
85 switch (val->kind()) {
86 case StackValue::Constant:
87 masm.moveValue(val->constant(), dest);
88 break;
89 case StackValue::LocalSlot:
90 masm.loadValue(addressOfLocal(val->localSlot()), dest);
91 break;
92 case StackValue::ArgSlot:
93 masm.loadValue(addressOfArg(val->argSlot()), dest);
94 break;
95 case StackValue::ThisSlot:
96 masm.loadValue(addressOfThis(), dest);
97 break;
98 case StackValue::Stack:
99 masm.popValue(dest);
100 break;
101 case StackValue::Register:
102 masm.moveValue(val->reg(), dest);
103 break;
104 default:
105 MOZ_ASSUME_UNREACHABLE("Invalid kind");
106 }
107
108 // masm.popValue already adjusted the stack pointer, don't do it twice.
109 pop(DontAdjustStack);
110 }
111
112 void
113 FrameInfo::popRegsAndSync(uint32_t uses)
114 {
115 // x86 has only 3 Value registers. Only support 2 regs here for now,
116 // so that there's always a scratch Value register for reg -> reg
117 // moves.
118 JS_ASSERT(uses > 0);
119 JS_ASSERT(uses <= 2);
120 JS_ASSERT(uses <= stackDepth());
121
122 syncStack(uses);
123
124 switch (uses) {
125 case 1:
126 popValue(R0);
127 break;
128 case 2: {
129 // If the second value is in R1, move it to R2 so that it's not
130 // clobbered by the first popValue.
131 StackValue *val = peek(-2);
132 if (val->kind() == StackValue::Register && val->reg() == R1) {
133 masm.moveValue(R1, R2);
134 val->setRegister(R2);
135 }
136 popValue(R1);
137 popValue(R0);
138 break;
139 }
140 default:
141 MOZ_ASSUME_UNREACHABLE("Invalid uses");
142 }
143 }
144
145 #ifdef DEBUG
146 void
147 FrameInfo::assertValidState(const BytecodeInfo &info)
148 {
149 // Check stack depth.
150 JS_ASSERT(stackDepth() == info.stackDepth);
151
152 // Start at the bottom, find the first value that's not synced.
153 uint32_t i = 0;
154 for (; i < stackDepth(); i++) {
155 if (stack[i].kind() != StackValue::Stack)
156 break;
157 }
158
159 // Assert all values on top of it are also not synced.
160 for (; i < stackDepth(); i++)
161 JS_ASSERT(stack[i].kind() != StackValue::Stack);
162
163 // Assert every Value register is used by at most one StackValue.
164 // R2 is used as scratch register by the compiler and FrameInfo,
165 // so it shouldn't be used for StackValues.
166 bool usedR0 = false, usedR1 = false;
167
168 for (i = 0; i < stackDepth(); i++) {
169 if (stack[i].kind() == StackValue::Register) {
170 ValueOperand reg = stack[i].reg();
171 if (reg == R0) {
172 JS_ASSERT(!usedR0);
173 usedR0 = true;
174 } else if (reg == R1) {
175 JS_ASSERT(!usedR1);
176 usedR1 = true;
177 } else {
178 MOZ_ASSUME_UNREACHABLE("Invalid register");
179 }
180 }
181 }
182 }
183 #endif

mercurial