OLD | NEW |
1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 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 18 matching lines...) Expand all Loading... |
29 | 29 |
30 #include "codegen-inl.h" | 30 #include "codegen-inl.h" |
31 #include "register-allocator-inl.h" | 31 #include "register-allocator-inl.h" |
32 #include "scopes.h" | 32 #include "scopes.h" |
33 | 33 |
34 namespace v8 { namespace internal { | 34 namespace v8 { namespace internal { |
35 | 35 |
36 // ------------------------------------------------------------------------- | 36 // ------------------------------------------------------------------------- |
37 // VirtualFrame implementation. | 37 // VirtualFrame implementation. |
38 | 38 |
39 #define __ ACCESS_MASM(masm_) | 39 #define __ ACCESS_MASM(masm()) |
40 | 40 |
41 | 41 |
42 // On entry to a function, the virtual frame already contains the | 42 // On entry to a function, the virtual frame already contains the |
43 // receiver and the parameters. All initial frame elements are in | 43 // receiver and the parameters. All initial frame elements are in |
44 // memory. | 44 // memory. |
45 VirtualFrame::VirtualFrame(CodeGenerator* cgen) | 45 VirtualFrame::VirtualFrame() |
46 : cgen_(cgen), | 46 : elements_(parameter_count() + local_count() + kPreallocatedElements), |
47 masm_(cgen->masm()), | 47 stack_pointer_(parameter_count()) { // 0-based index of TOS. |
48 elements_(cgen->scope()->num_parameters() | 48 for (int i = 0; i <= stack_pointer_; i++) { |
49 + cgen->scope()->num_stack_slots() | |
50 + kPreallocatedElements), | |
51 parameter_count_(cgen->scope()->num_parameters()), | |
52 local_count_(0), | |
53 stack_pointer_(parameter_count_), // 0-based index of TOS. | |
54 frame_pointer_(kIllegalIndex) { | |
55 for (int i = 0; i < parameter_count_ + 1; i++) { | |
56 elements_.Add(FrameElement::MemoryElement()); | 49 elements_.Add(FrameElement::MemoryElement()); |
57 } | 50 } |
58 for (int i = 0; i < kNumRegisters; i++) { | 51 for (int i = 0; i < kNumRegisters; i++) { |
59 register_locations_[i] = kIllegalIndex; | 52 register_locations_[i] = kIllegalIndex; |
60 } | 53 } |
61 } | 54 } |
62 | 55 |
63 | 56 |
64 void VirtualFrame::SyncElementBelowStackPointer(int index) { | 57 void VirtualFrame::SyncElementBelowStackPointer(int index) { |
65 UNREACHABLE(); | 58 UNREACHABLE(); |
66 } | 59 } |
67 | 60 |
68 | 61 |
69 void VirtualFrame::SyncElementByPushing(int index) { | 62 void VirtualFrame::SyncElementByPushing(int index) { |
70 UNREACHABLE(); | 63 UNREACHABLE(); |
71 } | 64 } |
72 | 65 |
73 | 66 |
74 void VirtualFrame::SyncRange(int begin, int end) { | 67 void VirtualFrame::SyncRange(int begin, int end) { |
75 // All elements are in memory on ARM (ie, synced). | 68 // All elements are in memory on ARM (ie, synced). |
76 #ifdef DEBUG | 69 #ifdef DEBUG |
77 for (int i = begin; i <= end; i++) { | 70 for (int i = begin; i <= end; i++) { |
78 ASSERT(elements_[i].is_synced()); | 71 ASSERT(elements_[i].is_synced()); |
79 } | 72 } |
80 #endif | 73 #endif |
81 } | 74 } |
82 | 75 |
83 | 76 |
84 void VirtualFrame::MergeTo(VirtualFrame* expected) { | 77 void VirtualFrame::MergeTo(VirtualFrame* expected) { |
85 Comment cmnt(masm_, "[ Merge frame"); | 78 Comment cmnt(masm(), "[ Merge frame"); |
86 // We should always be merging the code generator's current frame to an | 79 // We should always be merging the code generator's current frame to an |
87 // expected frame. | 80 // expected frame. |
88 ASSERT(cgen_->frame() == this); | 81 ASSERT(cgen()->frame() == this); |
89 | 82 |
90 // Adjust the stack pointer upward (toward the top of the virtual | 83 // Adjust the stack pointer upward (toward the top of the virtual |
91 // frame) if necessary. | 84 // frame) if necessary. |
92 if (stack_pointer_ < expected->stack_pointer_) { | 85 if (stack_pointer_ < expected->stack_pointer_) { |
93 int difference = expected->stack_pointer_ - stack_pointer_; | 86 int difference = expected->stack_pointer_ - stack_pointer_; |
94 stack_pointer_ = expected->stack_pointer_; | 87 stack_pointer_ = expected->stack_pointer_; |
95 __ sub(sp, sp, Operand(difference * kPointerSize)); | 88 __ sub(sp, sp, Operand(difference * kPointerSize)); |
96 } | 89 } |
97 | 90 |
98 MergeMoveRegistersToMemory(expected); | 91 MergeMoveRegistersToMemory(expected); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
145 | 138 |
146 void VirtualFrame::MergeMoveRegistersToRegisters(VirtualFrame* expected) { | 139 void VirtualFrame::MergeMoveRegistersToRegisters(VirtualFrame* expected) { |
147 } | 140 } |
148 | 141 |
149 | 142 |
150 void VirtualFrame::MergeMoveMemoryToRegisters(VirtualFrame* expected) { | 143 void VirtualFrame::MergeMoveMemoryToRegisters(VirtualFrame* expected) { |
151 } | 144 } |
152 | 145 |
153 | 146 |
154 void VirtualFrame::Enter() { | 147 void VirtualFrame::Enter() { |
155 Comment cmnt(masm_, "[ Enter JS frame"); | 148 Comment cmnt(masm(), "[ Enter JS frame"); |
156 | 149 |
157 #ifdef DEBUG | 150 #ifdef DEBUG |
158 // Verify that r1 contains a JS function. The following code relies | 151 // Verify that r1 contains a JS function. The following code relies |
159 // on r2 being available for use. | 152 // on r2 being available for use. |
160 { Label map_check, done; | 153 { Label map_check, done; |
161 __ tst(r1, Operand(kSmiTagMask)); | 154 __ tst(r1, Operand(kSmiTagMask)); |
162 __ b(ne, &map_check); | 155 __ b(ne, &map_check); |
163 __ stop("VirtualFrame::Enter - r1 is not a function (smi check)."); | 156 __ stop("VirtualFrame::Enter - r1 is not a function (smi check)."); |
164 __ bind(&map_check); | 157 __ bind(&map_check); |
165 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset)); | 158 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset)); |
166 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset)); | 159 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset)); |
167 __ cmp(r2, Operand(JS_FUNCTION_TYPE)); | 160 __ cmp(r2, Operand(JS_FUNCTION_TYPE)); |
168 __ b(eq, &done); | 161 __ b(eq, &done); |
169 __ stop("VirtualFrame::Enter - r1 is not a function (map check)."); | 162 __ stop("VirtualFrame::Enter - r1 is not a function (map check)."); |
170 __ bind(&done); | 163 __ bind(&done); |
171 } | 164 } |
172 #endif // DEBUG | 165 #endif // DEBUG |
173 | 166 |
174 // We are about to push four values to the frame. | 167 // We are about to push four values to the frame. |
175 Adjust(4); | 168 Adjust(4); |
176 __ stm(db_w, sp, r1.bit() | cp.bit() | fp.bit() | lr.bit()); | 169 __ stm(db_w, sp, r1.bit() | cp.bit() | fp.bit() | lr.bit()); |
177 // Adjust FP to point to saved FP. | 170 // Adjust FP to point to saved FP. |
178 frame_pointer_ = elements_.length() - 2; | |
179 __ add(fp, sp, Operand(2 * kPointerSize)); | 171 __ add(fp, sp, Operand(2 * kPointerSize)); |
180 cgen_->allocator()->Unuse(r1); | 172 cgen()->allocator()->Unuse(r1); |
181 cgen_->allocator()->Unuse(lr); | 173 cgen()->allocator()->Unuse(lr); |
182 } | 174 } |
183 | 175 |
184 | 176 |
185 void VirtualFrame::Exit() { | 177 void VirtualFrame::Exit() { |
186 Comment cmnt(masm_, "[ Exit JS frame"); | 178 Comment cmnt(masm(), "[ Exit JS frame"); |
187 // Drop the execution stack down to the frame pointer and restore the caller | 179 // Drop the execution stack down to the frame pointer and restore the caller |
188 // frame pointer and return address. | 180 // frame pointer and return address. |
189 __ mov(sp, fp); | 181 __ mov(sp, fp); |
190 __ ldm(ia_w, sp, fp.bit() | lr.bit()); | 182 __ ldm(ia_w, sp, fp.bit() | lr.bit()); |
191 } | 183 } |
192 | 184 |
193 | 185 |
194 void VirtualFrame::AllocateStackSlots(int count) { | 186 void VirtualFrame::AllocateStackSlots() { |
195 ASSERT(height() == 0); | 187 ASSERT(height() == 0); |
196 local_count_ = count; | 188 int count = local_count(); |
197 Adjust(count); | |
198 if (count > 0) { | 189 if (count > 0) { |
199 Comment cmnt(masm_, "[ Allocate space for locals"); | 190 Comment cmnt(masm(), "[ Allocate space for locals"); |
| 191 Adjust(count); |
200 // Initialize stack slots with 'undefined' value. | 192 // Initialize stack slots with 'undefined' value. |
201 __ mov(ip, Operand(Factory::undefined_value())); | 193 __ mov(ip, Operand(Factory::undefined_value())); |
202 for (int i = 0; i < count; i++) { | 194 for (int i = 0; i < count; i++) { |
203 __ push(ip); | 195 __ push(ip); |
204 } | 196 } |
205 } | 197 } |
206 } | 198 } |
207 | 199 |
208 | 200 |
209 void VirtualFrame::SaveContextRegister() { | 201 void VirtualFrame::SaveContextRegister() { |
(...skipping 29 matching lines...) Expand all Loading... |
239 | 231 |
240 void VirtualFrame::PushTryHandler(HandlerType type) { | 232 void VirtualFrame::PushTryHandler(HandlerType type) { |
241 // Grow the expression stack by handler size less one (the return address | 233 // Grow the expression stack by handler size less one (the return address |
242 // is already pushed by a call instruction). | 234 // is already pushed by a call instruction). |
243 Adjust(kHandlerSize - 1); | 235 Adjust(kHandlerSize - 1); |
244 __ PushTryHandler(IN_JAVASCRIPT, type); | 236 __ PushTryHandler(IN_JAVASCRIPT, type); |
245 } | 237 } |
246 | 238 |
247 | 239 |
248 Result VirtualFrame::RawCallStub(CodeStub* stub) { | 240 Result VirtualFrame::RawCallStub(CodeStub* stub) { |
249 ASSERT(cgen_->HasValidEntryRegisters()); | 241 ASSERT(cgen()->HasValidEntryRegisters()); |
250 __ CallStub(stub); | 242 __ CallStub(stub); |
251 Result result = cgen_->allocator()->Allocate(r0); | 243 Result result = cgen()->allocator()->Allocate(r0); |
252 ASSERT(result.is_valid()); | 244 ASSERT(result.is_valid()); |
253 return result; | 245 return result; |
254 } | 246 } |
255 | 247 |
256 | 248 |
257 Result VirtualFrame::CallStub(CodeStub* stub, Result* arg) { | 249 Result VirtualFrame::CallStub(CodeStub* stub, Result* arg) { |
258 PrepareForCall(0, 0); | 250 PrepareForCall(0, 0); |
259 arg->Unuse(); | 251 arg->Unuse(); |
260 return RawCallStub(stub); | 252 return RawCallStub(stub); |
261 } | 253 } |
262 | 254 |
263 | 255 |
264 Result VirtualFrame::CallStub(CodeStub* stub, Result* arg0, Result* arg1) { | 256 Result VirtualFrame::CallStub(CodeStub* stub, Result* arg0, Result* arg1) { |
265 PrepareForCall(0, 0); | 257 PrepareForCall(0, 0); |
266 arg0->Unuse(); | 258 arg0->Unuse(); |
267 arg1->Unuse(); | 259 arg1->Unuse(); |
268 return RawCallStub(stub); | 260 return RawCallStub(stub); |
269 } | 261 } |
270 | 262 |
271 | 263 |
272 Result VirtualFrame::CallRuntime(Runtime::Function* f, int arg_count) { | 264 Result VirtualFrame::CallRuntime(Runtime::Function* f, int arg_count) { |
273 PrepareForCall(arg_count, arg_count); | 265 PrepareForCall(arg_count, arg_count); |
274 ASSERT(cgen_->HasValidEntryRegisters()); | 266 ASSERT(cgen()->HasValidEntryRegisters()); |
275 __ CallRuntime(f, arg_count); | 267 __ CallRuntime(f, arg_count); |
276 Result result = cgen_->allocator()->Allocate(r0); | 268 Result result = cgen()->allocator()->Allocate(r0); |
277 ASSERT(result.is_valid()); | 269 ASSERT(result.is_valid()); |
278 return result; | 270 return result; |
279 } | 271 } |
280 | 272 |
281 | 273 |
282 Result VirtualFrame::CallRuntime(Runtime::FunctionId id, int arg_count) { | 274 Result VirtualFrame::CallRuntime(Runtime::FunctionId id, int arg_count) { |
283 PrepareForCall(arg_count, arg_count); | 275 PrepareForCall(arg_count, arg_count); |
284 ASSERT(cgen_->HasValidEntryRegisters()); | 276 ASSERT(cgen()->HasValidEntryRegisters()); |
285 __ CallRuntime(id, arg_count); | 277 __ CallRuntime(id, arg_count); |
286 Result result = cgen_->allocator()->Allocate(r0); | 278 Result result = cgen()->allocator()->Allocate(r0); |
287 ASSERT(result.is_valid()); | 279 ASSERT(result.is_valid()); |
288 return result; | 280 return result; |
289 } | 281 } |
290 | 282 |
291 | 283 |
292 Result VirtualFrame::InvokeBuiltin(Builtins::JavaScript id, | 284 Result VirtualFrame::InvokeBuiltin(Builtins::JavaScript id, |
293 InvokeJSFlags flags, | 285 InvokeJSFlags flags, |
294 Result* arg_count_register, | 286 Result* arg_count_register, |
295 int arg_count) { | 287 int arg_count) { |
296 ASSERT(arg_count_register->reg().is(r0)); | 288 ASSERT(arg_count_register->reg().is(r0)); |
297 PrepareForCall(arg_count, arg_count); | 289 PrepareForCall(arg_count, arg_count); |
298 arg_count_register->Unuse(); | 290 arg_count_register->Unuse(); |
299 __ InvokeBuiltin(id, flags); | 291 __ InvokeBuiltin(id, flags); |
300 Result result = cgen_->allocator()->Allocate(r0); | 292 Result result = cgen()->allocator()->Allocate(r0); |
301 return result; | 293 return result; |
302 } | 294 } |
303 | 295 |
304 | 296 |
305 Result VirtualFrame::RawCallCodeObject(Handle<Code> code, | 297 Result VirtualFrame::RawCallCodeObject(Handle<Code> code, |
306 RelocInfo::Mode rmode) { | 298 RelocInfo::Mode rmode) { |
307 ASSERT(cgen_->HasValidEntryRegisters()); | 299 ASSERT(cgen()->HasValidEntryRegisters()); |
308 __ Call(code, rmode); | 300 __ Call(code, rmode); |
309 Result result = cgen_->allocator()->Allocate(r0); | 301 Result result = cgen()->allocator()->Allocate(r0); |
310 ASSERT(result.is_valid()); | 302 ASSERT(result.is_valid()); |
311 return result; | 303 return result; |
312 } | 304 } |
313 | 305 |
314 | 306 |
315 Result VirtualFrame::CallCodeObject(Handle<Code> code, | 307 Result VirtualFrame::CallCodeObject(Handle<Code> code, |
316 RelocInfo::Mode rmode, | 308 RelocInfo::Mode rmode, |
317 int dropped_args) { | 309 int dropped_args) { |
318 int spilled_args = 0; | 310 int spilled_args = 0; |
319 switch (code->kind()) { | 311 switch (code->kind()) { |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
438 ASSERT(stack_pointer_ == elements_.length() - 1); | 430 ASSERT(stack_pointer_ == elements_.length() - 1); |
439 elements_.Add(FrameElement::MemoryElement()); | 431 elements_.Add(FrameElement::MemoryElement()); |
440 stack_pointer_++; | 432 stack_pointer_++; |
441 __ push(reg); | 433 __ push(reg); |
442 } | 434 } |
443 | 435 |
444 | 436 |
445 #undef __ | 437 #undef __ |
446 | 438 |
447 } } // namespace v8::internal | 439 } } // namespace v8::internal |
OLD | NEW |