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

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

Issue 1604002: Simple register allocation for ARM. Only top of expression... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 8 months 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
OLDNEW
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 19 matching lines...) Expand all
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 #include "virtual-frame-inl.h" 33 #include "virtual-frame-inl.h"
34 34
35 namespace v8 { 35 namespace v8 {
36 namespace internal { 36 namespace internal {
37 37
38 #define __ ACCESS_MASM(masm()) 38 #define __ ACCESS_MASM(masm())
39 39
40 void VirtualFrame::SyncElementBelowStackPointer(int index) { 40 void VirtualFrame::PopToR1R0() {
41 UNREACHABLE(); 41 VirtualFrame where_to_go = *this;
42 where_to_go.top_of_stack_state_ = R1_R0_TOS;
43 MergeTo(&where_to_go);
Søren Thygesen Gjesse 2010/04/07 10:46:51 Maybe add a comment here saying the r0/r1 TOS stat
Erik Corry 2010/04/07 12:49:17 Done.
44 element_count_ -= 2;
45 top_of_stack_state_ = NO_TOS_REGISTERS;
42 } 46 }
43 47
44 48
45 void VirtualFrame::SyncElementByPushing(int index) { 49 void VirtualFrame::PopToR1() {
46 UNREACHABLE(); 50 VirtualFrame where_to_go = *this;
51 where_to_go.top_of_stack_state_ = R1_TOS;
52 MergeTo(&where_to_go);
53 element_count_ -= 1;
54 top_of_stack_state_ = NO_TOS_REGISTERS;
55 }
56
57
58 void VirtualFrame::PopToR0() {
59 VirtualFrame where_to_go = *this;
60 where_to_go.top_of_stack_state_ = R0_TOS;
61 MergeTo(&where_to_go);
62 element_count_ -= 1;
63 top_of_stack_state_ = NO_TOS_REGISTERS;
47 } 64 }
48 65
49 66
50 void VirtualFrame::MergeTo(VirtualFrame* expected) { 67 void VirtualFrame::MergeTo(VirtualFrame* expected) {
Kasper Lund 2010/04/07 08:09:50 Do you have good tests of this function? Full cove
Erik Corry 2010/04/07 12:49:17 No. The coverage tool for covering code generated
51 // ARM frames are currently always in memory. 68 if (Equals(expected)) return;
52 ASSERT(Equals(expected)); 69 switch (top_of_stack_state_ * 5 + expected->top_of_stack_state_) {
Søren Thygesen Gjesse 2010/04/07 10:46:51 Maybe add a macro for (one_state * 5 + another_sta
Erik Corry 2010/04/07 12:49:17 On ARM multiplying by 5 should be the same speed a
53 } 70 case NO_TOS_REGISTERS * 5 + NO_TOS_REGISTERS:
54 71 break;
55 72 case NO_TOS_REGISTERS * 5 + R0_TOS:
56 void VirtualFrame::MergeMoveRegistersToMemory(VirtualFrame* expected) { 73 __ pop(r0);
57 UNREACHABLE(); 74 break;
58 } 75 case NO_TOS_REGISTERS * 5 + R1_TOS:
59 76 __ pop(r1);
60 77 break;
61 void VirtualFrame::MergeMoveRegistersToRegisters(VirtualFrame* expected) { 78 case NO_TOS_REGISTERS * 5 + R1_R0_TOS:
62 UNREACHABLE(); 79 __ pop(r0);
63 } 80 __ pop(r1);
64 81 break;
65 82 case NO_TOS_REGISTERS * 5 + R0_R1_TOS:
66 void VirtualFrame::MergeMoveMemoryToRegisters(VirtualFrame* expected) { 83 __ pop(r0);
67 UNREACHABLE(); 84 __ pop(r1);
85 break;
86 case R0_TOS * 5 + NO_TOS_REGISTERS:
87 __ push(r0);
88 break;
89 case R0_TOS * 5 + R0_TOS:
90 break;
91 case R0_TOS * 5 + R1_TOS:
92 __ mov(r1, r0);
93 break;
94 case R0_TOS * 5 + R1_R0_TOS:
95 __ pop(r1);
96 break;
97 case R0_TOS * 5 + R0_R1_TOS:
98 __ mov(r1, r0);
99 __ pop(r0);
100 break;
101 case R1_TOS * 5 + NO_TOS_REGISTERS:
102 __ push(r1);
103 break;
104 case R1_TOS * 5 + R0_TOS:
105 __ mov(r0, r1);
106 break;
107 case R1_TOS * 5 + R1_TOS:
108 break;
109 case R1_TOS * 5 + R1_R0_TOS:
110 __ mov(r0, r1);
111 __ pop(r1);
112 break;
113 case R1_TOS * 5 + R0_R1_TOS:
114 __ pop(r0);
115 break;
116 case R1_R0_TOS * 5 + NO_TOS_REGISTERS:
117 __ push(r1);
118 __ push(r0);
119 break;
120 case R1_R0_TOS * 5 + R0_TOS:
121 __ push(r1);
122 break;
123 case R1_R0_TOS * 5 + R1_TOS:
124 __ push(r1);
125 __ mov(r1, r0);
126 break;
127 case R1_R0_TOS * 5 + R1_R0_TOS:
128 break;
129 case R1_R0_TOS * 5 + R0_R1_TOS:
Søren Thygesen Gjesse 2010/04/07 07:53:37 MacroAssembler::Swap?
Erik Corry 2010/04/07 12:49:17 Done.
130 __ eor(r0, r0, Operand(r1));
131 __ eor(r1, r1, Operand(r0));
132 __ eor(r0, r0, Operand(r1));
133 break;
134 case R0_R1_TOS * 5 + NO_TOS_REGISTERS:
135 __ push(r0);
136 __ push(r1);
137 break;
138 case R0_R1_TOS * 5 + R0_TOS:
139 __ push(r0);
140 __ mov(r0, r1);
141 break;
142 case R0_R1_TOS * 5 + R1_TOS:
143 __ push(r0);
144 break;
145 case R0_R1_TOS * 5 + R1_R0_TOS:
146 __ eor(r0, r0, Operand(r1));
Kasper Lund 2010/04/07 08:09:50 Swap again.
Erik Corry 2010/04/07 12:49:17 Done.
147 __ eor(r1, r1, Operand(r0));
148 __ eor(r0, r0, Operand(r1));
149 break;
150 case R0_R1_TOS * 5 + R0_R1_TOS:
151 break;
Søren Thygesen Gjesse 2010/04/07 10:46:51 default with UNREACHABLE()?
Erik Corry 2010/04/07 12:49:17 Done.
152 }
153 ASSERT(register_allocation_map_ == expected->register_allocation_map_);
68 } 154 }
69 155
70 156
71 void VirtualFrame::Enter() { 157 void VirtualFrame::Enter() {
72 Comment cmnt(masm(), "[ Enter JS frame"); 158 Comment cmnt(masm(), "[ Enter JS frame");
73 159
74 #ifdef DEBUG 160 #ifdef DEBUG
75 // Verify that r1 contains a JS function. The following code relies 161 // Verify that r1 contains a JS function. The following code relies
76 // on r2 being available for use. 162 // on r2 being available for use.
77 if (FLAG_debug_code) { 163 if (FLAG_debug_code) {
78 Label map_check, done; 164 Label map_check, done;
79 __ tst(r1, Operand(kSmiTagMask)); 165 __ tst(r1, Operand(kSmiTagMask));
80 __ b(ne, &map_check); 166 __ b(ne, &map_check);
81 __ stop("VirtualFrame::Enter - r1 is not a function (smi check)."); 167 __ stop("VirtualFrame::Enter - r1 is not a function (smi check).");
82 __ bind(&map_check); 168 __ bind(&map_check);
83 __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE); 169 __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE);
84 __ b(eq, &done); 170 __ b(eq, &done);
85 __ stop("VirtualFrame::Enter - r1 is not a function (map check)."); 171 __ stop("VirtualFrame::Enter - r1 is not a function (map check).");
86 __ bind(&done); 172 __ bind(&done);
87 } 173 }
88 #endif // DEBUG 174 #endif // DEBUG
89 175
90 // We are about to push four values to the frame. 176 // We are about to push four values to the frame.
91 Adjust(4); 177 Adjust(4);
92 __ stm(db_w, sp, r1.bit() | cp.bit() | fp.bit() | lr.bit()); 178 __ stm(db_w, sp, r1.bit() | cp.bit() | fp.bit() | lr.bit());
93 // Adjust FP to point to saved FP. 179 // Adjust FP to point to saved FP.
94 __ add(fp, sp, Operand(2 * kPointerSize)); 180 __ add(fp, sp, Operand(2 * kPointerSize));
95 cgen()->allocator()->Unuse(r1);
96 cgen()->allocator()->Unuse(lr);
97 } 181 }
98 182
99 183
100 void VirtualFrame::Exit() { 184 void VirtualFrame::Exit() {
101 Comment cmnt(masm(), "[ Exit JS frame"); 185 Comment cmnt(masm(), "[ Exit JS frame");
102 // Record the location of the JS exit code for patching when setting 186 // Record the location of the JS exit code for patching when setting
103 // break point. 187 // break point.
104 __ RecordJSReturn(); 188 __ RecordJSReturn();
105 189
106 // Drop the execution stack down to the frame pointer and restore the caller 190 // Drop the execution stack down to the frame pointer and restore the caller
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
145 // Call the stub if lower. 229 // Call the stub if lower.
146 masm()->mov(pc, 230 masm()->mov(pc,
147 Operand(reinterpret_cast<intptr_t>(stub.GetCode().location()), 231 Operand(reinterpret_cast<intptr_t>(stub.GetCode().location()),
148 RelocInfo::CODE_TARGET), 232 RelocInfo::CODE_TARGET),
149 LeaveCC, 233 LeaveCC,
150 lo); 234 lo);
151 } 235 }
152 236
153 237
154 238
155 void VirtualFrame::SaveContextRegister() {
156 UNIMPLEMENTED();
157 }
158
159
160 void VirtualFrame::RestoreContextRegister() {
161 UNIMPLEMENTED();
162 }
163
164
165 void VirtualFrame::PushReceiverSlotAddress() { 239 void VirtualFrame::PushReceiverSlotAddress() {
166 UNIMPLEMENTED(); 240 UNIMPLEMENTED();
167 } 241 }
168 242
169 243
170 int VirtualFrame::InvalidateFrameSlotAt(int index) {
171 UNIMPLEMENTED();
172 return kIllegalIndex;
173 }
174
175
176 void VirtualFrame::TakeFrameSlotAt(int index) {
177 UNIMPLEMENTED();
178 }
179
180
181 void VirtualFrame::StoreToFrameSlotAt(int index) {
182 UNIMPLEMENTED();
183 }
184
185
186 void VirtualFrame::PushTryHandler(HandlerType type) { 244 void VirtualFrame::PushTryHandler(HandlerType type) {
187 // Grow the expression stack by handler size less one (the return 245 // Grow the expression stack by handler size less one (the return
188 // address in lr is already counted by a call instruction). 246 // address in lr is already counted by a call instruction).
189 Adjust(kHandlerSize - 1); 247 Adjust(kHandlerSize - 1);
190 __ PushTryHandler(IN_JAVASCRIPT, type); 248 __ PushTryHandler(IN_JAVASCRIPT, type);
191 } 249 }
192 250
193 251
194 void VirtualFrame::CallRuntime(Runtime::Function* f, int arg_count) { 252 void VirtualFrame::CallRuntime(Runtime::Function* f, int arg_count) {
195 Forget(arg_count); 253 Forget(arg_count);
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
239 break; 297 break;
240 default: 298 default:
241 UNREACHABLE(); 299 UNREACHABLE();
242 break; 300 break;
243 } 301 }
244 Forget(dropped_args); 302 Forget(dropped_args);
245 ASSERT(cgen()->HasValidEntryRegisters()); 303 ASSERT(cgen()->HasValidEntryRegisters());
246 __ Call(code, rmode); 304 __ Call(code, rmode);
247 } 305 }
248 306
249 307
Søren Thygesen Gjesse 2010/04/07 10:46:51 Lining up the states in a comment here could be he
Erik Corry 2010/04/07 12:49:17 Done.
308 const bool VirtualFrame::kR0InUse[TOS_STATES] =
309 { false, true, false, true, true };
310 const bool VirtualFrame::kR1InUse[TOS_STATES] =
311 { false, false, true, true, true };
312 const int VirtualFrame::kVirtualElements[TOS_STATES] = { 0, 1, 1, 2, 2 };
313 const VirtualFrame::TopOfStack VirtualFrame::kPopState[TOS_STATES] =
314 { NO_TOS_REGISTERS, NO_TOS_REGISTERS, NO_TOS_REGISTERS, R0_TOS, R1_TOS };
315 const VirtualFrame::TopOfStack VirtualFrame::kPushState[TOS_STATES] =
316 { R0_TOS, R0_R1_TOS, R1_R0_TOS, R1_R0_TOS, R0_R1_TOS };
317 const Register VirtualFrame::kTopRegister[TOS_STATES] = { r0, r0, r1, r1, r0 };
318 const Register VirtualFrame::kBottomRegister[TOS_STATES] =
319 { r0, r0, r1, r0, r1 };
320 const Register VirtualFrame::kAllocatedRegisters[
321 VirtualFrame::kNumberOfAllocatedRegisters] = { r2, r3, r4, r5, r6 };
322
323
324 bool VirtualFrame::SpilledScope::is_spilled_ = false;
325
326
250 void VirtualFrame::Drop(int count) { 327 void VirtualFrame::Drop(int count) {
251 ASSERT(count >= 0); 328 ASSERT(count >= 0);
252 ASSERT(height() >= count); 329 ASSERT(height() >= count);
253 int num_virtual_elements = (element_count() - 1) - stack_pointer_; 330 // Discard elements from the virtual frame and free any registers.
254 331 int num_virtual_elements = kVirtualElements[top_of_stack_state_];
255 // Emit code to lower the stack pointer if necessary. 332 while (num_virtual_elements > 0) {
256 if (num_virtual_elements < count) { 333 Pop();
257 int num_dropped = count - num_virtual_elements; 334 num_virtual_elements--;
258 stack_pointer_ -= num_dropped; 335 count--;
259 __ add(sp, sp, Operand(num_dropped * kPointerSize)); 336 if (count == 0) return;
260 } 337 }
261 338 if (count == 0) return;
262 // Discard elements from the virtual frame and free any registers. 339 __ add(sp, sp, Operand(count * kPointerSize));
263 element_count_ -= count; 340 element_count_ -= count;
264 } 341 }
265 342
266 343
267 Result VirtualFrame::Pop() { 344 void VirtualFrame::Pop() {
268 UNIMPLEMENTED(); 345 if (top_of_stack_state_ == NO_TOS_REGISTERS) {
269 return Result(); 346 __ add(sp, sp, Operand(kPointerSize));
347 } else {
348 top_of_stack_state_ = kPopState[top_of_stack_state_];
349 }
350 element_count_--;
270 } 351 }
271 352
272 353
273 void VirtualFrame::EmitPop(Register reg) { 354 void VirtualFrame::EmitPop(Register reg) {
274 ASSERT(stack_pointer_ == element_count() - 1); 355 ASSERT(!is_used(reg));
275 stack_pointer_--; 356 if (top_of_stack_state_ == NO_TOS_REGISTERS) {
357 __ pop(reg);
358 } else {
359 __ mov(reg, kTopRegister[top_of_stack_state_]);
360 top_of_stack_state_ = kPopState[top_of_stack_state_];
361 }
276 element_count_--; 362 element_count_--;
277 __ pop(reg); 363 }
364
365
366 Register VirtualFrame::Peek() {
367 AssertIsNotSpilled();
368 if (top_of_stack_state_ == NO_TOS_REGISTERS) {
369 top_of_stack_state_ = kPushState[top_of_stack_state_];
370 Register answer = kTopRegister[top_of_stack_state_];
371 __ pop(answer);
372 return answer;
373 } else {
374 return kTopRegister[top_of_stack_state_];
375 }
376 }
377
378
379 Register VirtualFrame::PopToRegister(Register but_not_to_this_one) {
Søren Thygesen Gjesse 2010/04/07 10:46:51 Maybe assert that but_not_to_this_one is one of th
Erik Corry 2010/04/07 12:49:17 Done.
380 AssertIsNotSpilled();
381 element_count_--;
382 if (top_of_stack_state_ == NO_TOS_REGISTERS) {
383 if (but_not_to_this_one.is(r0)) {
384 __ pop(r1);
385 return r1;
386 } else {
387 __ pop(r0);
388 return r0;
389 }
390 } else {
Søren Thygesen Gjesse 2010/04/07 10:46:51 Isn't but_not_to_this_one ignored in the else part
Erik Corry 2010/04/07 12:49:17 Yes, because it never happens.
391 Register answer = kTopRegister[top_of_stack_state_];
392 top_of_stack_state_ = kPopState[top_of_stack_state_];
Søren Thygesen Gjesse 2010/04/07 10:46:51 ASSERT(!answer.is(but_not_to_this_one));
Erik Corry 2010/04/07 12:49:17 Done.
393 return answer;
394 }
278 } 395 }
279 396
280 397
281 void VirtualFrame::EmitPush(Register reg) { 398 void VirtualFrame::EmitPush(Register reg) {
282 ASSERT(stack_pointer_ == element_count() - 1);
283 element_count_++; 399 element_count_++;
284 stack_pointer_++; 400 if (SpilledScope::is_spilled()) {
285 __ push(reg); 401 __ push(reg);
402 return;
403 }
404 if (top_of_stack_state_ == NO_TOS_REGISTERS) {
405 if (reg.is(r0)) {
406 top_of_stack_state_ = R0_TOS;
407 return;
408 }
409 if (reg.is(r1)) {
410 top_of_stack_state_ = R1_TOS;
411 return;
412 }
413 }
Søren Thygesen Gjesse 2010/04/07 10:46:51 Maybe add some kind of helper function "EnsureOneF
Erik Corry 2010/04/07 12:49:17 Done.
414 if (kVirtualElements[top_of_stack_state_] == kMaxTOSRegisters) {
415 __ push(kBottomRegister[top_of_stack_state_]);
416 }
417 top_of_stack_state_ = kPushState[top_of_stack_state_];
418 Register dest = kTopRegister[top_of_stack_state_];
419 if (!dest.is(reg)) {
420 __ mov(dest, reg);
421 }
422 }
423
424
425 Register VirtualFrame::GetTOSRegister() {
426 if (SpilledScope::is_spilled()) return r0;
427
428 if (kVirtualElements[top_of_stack_state_] == kMaxTOSRegisters) {
429 Register answer = kBottomRegister[top_of_stack_state_];
430 __ push(answer);
431 top_of_stack_state_ = kPushState[top_of_stack_state_];
432 top_of_stack_state_ = kPopState[top_of_stack_state_];
433 return answer;
434 }
435
436 return kTopRegister[kPushState[top_of_stack_state_]];
437 }
438
439
440 void VirtualFrame::EmitPush(MemOperand operand) {
441 element_count_++;
442 if (SpilledScope::is_spilled()) {
443 __ ldr(r0, operand);
444 __ push(r0);
445 return;
446 }
447 if (kVirtualElements[top_of_stack_state_] == kMaxTOSRegisters) {
448 __ push(kBottomRegister[top_of_stack_state_]);
449 }
450 top_of_stack_state_ = kPushState[top_of_stack_state_];
451 __ ldr(kTopRegister[top_of_stack_state_], operand);
286 } 452 }
287 453
288 454
289 void VirtualFrame::EmitPushMultiple(int count, int src_regs) { 455 void VirtualFrame::EmitPushMultiple(int count, int src_regs) {
290 ASSERT(stack_pointer_ == element_count() - 1); 456 ASSERT(SpilledScope::is_spilled());
291 Adjust(count); 457 Adjust(count);
292 __ stm(db_w, sp, src_regs); 458 __ stm(db_w, sp, src_regs);
293 } 459 }
294 460
295 461
296 #undef __ 462 #undef __
297 463
298 } } // namespace v8::internal 464 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698