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

Side by Side Diff: src/codegen-ia32.cc

Issue 11396: Begin counting references to registers, both in the frame and out.... (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/toiger/
Patch Set: '' Created 12 years 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
« no previous file with comments | « src/codegen-ia32.h ('k') | src/register-allocator.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-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 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
73 // CodeGenerator implementation 73 // CodeGenerator implementation
74 74
75 CodeGenerator::CodeGenerator(int buffer_size, Handle<Script> script, 75 CodeGenerator::CodeGenerator(int buffer_size, Handle<Script> script,
76 bool is_eval) 76 bool is_eval)
77 : is_eval_(is_eval), 77 : is_eval_(is_eval),
78 script_(script), 78 script_(script),
79 deferred_(8), 79 deferred_(8),
80 masm_(new MacroAssembler(NULL, buffer_size)), 80 masm_(new MacroAssembler(NULL, buffer_size)),
81 scope_(NULL), 81 scope_(NULL),
82 frame_(NULL), 82 frame_(NULL),
83 allocator_(NULL),
83 cc_reg_(no_condition), 84 cc_reg_(no_condition),
84 state_(NULL), 85 state_(NULL),
85 is_inside_try_(false), 86 is_inside_try_(false),
86 break_stack_height_(0), 87 break_stack_height_(0),
87 loop_nesting_(0), 88 loop_nesting_(0),
88 function_return_is_shadowed_(false) { 89 function_return_is_shadowed_(false) {
89 } 90 }
90 91
91 92
92 // Calling conventions: 93 // Calling conventions:
93 // ebp: frame pointer 94 // ebp: frame pointer
94 // esp: stack pointer 95 // esp: stack pointer
95 // edi: caller's parameter pointer 96 // edi: caller's parameter pointer
96 // esi: callee's context 97 // esi: callee's context
97 98
98 void CodeGenerator::GenCode(FunctionLiteral* fun) { 99 void CodeGenerator::GenCode(FunctionLiteral* fun) {
99 // Record the position for debugging purposes. 100 // Record the position for debugging purposes.
100 __ RecordPosition(fun->start_position()); 101 __ RecordPosition(fun->start_position());
101 102
102 ZoneList<Statement*>* body = fun->body(); 103 ZoneList<Statement*>* body = fun->body();
103 104
104 // Initialize state. 105 // Initialize state.
105 ASSERT(scope_ == NULL); 106 ASSERT(scope_ == NULL);
106 scope_ = fun->scope(); 107 scope_ = fun->scope();
107 ASSERT(frame_ == NULL); 108 ASSERT(frame_ == NULL);
108 set_frame(new VirtualFrame(this)); 109 set_frame(new VirtualFrame(this));
110 ASSERT(allocator_ == NULL);
111 RegisterAllocator register_allocator(this);
112 allocator_ = &register_allocator;
109 cc_reg_ = no_condition; 113 cc_reg_ = no_condition;
110 function_return_.set_code_generator(this); 114 function_return_.set_code_generator(this);
111 function_return_is_shadowed_ = false; 115 function_return_is_shadowed_ = false;
112 116
113 // Adjust for function-level loop nesting. 117 // Adjust for function-level loop nesting.
114 loop_nesting_ += fun->loop_nesting(); 118 loop_nesting_ += fun->loop_nesting();
115 119
116 { 120 {
117 CodeGenState state(this); 121 CodeGenState state(this);
118 122
119 // Entry 123 // Entry
120 // stack: function, receiver, arguments, return address 124 // stack: function, receiver, arguments, return address
121 // esp: stack pointer 125 // esp: stack pointer
122 // ebp: frame pointer 126 // ebp: frame pointer
123 // edi: caller's parameter pointer 127 // edi: caller's parameter pointer
124 // esi: callee's context 128 // esi: callee's context
125 129
130 allocator_->Initialize();
126 frame_->Enter(); 131 frame_->Enter();
127 // tos: code slot 132 // tos: code slot
128 #ifdef DEBUG 133 #ifdef DEBUG
129 if (strlen(FLAG_stop_at) > 0 && 134 if (strlen(FLAG_stop_at) > 0 &&
130 fun->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { 135 fun->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
136 frame_->SpillAll();
131 __ int3(); 137 __ int3();
132 } 138 }
133 #endif 139 #endif
134 140
135 // This section now only allocates and copies the formals into the 141 // Allocate space for locals and initialize them.
136 // arguments object. It saves the address in ecx, which is saved 142 frame_->AllocateStackSlots(scope_->num_stack_slots());
137 // at any point before either garbage collection or ecx is
138 // overwritten. The flag arguments_array_allocated communicates
139 // with the store into the arguments variable and guards the lazy
140 // pushes of ecx to TOS. The flag arguments_array_saved notes
141 // when the push has happened.
142 bool arguments_object_allocated = false;
143 bool arguments_object_saved = false;
144 143
145 // Allocate arguments object. 144 // Allocate the arguments object and copy the parameters into it.
146 // The arguments object pointer needs to be saved in ecx, since we need
147 // to store arguments into the context.
148 if (scope_->arguments() != NULL) { 145 if (scope_->arguments() != NULL) {
149 ASSERT(scope_->arguments_shadow() != NULL); 146 ASSERT(scope_->arguments_shadow() != NULL);
150 Comment cmnt(masm_, "[ allocate arguments object"); 147 Comment cmnt(masm_, "[ Allocate arguments object");
151 ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT); 148 ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT);
149 frame_->SpillAll();
152 __ lea(eax, frame_->Receiver()); 150 __ lea(eax, frame_->Receiver());
153 frame_->EmitPush(frame_->Function()); 151 frame_->EmitPush(frame_->Function());
154 frame_->EmitPush(eax); 152 frame_->EmitPush(eax);
155 frame_->EmitPush(Immediate(Smi::FromInt(scope_->num_parameters()))); 153 frame_->EmitPush(Immediate(Smi::FromInt(scope_->num_parameters())));
156 frame_->CallStub(&stub, 3); 154 frame_->CallStub(&stub, 3);
157 __ mov(ecx, Operand(eax)); 155 frame_->Push(eax);
158 arguments_object_allocated = true;
159 } 156 }
160 157
161 // Allocate space for locals and initialize them.
162 frame_->AllocateStackSlots(scope_->num_stack_slots());
163
164 if (scope_->num_heap_slots() > 0) { 158 if (scope_->num_heap_slots() > 0) {
165 frame_->SpillAll();
166 Comment cmnt(masm_, "[ allocate local context"); 159 Comment cmnt(masm_, "[ allocate local context");
167 // Save the arguments object pointer, if any.
168 if (arguments_object_allocated && !arguments_object_saved) {
169 frame_->EmitPush(ecx);
170 arguments_object_saved = true;
171 }
172 // Allocate local context. 160 // Allocate local context.
173 // Get outer context and create a new context based on it. 161 // Get outer context and create a new context based on it.
162 frame_->SpillAll();
174 frame_->EmitPush(frame_->Function()); 163 frame_->EmitPush(frame_->Function());
175 frame_->CallRuntime(Runtime::kNewContext, 1); // eax holds the result 164 frame_->CallRuntime(Runtime::kNewContext, 1); // eax holds the result
176 165
177 if (kDebug) { 166 if (kDebug) {
178 JumpTarget verified_true(this); 167 JumpTarget verified_true(this);
179 // Verify eax and esi are the same in debug mode 168 // Verify eax and esi are the same in debug mode
180 __ cmp(eax, Operand(esi)); 169 __ cmp(eax, Operand(esi));
181 verified_true.Branch(equal); 170 verified_true.Branch(equal);
182 __ int3(); 171 __ int3();
183 verified_true.Bind(); 172 verified_true.Bind();
(...skipping 14 matching lines...) Expand all
198 // needs to be copied into the context, it must be the last argument 187 // needs to be copied into the context, it must be the last argument
199 // passed to the parameter that needs to be copied. This is a rare 188 // passed to the parameter that needs to be copied. This is a rare
200 // case so we don't check for it, instead we rely on the copying 189 // case so we don't check for it, instead we rely on the copying
201 // order: such a parameter is copied repeatedly into the same 190 // order: such a parameter is copied repeatedly into the same
202 // context location and thus the last value is what is seen inside 191 // context location and thus the last value is what is seen inside
203 // the function. 192 // the function.
204 for (int i = 0; i < scope_->num_parameters(); i++) { 193 for (int i = 0; i < scope_->num_parameters(); i++) {
205 Variable* par = scope_->parameter(i); 194 Variable* par = scope_->parameter(i);
206 Slot* slot = par->slot(); 195 Slot* slot = par->slot();
207 if (slot != NULL && slot->type() == Slot::CONTEXT) { 196 if (slot != NULL && slot->type() == Slot::CONTEXT) {
197 frame_->SpillAll();
208 ASSERT(!scope_->is_global_scope()); // no parameters in global scope 198 ASSERT(!scope_->is_global_scope()); // no parameters in global scope
209 __ mov(eax, frame_->ParameterAt(i)); 199 __ mov(eax, frame_->ParameterAt(i));
210 // Loads ecx with context; used below in RecordWrite. 200 // Loads ecx with context; used below in RecordWrite.
211 __ mov(SlotOperand(slot, edx), eax); 201 __ mov(SlotOperand(slot, edx), eax);
212 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; 202 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize;
213 __ RecordWrite(edx, offset, eax, ebx); 203 __ RecordWrite(edx, offset, eax, ebx);
214 } 204 }
215 } 205 }
216 } 206 }
217 207
218 // This section stores the pointer to the arguments object that 208 // This section stores the pointer to the arguments object that
219 // was allocated and copied into above. If the address was not 209 // was allocated and copied into above. If the address was not
220 // saved to TOS, we push ecx onto the stack. 210 // saved to TOS, we push ecx onto the stack.
221 // 211 //
222 // Store the arguments object. This must happen after context 212 // Store the arguments object. This must happen after context
223 // initialization because the arguments object may be stored in the 213 // initialization because the arguments object may be stored in the
224 // context. 214 // context.
225 if (arguments_object_allocated) { 215 if (scope_->arguments() != NULL) {
226 ASSERT(scope_->arguments() != NULL); 216 frame_->SpillAll();
227 ASSERT(scope_->arguments_shadow() != NULL);
228 Comment cmnt(masm_, "[ store arguments object"); 217 Comment cmnt(masm_, "[ store arguments object");
229 { Reference shadow_ref(this, scope_->arguments_shadow()); 218 { Reference shadow_ref(this, scope_->arguments_shadow());
230 ASSERT(shadow_ref.is_slot()); 219 ASSERT(shadow_ref.is_slot());
231 { Reference arguments_ref(this, scope_->arguments()); 220 { Reference arguments_ref(this, scope_->arguments());
232 ASSERT(arguments_ref.is_slot()); 221 ASSERT(arguments_ref.is_slot());
233 // If the newly-allocated arguments object is already on the 222 // Here we rely on the convenient property that references to slot
234 // stack, we make use of the convenient property that references 223 // take up zero space in the frame (ie, it doesn't matter that the
235 // representing slots take up no space on the expression stack 224 // stored value is actually below the reference on the frame).
236 // (ie, it doesn't matter that the stored value is actually below
237 // the reference).
238 //
239 // If the newly-allocated argument object is not already on
240 // the stack, we rely on the property that loading a
241 // zero-sized reference will not clobber the ecx register.
242 if (!arguments_object_saved) {
243 frame_->SpillAll();
244 frame_->EmitPush(ecx);
245 }
246 arguments_ref.SetValue(NOT_CONST_INIT); 225 arguments_ref.SetValue(NOT_CONST_INIT);
247 } 226 }
248 shadow_ref.SetValue(NOT_CONST_INIT); 227 shadow_ref.SetValue(NOT_CONST_INIT);
249 } 228 }
250 frame_->Drop(); // Value is no longer needed. 229 frame_->Drop(); // Value is no longer needed.
251 } 230 }
252 231
253 // Generate code to 'execute' declarations and initialize functions 232 // Generate code to 'execute' declarations and initialize functions
254 // (source elements). In case of an illegal redeclaration we need to 233 // (source elements). In case of an illegal redeclaration we need to
255 // handle that instead of processing the declarations. 234 // handle that instead of processing the declarations.
256 if (scope_->HasIllegalRedeclaration()) { 235 if (scope_->HasIllegalRedeclaration()) {
257 Comment cmnt(masm_, "[ illegal redeclarations"); 236 Comment cmnt(masm_, "[ illegal redeclarations");
258 scope_->VisitIllegalRedeclaration(this); 237 scope_->VisitIllegalRedeclaration(this);
259 } else { 238 } else {
260 Comment cmnt(masm_, "[ declarations"); 239 Comment cmnt(masm_, "[ declarations");
261 ProcessDeclarations(scope_->declarations()); 240 ProcessDeclarations(scope_->declarations());
262 // Bail out if a stack-overflow exception occurred when processing 241 // Bail out if a stack-overflow exception occurred when processing
263 // declarations. 242 // declarations.
264 if (HasStackOverflow()) return; 243 if (HasStackOverflow()) return;
265 } 244 }
266 245
267 if (FLAG_trace) { 246 if (FLAG_trace) {
268 frame_->CallRuntime(Runtime::kTraceEnter, 0); 247 frame_->CallRuntime(Runtime::kTraceEnter, 0);
269 // Ignore the return value. 248 // Ignore the return value.
270 } 249 }
250 frame_->SpillAll();
271 CheckStack(); 251 CheckStack();
272 252
273 // Compile the body of the function in a vanilla state. Don't 253 // Compile the body of the function in a vanilla state. Don't
274 // bother compiling all the code if the scope has an illegal 254 // bother compiling all the code if the scope has an illegal
275 // redeclaration. 255 // redeclaration.
276 if (!scope_->HasIllegalRedeclaration()) { 256 if (!scope_->HasIllegalRedeclaration()) {
277 Comment cmnt(masm_, "[ function body"); 257 Comment cmnt(masm_, "[ function body");
278 #ifdef DEBUG 258 #ifdef DEBUG
279 bool is_builtin = Bootstrapper::IsActive(); 259 bool is_builtin = Bootstrapper::IsActive();
280 bool should_trace = 260 bool should_trace =
(...skipping 14 matching lines...) Expand all
295 statement.set_statement_pos(fun->end_position()); 275 statement.set_statement_pos(fun->end_position());
296 VisitReturnStatement(&statement); 276 VisitReturnStatement(&statement);
297 } 277 }
298 } 278 }
299 } 279 }
300 280
301 // Adjust for function-level loop nesting. 281 // Adjust for function-level loop nesting.
302 loop_nesting_ -= fun->loop_nesting(); 282 loop_nesting_ -= fun->loop_nesting();
303 283
304 // Code generation state must be reset. 284 // Code generation state must be reset.
285 ASSERT(state_ == NULL);
286 ASSERT(loop_nesting() == 0);
305 ASSERT(!function_return_is_shadowed_); 287 ASSERT(!function_return_is_shadowed_);
306 function_return_.Unuse(); 288 function_return_.Unuse();
289 ASSERT(!has_cc());
290 // There is no need to delete the register allocator, it is a
291 // stack-allocated local.
292 allocator_ = NULL;
293 delete_frame();
307 scope_ = NULL; 294 scope_ = NULL;
308 delete_frame();
309 ASSERT(!has_cc());
310 ASSERT(state_ == NULL);
311 ASSERT(loop_nesting() == 0);
312 } 295 }
313 296
314 297
315 Operand CodeGenerator::SlotOperand(Slot* slot, Register tmp) { 298 Operand CodeGenerator::SlotOperand(Slot* slot, Register tmp) {
316 // Currently, this assertion will fail if we try to assign to 299 // Currently, this assertion will fail if we try to assign to
317 // a constant variable that is constant because it is read-only 300 // a constant variable that is constant because it is read-only
318 // (such as the variable referring to a named function expression). 301 // (such as the variable referring to a named function expression).
319 // We need to implement assignments to read-only variables. 302 // We need to implement assignments to read-only variables.
320 // Ideally, we should do this during AST generation (by converting 303 // Ideally, we should do this during AST generation (by converting
321 // such assignments into expression statements); however, in general 304 // such assignments into expression statements); however, in general
(...skipping 5045 matching lines...) Expand 10 before | Expand all | Expand 10 after
5367 5350
5368 // Slow-case: Go through the JavaScript implementation. 5351 // Slow-case: Go through the JavaScript implementation.
5369 __ bind(&slow); 5352 __ bind(&slow);
5370 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); 5353 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION);
5371 } 5354 }
5372 5355
5373 5356
5374 #undef __ 5357 #undef __
5375 5358
5376 } } // namespace v8::internal 5359 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/codegen-ia32.h ('k') | src/register-allocator.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698