Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(626)

Side by Side Diff: src/virtual-frame-ia32.cc

Issue 11232: First step toward allowing constants to appear in the virtual frame... (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/toiger/
Patch Set: '' Created 12 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« src/virtual-frame-ia32.h ('K') | « src/virtual-frame-ia32.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2008 the V8 project authors. All rights reserved. 1 // Copyright 2008 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 15 matching lines...) Expand all
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 #include "v8.h" 28 #include "v8.h"
29 29
30 #include "codegen.h" 30 #include "codegen.h"
31 #include "codegen-inl.h" 31 #include "codegen-inl.h"
32 #include "virtual-frame.h" 32 #include "virtual-frame.h"
33 33
34 namespace v8 { namespace internal { 34 namespace v8 { namespace internal {
35 35
36 #define __ masm_->
37
36 // ------------------------------------------------------------------------- 38 // -------------------------------------------------------------------------
37 // VirtualFrame implementation. 39 // VirtualFrame implementation.
38 40
39 #define __ masm_-> 41 // On entry to a function, the virtual frame already contains the receiver,
40 42 // the parameters, and a return address. All frame elements are in memory.
41 VirtualFrame::VirtualFrame(CodeGenerator* cgen) 43 VirtualFrame::VirtualFrame(CodeGenerator* cgen)
42 : masm_(cgen->masm()), 44 : masm_(cgen->masm()),
43 elements_(0), 45 elements_(0),
44 parameter_count_(cgen->scope()->num_parameters()), 46 parameter_count_(cgen->scope()->num_parameters()),
45 local_count_(0), 47 local_count_(0),
46 frame_pointer_(-1) { 48 stack_pointer_(parameter_count_ + 1), // 0-based index of TOS.
47 // The virtual frame contains a receiver, the parameters, and a return 49 frame_pointer_(kIllegalIndex) {
William Hesse 2008/11/18 16:37:34 In this case, is IllegalIndex actually the accurat
Kevin Millikin (Chromium) 2008/11/18 19:12:06 We don't know what the frame pointer is until we s
48 // address (all in memory) when it is created. 50 for (int i = 0; i < parameter_count_ + 2; i++) {
49 Adjust(parameter_count_ + 2); 51 elements_.Add(FrameElement());
52 }
50 } 53 }
51 54
52 55
56 // When cloned, a frame is a deep copy of the original.
William Hesse 2008/11/18 16:37:34 How deep? Are heap objects cloned?
53 VirtualFrame::VirtualFrame(VirtualFrame* original) 57 VirtualFrame::VirtualFrame(VirtualFrame* original)
54 : masm_(original->masm_), 58 : masm_(original->masm_),
55 elements_(original->elements_.length()), 59 elements_(original->elements_.length()),
56 parameter_count_(original->parameter_count_), 60 parameter_count_(original->parameter_count_),
57 local_count_(original->local_count_), 61 local_count_(original->local_count_),
62 stack_pointer_(original->stack_pointer_),
58 frame_pointer_(original->frame_pointer_) { 63 frame_pointer_(original->frame_pointer_) {
59 // Copy all the elements. 64 // Copy all the elements from the original.
60 for (int i = 0; i < original->elements_.length(); i++) { 65 for (int i = 0; i < original->elements_.length(); i++) {
61 elements_.Add(original->elements_[i]); 66 elements_.Add(original->elements_[i]);
62 } 67 }
63 } 68 }
64 69
65 70
71 // Modify the state of the virtual frame to match the actual frame by adding
72 // extra in-memory elements to the top of the virtual frame. The extra
73 // elements will be externally materialized on the actual frame (eg, by
74 // pushing an exception handler). No code is emitted.
66 void VirtualFrame::Adjust(int count) { 75 void VirtualFrame::Adjust(int count) {
67 ASSERT(count >= 0); 76 ASSERT(count >= 0);
77 ASSERT(stack_pointer_ == elements_.length() - 1);
William Hesse 2008/11/18 16:37:34 Isn't this too strong a precondition for a useful
Kevin Millikin (Chromium) 2008/11/18 19:12:06 I think it's right. The intent of "Adjust" is tha
78
68 for (int i = 0; i < count; i++) { 79 for (int i = 0; i < count; i++) {
69 elements_.Add(Element()); 80 elements_.Add(FrameElement());
81 }
82 stack_pointer_ += count;
83 }
84
85
86 // Modify the state of the virtual frame to match the actual frame by
87 // removing elements from the top of the virtual frame. The elements will
88 // be externally popped from the actual frame (eg, by a runtime call). No
89 // code is emitted.
90 void VirtualFrame::Forget(int count) {
91 ASSERT(count >= 0);
92 ASSERT(stack_pointer_ == elements_.length() - 1);
93 ASSERT(elements_.length() >= count);
94
95 stack_pointer_ -= count;
96 for (int i = 0; i < count; i++) {
97 elements_.RemoveLast();
70 } 98 }
71 } 99 }
72 100
73 101
74 void VirtualFrame::Forget(int count) { 102 void VirtualFrame::SpillAll() {
75 ASSERT(count >= 0); 103 int i = 0;
76 ASSERT(elements_.length() >= count); 104
77 for (int i = 0; i < count; i++) { 105 // Spill dirty constants below the stack pointer.
78 elements_.RemoveLast(); 106 for (; i <= stack_pointer_; i++) {
107 if (elements_[i].type() == FrameElement::CONSTANT &&
108 elements_[i].is_dirty()) {
109 __ mov(Operand(ebp, fp_relative(i)), Immediate(elements_[i].handle()));
William Hesse 2008/11/18 16:37:34 Is the splitting into two 16-bit quantities inside
Kevin Millikin (Chromium) 2008/11/18 19:12:06 There is no splitting here (yet). The only consta
110 elements_[i] = FrameElement(); // The element is now in memory.
111 }
79 } 112 }
113
114 // Spill all constants above the stack pointer.
115 for (; i < elements_.length(); i++) {
116 ASSERT(elements_[i].type() == FrameElement::CONSTANT);
117 ASSERT(elements_[i].is_dirty());
118 stack_pointer_++;
119 __ push(Immediate(elements_[i].handle()));
120 elements_[i] = FrameElement(); // The element is now in memory.
121 }
122 }
123
124
125 void VirtualFrame::PrepareCall(int frame_arg_count) {
126 ASSERT(height() >= frame_arg_count);
127
128 // The only non-memory elements of the frame are constants. Push all of
129 // them above the stack pointer to allocate space for them and to ensure
130 // the arguments are flushed to memory.
131 for (int i = stack_pointer_ + 1; i < elements_.length(); i++) {
132 ASSERT(elements_[i].type() == FrameElement::CONSTANT);
133 ASSERT(elements_[i].is_dirty());
134 stack_pointer_++;
135 elements_[i].clear_dirty();
136 __ push(Immediate(elements_[i].handle()));
137 }
138
139 // Forget the ones that will be popped by the call.
140 Forget(frame_arg_count);
141 }
142
143
144 void VirtualFrame::EnsureMergable() {
145 // We cannot merge to a frame that has constants as elements, because an
146 // arbitrary frame may not have constants in those locations.
147 SpillAll();
80 } 148 }
81 149
82 150
83 void VirtualFrame::MergeTo(VirtualFrame* expected) { 151 void VirtualFrame::MergeTo(VirtualFrame* expected) {
84 ASSERT(masm_ == expected->masm_); 152 ASSERT(masm_ == expected->masm_);
85 ASSERT(elements_.length() == expected->elements_.length()); 153 ASSERT(elements_.length() == expected->elements_.length());
86 ASSERT(parameter_count_ == expected->parameter_count_); 154 ASSERT(parameter_count_ == expected->parameter_count_);
87 ASSERT(local_count_ == expected->local_count_); 155 ASSERT(local_count_ == expected->local_count_);
88 ASSERT(frame_pointer_ == expected->frame_pointer_); 156 ASSERT(frame_pointer_ == expected->frame_pointer_);
89 for (int i = 0; i < elements_.length(); i++) { 157
90 ASSERT(elements_[i].matches(expected->elements_[i])); 158 // The expected frame is one we can merge to (ie, currently that means
91 } 159 // that all elements are in memory). The only thing we need to do to
160 // merge is make this one mergable too.
161 SpillAll();
162
163 ASSERT(stack_pointer_ == expected->stack_pointer_);
92 } 164 }
93 165
94 166
95 void VirtualFrame::Enter() { 167 void VirtualFrame::Enter() {
96 Comment cmnt(masm_, "[ Enter JS frame"); 168 Comment cmnt(masm_, "[ Enter JS frame");
97 Adjust(1); 169 EmitPush(ebp);
98 __ push(ebp);
99 170
100 frame_pointer_ = elements_.length() - 1; 171 frame_pointer_ = stack_pointer_;
101 __ mov(ebp, Operand(esp)); 172 __ mov(ebp, Operand(esp));
102 173
103 // Store the context and the function in the frame. 174 // Store the context and the function in the frame.
104 Adjust(2); 175 EmitPush(esi);
105 __ push(esi); 176 EmitPush(edi);
106 __ push(edi);
107 177
108 // Clear the function slot when generating debug code. 178 // Clear the function slot when generating debug code.
109 if (FLAG_debug_code) { 179 if (FLAG_debug_code) {
110 __ Set(edi, Immediate(reinterpret_cast<int>(kZapValue))); 180 __ Set(edi, Immediate(reinterpret_cast<int>(kZapValue)));
111 } 181 }
112 } 182 }
113 183
114 184
115 void VirtualFrame::Exit() { 185 void VirtualFrame::Exit() {
116 Comment cmnt(masm_, "[ Exit JS frame"); 186 Comment cmnt(masm_, "[ Exit JS frame");
117 // Record the location of the JS exit code for patching when setting 187 // Record the location of the JS exit code for patching when setting
118 // break point. 188 // break point.
119 __ RecordJSReturn(); 189 __ RecordJSReturn();
120 190
121 // Avoid using the leave instruction here, because it is too 191 // Avoid using the leave instruction here, because it is too
122 // short. We need the return sequence to be a least the size of a 192 // short. We need the return sequence to be a least the size of a
123 // call instruction to support patching the exit code in the 193 // call instruction to support patching the exit code in the
124 // debugger. See VisitReturnStatement for the full return sequence. 194 // debugger. See VisitReturnStatement for the full return sequence.
125 __ mov(esp, Operand(ebp)); 195 __ mov(esp, Operand(ebp));
126 __ pop(ebp); 196 stack_pointer_ = frame_pointer_;
197 for (int i = elements_.length() - 1; i > stack_pointer_; i--) {
198 elements_.RemoveLast();
199 }
200
201 frame_pointer_ = kIllegalIndex;
202 EmitPop(ebp);
127 } 203 }
128 204
129 205
130 void VirtualFrame::AllocateStackSlots(int count) { 206 void VirtualFrame::AllocateStackSlots(int count) {
131 ASSERT(height() == 0); 207 ASSERT(height() == 0);
132 local_count_ = count; 208 local_count_ = count;
133 Adjust(count); 209 for (int i = 0; i < count; i++) {
134 if (count > 0) { 210 elements_.Add(FrameElement(Factory::undefined_value()));
135 Comment cmnt(masm_, "[ Allocate space for locals");
136 __ Set(eax, Immediate(Factory::undefined_value()));
137 for (int i = 0; i < count; i++) {
138 __ push(eax);
139 }
140 } 211 }
141 } 212 }
142 213
143 214
144 void VirtualFrame::PushTryHandler(HandlerType type) { 215 void VirtualFrame::PushTryHandler(HandlerType type) {
145 // Grow the expression stack by handler size less two (the return address 216 // Grow the expression stack by handler size less two (the return address
146 // is already pushed by a call instruction, and PushTryHandler from the 217 // is already pushed by a call instruction, and PushTryHandler from the
147 // macro assembler will leave the top of stack in the eax register to be 218 // macro assembler will leave the top of stack in the eax register to be
148 // pushed separately). 219 // pushed separately).
149 Adjust(kHandlerSize - 2); 220 Adjust(kHandlerSize - 2);
150 __ PushTryHandler(IN_JAVASCRIPT, type); 221 __ PushTryHandler(IN_JAVASCRIPT, type);
151 // TODO(1222589): remove the reliance of PushTryHandler on a cached TOS 222 // TODO(1222589): remove the reliance of PushTryHandler on a cached TOS
152 EmitPush(eax); 223 EmitPush(eax);
153 } 224 }
154 225
155 226
156 void VirtualFrame::CallStub(CodeStub* stub, int frame_arg_count) { 227 void VirtualFrame::CallStub(CodeStub* stub, int frame_arg_count) {
157 ASSERT(height() >= frame_arg_count); 228 PrepareCall(frame_arg_count);
158 Forget(frame_arg_count);
159 __ CallStub(stub); 229 __ CallStub(stub);
160 } 230 }
161 231
162 232
163 void VirtualFrame::CallRuntime(Runtime::Function* f, int frame_arg_count) { 233 void VirtualFrame::CallRuntime(Runtime::Function* f, int frame_arg_count) {
164 ASSERT(height() >= frame_arg_count); 234 PrepareCall(frame_arg_count);
165 Forget(frame_arg_count);
166 __ CallRuntime(f, frame_arg_count); 235 __ CallRuntime(f, frame_arg_count);
167 } 236 }
168 237
169 238
170 void VirtualFrame::CallRuntime(Runtime::FunctionId id, int frame_arg_count) { 239 void VirtualFrame::CallRuntime(Runtime::FunctionId id, int frame_arg_count) {
171 ASSERT(height() >= frame_arg_count); 240 PrepareCall(frame_arg_count);
172 Forget(frame_arg_count);
173 __ CallRuntime(id, frame_arg_count); 241 __ CallRuntime(id, frame_arg_count);
174 } 242 }
175 243
176 244
177 void VirtualFrame::InvokeBuiltin(Builtins::JavaScript id, 245 void VirtualFrame::InvokeBuiltin(Builtins::JavaScript id,
178 InvokeFlag flag, 246 InvokeFlag flag,
179 int frame_arg_count) { 247 int frame_arg_count) {
180 ASSERT(height() >= frame_arg_count); 248 PrepareCall(frame_arg_count);
181 Forget(frame_arg_count);
182 __ InvokeBuiltin(id, flag); 249 __ InvokeBuiltin(id, flag);
183 } 250 }
184 251
185 252
186 void VirtualFrame::CallCodeObject(Handle<Code> code, 253 void VirtualFrame::CallCodeObject(Handle<Code> code,
187 RelocInfo::Mode rmode, 254 RelocInfo::Mode rmode,
188 int frame_arg_count) { 255 int frame_arg_count) {
189 ASSERT(height() >= frame_arg_count); 256 PrepareCall(frame_arg_count);
190 Forget(frame_arg_count);
191 __ call(code, rmode); 257 __ call(code, rmode);
192 } 258 }
193 259
194 260
195 void VirtualFrame::Drop(int count) { 261 void VirtualFrame::Drop(int count) {
196 ASSERT(height() >= count); 262 ASSERT(height() >= count);
263
264 // Discard elements above the stack pointer.
265 while (count > 0 && stack_pointer_ < elements_.length() - 1) {
266 elements_.RemoveLast();
267 }
268
269 // Discard the rest of the elements and lower the stack pointer.
197 Forget(count); 270 Forget(count);
198 if (count > 0) { 271 if (count > 0) {
199 __ add(Operand(esp), Immediate(count * kPointerSize)); 272 __ add(Operand(esp), Immediate(count * kPointerSize));
200 } 273 }
201 } 274 }
202 275
203 276
204 void VirtualFrame::Drop() { Drop(1); } 277 void VirtualFrame::Drop() { Drop(1); }
205 278
206 279
207 void VirtualFrame::Pop(Register reg) { 280 void VirtualFrame::EmitPop(Register reg) {
208 Forget(1); 281 ASSERT(stack_pointer_ == elements_.length() - 1);
282 stack_pointer_--;
283 elements_.RemoveLast();
209 __ pop(reg); 284 __ pop(reg);
210 } 285 }
211 286
212 287
213 void VirtualFrame::Pop(Operand operand) { 288 void VirtualFrame::EmitPop(Operand operand) {
214 Forget(1); 289 ASSERT(stack_pointer_ == elements_.length() - 1);
290 stack_pointer_--;
291 elements_.RemoveLast();
215 __ pop(operand); 292 __ pop(operand);
216 } 293 }
217 294
218 295
219 void VirtualFrame::EmitPush(Register reg) { 296 void VirtualFrame::EmitPush(Register reg) {
220 Adjust(1); 297 ASSERT(stack_pointer_ == elements_.length() - 1);
298 elements_.Add(FrameElement());
299 stack_pointer_++;
221 __ push(reg); 300 __ push(reg);
222 } 301 }
223 302
224 303
225 void VirtualFrame::EmitPush(Operand operand) { 304 void VirtualFrame::EmitPush(Operand operand) {
226 Adjust(1); 305 ASSERT(stack_pointer_ == elements_.length() - 1);
306 elements_.Add(FrameElement());
307 stack_pointer_++;
227 __ push(operand); 308 __ push(operand);
228 } 309 }
229 310
230 311
231 void VirtualFrame::EmitPush(Immediate immediate) { 312 void VirtualFrame::EmitPush(Immediate immediate) {
232 Adjust(1); 313 ASSERT(stack_pointer_ == elements_.length() - 1);
314 elements_.Add(FrameElement());
315 stack_pointer_++;
233 __ push(immediate); 316 __ push(immediate);
234 } 317 }
235 318
319
236 #undef __ 320 #undef __
237 321
238 } } // namespace v8::internal 322 } } // namespace v8::internal
OLDNEW
« src/virtual-frame-ia32.h ('K') | « src/virtual-frame-ia32.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698