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

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

Issue 338043: Make it more pleasant to work with expression locations in the... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 11 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
« no previous file with comments | « src/fast-codegen.cc ('k') | src/location.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 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 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
101 __ RecordJSReturn(); 101 __ RecordJSReturn();
102 // Do not use the leave instruction here because it is too short to 102 // Do not use the leave instruction here because it is too short to
103 // patch with the code required by the debugger. 103 // patch with the code required by the debugger.
104 __ mov(esp, ebp); 104 __ mov(esp, ebp);
105 __ pop(ebp); 105 __ pop(ebp);
106 __ ret((fun->scope()->num_parameters() + 1) * kPointerSize); 106 __ ret((fun->scope()->num_parameters() + 1) * kPointerSize);
107 } 107 }
108 } 108 }
109 109
110 110
111 void FastCodeGenerator::Move(Location destination, Slot* source) {
112 switch (destination.type()) {
113 case Location::NOWHERE:
114 break;
115 case Location::TEMP:
116 __ push(Operand(ebp, SlotOffset(source)));
117 break;
118 }
119 }
120
121
122 void FastCodeGenerator::Move(Location destination, Literal* expr) {
123 switch (destination.type()) {
124 case Location::NOWHERE:
125 break;
126 case Location::TEMP:
127 __ push(Immediate(expr->handle()));
128 break;
129 }
130 }
131
132
133 void FastCodeGenerator::Move(Slot* destination, Location source) {
134 switch (source.type()) {
135 case Location::NOWHERE:
136 UNREACHABLE();
137 case Location::TEMP:
138 __ pop(Operand(ebp, SlotOffset(destination)));
139 break;
140 }
141 }
142
143
111 void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { 144 void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
112 // Call the runtime to declare the globals. 145 // Call the runtime to declare the globals.
113 __ push(esi); // The context is the first argument. 146 __ push(esi); // The context is the first argument.
114 __ push(Immediate(pairs)); 147 __ push(Immediate(pairs));
115 __ push(Immediate(Smi::FromInt(is_eval_ ? 1 : 0))); 148 __ push(Immediate(Smi::FromInt(is_eval_ ? 1 : 0)));
116 __ CallRuntime(Runtime::kDeclareGlobals, 3); 149 __ CallRuntime(Runtime::kDeclareGlobals, 3);
117 // Return value is ignored. 150 // Return value is ignored.
118 } 151 }
119 152
120 153
121 void FastCodeGenerator::VisitBlock(Block* stmt) {
122 Comment cmnt(masm_, "[ Block");
123 SetStatementPosition(stmt);
124 VisitStatements(stmt->statements());
125 }
126
127
128 void FastCodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) {
129 Comment cmnt(masm_, "[ ExpressionStatement");
130 SetStatementPosition(stmt);
131 Visit(stmt->expression());
132 }
133
134
135 void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { 154 void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
136 Comment cmnt(masm_, "[ ReturnStatement"); 155 Comment cmnt(masm_, "[ ReturnStatement");
137 SetStatementPosition(stmt); 156 SetStatementPosition(stmt);
138 Expression* expr = stmt->expression(); 157 Expression* expr = stmt->expression();
139 // Complete the statement based on the type of the subexpression. 158 // Complete the statement based on the type of the subexpression.
140 if (expr->AsLiteral() != NULL) { 159 if (expr->AsLiteral() != NULL) {
141 __ mov(eax, expr->AsLiteral()->handle()); 160 __ mov(eax, expr->AsLiteral()->handle());
142 } else { 161 } else {
143 Visit(expr); 162 Visit(expr);
144 ASSERT(expr->location().is_temporary()); 163 Move(eax, expr->location());
145 __ pop(eax);
146 } 164 }
147 165
148 if (FLAG_trace) { 166 if (FLAG_trace) {
149 __ push(eax); 167 __ push(eax);
150 __ CallRuntime(Runtime::kTraceExit, 1); 168 __ CallRuntime(Runtime::kTraceExit, 1);
151 } 169 }
152 __ RecordJSReturn(); 170 __ RecordJSReturn();
153 171
154 // Do not use the leave instruction here because it is too short to 172 // Do not use the leave instruction here because it is too short to
155 // patch with the code required by the debugger. 173 // patch with the code required by the debugger.
156 __ mov(esp, ebp); 174 __ mov(esp, ebp);
157 __ pop(ebp); 175 __ pop(ebp);
158 __ ret((function_->scope()->num_parameters() + 1) * kPointerSize); 176 __ ret((function_->scope()->num_parameters() + 1) * kPointerSize);
159 } 177 }
160 178
161 179
162 void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { 180 void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
163 Comment cmnt(masm_, "[ FunctionLiteral"); 181 Comment cmnt(masm_, "[ FunctionLiteral");
164 182
165 // Build the function boilerplate and instantiate it. 183 // Build the function boilerplate and instantiate it.
166 Handle<JSFunction> boilerplate = BuildBoilerplate(expr); 184 Handle<JSFunction> boilerplate = BuildBoilerplate(expr);
167 if (HasStackOverflow()) return; 185 if (HasStackOverflow()) return;
168 186
169 ASSERT(boilerplate->IsBoilerplate()); 187 ASSERT(boilerplate->IsBoilerplate());
170 188
171 // Create a new closure. 189 // Create a new closure.
172 __ push(esi); 190 __ push(esi);
173 __ push(Immediate(boilerplate)); 191 __ push(Immediate(boilerplate));
174 __ CallRuntime(Runtime::kNewClosure, 2); 192 __ CallRuntime(Runtime::kNewClosure, 2);
175 193 Move(expr->location(), eax);
176 if (expr->location().is_temporary()) {
177 __ push(eax);
178 } else {
179 ASSERT(expr->location().is_nowhere());
180 }
181 } 194 }
182 195
183 196
184 void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) { 197 void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
185 Comment cmnt(masm_, "[ VariableProxy"); 198 Comment cmnt(masm_, "[ VariableProxy");
186 Expression* rewrite = expr->var()->rewrite(); 199 Expression* rewrite = expr->var()->rewrite();
187 if (rewrite == NULL) { 200 if (rewrite == NULL) {
188 Comment cmnt(masm_, "Global variable"); 201 Comment cmnt(masm_, "Global variable");
189 // Use inline caching. Variable name is passed in ecx and the global 202 // Use inline caching. Variable name is passed in ecx and the global
190 // object on the stack. 203 // object on the stack.
191 __ push(CodeGenerator::GlobalObject()); 204 __ push(CodeGenerator::GlobalObject());
192 __ mov(ecx, expr->name()); 205 __ mov(ecx, expr->name());
193 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 206 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
194 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT); 207 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT);
195 208
196 // A test eax instruction following the call is used by the IC to 209 // A test eax instruction following the call is used by the IC to
197 // indicate that the inobject property case was inlined. Ensure there 210 // indicate that the inobject property case was inlined. Ensure there
198 // is no test eax instruction here. Remember that the assembler may 211 // is no test eax instruction here. Remember that the assembler may
199 // choose to do peephole optimization (eg, push/pop elimination). 212 // choose to do peephole optimization (eg, push/pop elimination).
200 if (expr->location().is_temporary()) { 213 switch (expr->location().type()) {
201 // Replace the global object with the result. 214 case Location::NOWHERE:
202 __ mov(Operand(esp, 0), eax); 215 __ add(Operand(esp), Immediate(kPointerSize));
203 } else { 216 break;
204 ASSERT(expr->location().is_nowhere()); 217 case Location::TEMP:
205 __ add(Operand(esp), Immediate(kPointerSize)); 218 // Replace the global object with the result.
219 __ mov(Operand(esp, 0), eax);
220 break;
206 } 221 }
207 222
208 } else { 223 } else {
209 Comment cmnt(masm_, "Stack slot"); 224 Comment cmnt(masm_, "Stack slot");
210 Slot* slot = rewrite->AsSlot(); 225 Move(expr->location(), rewrite->AsSlot());
211 ASSERT(slot != NULL);
212 if (expr->location().is_temporary()) {
213 __ push(Operand(ebp, SlotOffset(slot)));
214 } else {
215 ASSERT(expr->location().is_nowhere());
216 }
217 }
218 }
219
220
221 void FastCodeGenerator::VisitLiteral(Literal* expr) {
222 if (expr->location().is_temporary()) {
223 __ push(Immediate(expr->handle()));
224 } else {
225 ASSERT(expr->location().is_nowhere());
226 } 226 }
227 } 227 }
228 228
229 229
230 void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { 230 void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
231 Comment cmnt(masm_, "[ ObjectLiteral"); 231 Comment cmnt(masm_, "[ ObjectLiteral");
232 Label exists; 232 Label exists;
233 // Registers will be used as follows: 233 // Registers will be used as follows:
234 // edi = JS function. 234 // edi = JS function.
235 // ebx = literals array. 235 // ebx = literals array.
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
276 if (!result_saved) { 276 if (!result_saved) {
277 __ push(eax); // Save result on the stack 277 __ push(eax); // Save result on the stack
278 result_saved = true; 278 result_saved = true;
279 } 279 }
280 switch (property->kind()) { 280 switch (property->kind()) {
281 case ObjectLiteral::Property::MATERIALIZED_LITERAL: // fall through 281 case ObjectLiteral::Property::MATERIALIZED_LITERAL: // fall through
282 ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); 282 ASSERT(!CompileTimeValue::IsCompileTimeValue(value));
283 case ObjectLiteral::Property::COMPUTED: 283 case ObjectLiteral::Property::COMPUTED:
284 if (key->handle()->IsSymbol()) { 284 if (key->handle()->IsSymbol()) {
285 Visit(value); 285 Visit(value);
286 ASSERT(value->location().is_temporary()); 286 Move(eax, value->location());
287 __ pop(eax);
288 __ mov(ecx, Immediate(key->handle())); 287 __ mov(ecx, Immediate(key->handle()));
289 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 288 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
290 __ call(ic, RelocInfo::CODE_TARGET); 289 __ call(ic, RelocInfo::CODE_TARGET);
291 // StoreIC leaves the receiver on the stack. 290 // StoreIC leaves the receiver on the stack.
292 break; 291 break;
293 } 292 }
294 // fall through 293 // fall through
295 case ObjectLiteral::Property::PROTOTYPE: 294 case ObjectLiteral::Property::PROTOTYPE:
296 __ push(eax); 295 __ push(eax);
297 Visit(key); 296 Visit(key);
298 ASSERT(key->location().is_temporary()); 297 ASSERT(value->location().is_temporary());
299 Visit(value); 298 Visit(value);
300 ASSERT(value->location().is_temporary()); 299 ASSERT(value->location().is_temporary());
301 __ CallRuntime(Runtime::kSetProperty, 3); 300 __ CallRuntime(Runtime::kSetProperty, 3);
302 __ mov(eax, Operand(esp, 0)); // Restore result into eax. 301 __ mov(eax, Operand(esp, 0)); // Restore result into eax.
303 break; 302 break;
304 case ObjectLiteral::Property::SETTER: // fall through 303 case ObjectLiteral::Property::SETTER: // fall through
305 case ObjectLiteral::Property::GETTER: 304 case ObjectLiteral::Property::GETTER:
306 __ push(eax); 305 __ push(eax);
307 Visit(key); 306 Visit(key);
308 ASSERT(key->location().is_temporary()); 307 ASSERT(key->location().is_temporary());
309 __ push(Immediate(property->kind() == ObjectLiteral::Property::SETTER ? 308 __ push(Immediate(property->kind() == ObjectLiteral::Property::SETTER ?
310 Smi::FromInt(1) : 309 Smi::FromInt(1) :
311 Smi::FromInt(0))); 310 Smi::FromInt(0)));
312 Visit(value); 311 Visit(value);
313 ASSERT(value->location().is_temporary()); 312 ASSERT(value->location().is_temporary());
314 __ CallRuntime(Runtime::kDefineAccessor, 4); 313 __ CallRuntime(Runtime::kDefineAccessor, 4);
315 __ mov(eax, Operand(esp, 0)); // Restore result into eax. 314 __ mov(eax, Operand(esp, 0)); // Restore result into eax.
316 break; 315 break;
317 default: UNREACHABLE(); 316 default: UNREACHABLE();
318 } 317 }
319 } 318 }
320 if (expr->location().is_nowhere() && result_saved) { 319 switch (expr->location().type()) {
321 __ add(Operand(esp), Immediate(kPointerSize)); 320 case Location::NOWHERE:
322 } else if (expr->location().is_temporary() && !result_saved) { 321 if (result_saved) __ add(Operand(esp), Immediate(kPointerSize));
323 __ push(eax); 322 break;
323 case Location::TEMP:
324 if (!result_saved) __ push(eax);
325 break;
324 } 326 }
325 } 327 }
326 328
327 329
328 void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { 330 void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
329 Comment cmnt(masm_, "[ RegExp Literal"); 331 Comment cmnt(masm_, "[ RegExp Literal");
330 Label done; 332 Label done;
331 // Registers will be used as follows: 333 // Registers will be used as follows:
332 // edi = JS function. 334 // edi = JS function.
333 // ebx = literals array. 335 // ebx = literals array.
334 // eax = regexp literal. 336 // eax = regexp literal.
335 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 337 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
336 __ mov(ebx, FieldOperand(edi, JSFunction::kLiteralsOffset)); 338 __ mov(ebx, FieldOperand(edi, JSFunction::kLiteralsOffset));
337 int literal_offset = 339 int literal_offset =
338 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; 340 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize;
339 __ mov(eax, FieldOperand(ebx, literal_offset)); 341 __ mov(eax, FieldOperand(ebx, literal_offset));
340 __ cmp(eax, Factory::undefined_value()); 342 __ cmp(eax, Factory::undefined_value());
341 __ j(not_equal, &done); 343 __ j(not_equal, &done);
342 // Create regexp literal using runtime function 344 // Create regexp literal using runtime function
343 // Result will be in eax. 345 // Result will be in eax.
344 __ push(ebx); 346 __ push(ebx);
345 __ push(Immediate(Smi::FromInt(expr->literal_index()))); 347 __ push(Immediate(Smi::FromInt(expr->literal_index())));
346 __ push(Immediate(expr->pattern())); 348 __ push(Immediate(expr->pattern()));
347 __ push(Immediate(expr->flags())); 349 __ push(Immediate(expr->flags()));
348 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); 350 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
349 // Label done: 351 // Label done:
350 __ bind(&done); 352 __ bind(&done);
351 if (expr->location().is_temporary()) { 353 Move(expr->location(), eax);
352 __ push(eax);
353 } else {
354 ASSERT(expr->location().is_nowhere());
355 }
356 } 354 }
357 355
358 356
359 void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { 357 void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
360 Comment cmnt(masm_, "[ ArrayLiteral"); 358 Comment cmnt(masm_, "[ ArrayLiteral");
361 Label make_clone; 359 Label make_clone;
362 360
363 // Fetch the function's literals array. 361 // Fetch the function's literals array.
364 __ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 362 __ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
365 __ mov(ebx, FieldOperand(ebx, JSFunction::kLiteralsOffset)); 363 __ mov(ebx, FieldOperand(ebx, JSFunction::kLiteralsOffset));
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
410 __ pop(eax); // Subexpression value. 408 __ pop(eax); // Subexpression value.
411 __ mov(ebx, Operand(esp, 0)); // Copy of array literal. 409 __ mov(ebx, Operand(esp, 0)); // Copy of array literal.
412 __ mov(ebx, FieldOperand(ebx, JSObject::kElementsOffset)); 410 __ mov(ebx, FieldOperand(ebx, JSObject::kElementsOffset));
413 int offset = FixedArray::kHeaderSize + (i * kPointerSize); 411 int offset = FixedArray::kHeaderSize + (i * kPointerSize);
414 __ mov(FieldOperand(ebx, offset), eax); 412 __ mov(FieldOperand(ebx, offset), eax);
415 413
416 // Update the write barrier for the array store. 414 // Update the write barrier for the array store.
417 __ RecordWrite(ebx, offset, eax, ecx); 415 __ RecordWrite(ebx, offset, eax, ecx);
418 } 416 }
419 417
420 Location destination = expr->location(); 418 switch (expr->location().type()) {
421 if (destination.is_nowhere() && result_saved) { 419 case Location::NOWHERE:
422 __ add(Operand(esp), Immediate(kPointerSize)); 420 if (result_saved) __ add(Operand(esp), Immediate(kPointerSize));
423 } else if (destination.is_temporary() && !result_saved) { 421 break;
424 __ push(eax); 422 case Location::TEMP:
423 if (!result_saved) __ push(eax);
424 break;
425 } 425 }
426 } 426 }
427 427
428 428
429 void FastCodeGenerator::VisitAssignment(Assignment* expr) { 429 void FastCodeGenerator::VisitAssignment(Assignment* expr) {
430 Comment cmnt(masm_, "[ Assignment"); 430 Comment cmnt(masm_, "[ Assignment");
431 ASSERT(expr->op() == Token::ASSIGN || expr->op() == Token::INIT_VAR); 431 ASSERT(expr->op() == Token::ASSIGN || expr->op() == Token::INIT_VAR);
432 432
433 // Left-hand side can only be a global or a (parameter or local) slot. 433 // Left-hand side can only be a global or a (parameter or local) slot.
434 Variable* var = expr->target()->AsVariableProxy()->AsVariable(); 434 Variable* var = expr->target()->AsVariableProxy()->AsVariable();
435 ASSERT(var != NULL); 435 ASSERT(var != NULL);
436 ASSERT(var->is_global() || var->slot() != NULL); 436 ASSERT(var->is_global() || var->slot() != NULL);
437 437
438 Expression* rhs = expr->value(); 438 Expression* rhs = expr->value();
439 Location destination = expr->location();
440 if (var->is_global()) { 439 if (var->is_global()) {
441 // Assignment to a global variable, use inline caching. Right-hand-side 440 // Assignment to a global variable, use inline caching. Right-hand-side
442 // value is passed in eax, variable name in ecx, and the global object 441 // value is passed in eax, variable name in ecx, and the global object
443 // on the stack. 442 // on the stack.
444 443
445 // Code for the right-hand-side expression depends on its type. 444 // Code for the right-hand-side expression depends on its type.
446 if (rhs->AsLiteral() != NULL) { 445 if (rhs->AsLiteral() != NULL) {
447 __ mov(eax, rhs->AsLiteral()->handle()); 446 __ mov(eax, rhs->AsLiteral()->handle());
448 } else { 447 } else {
449 ASSERT(rhs->location().is_temporary()); 448 ASSERT(rhs->location().is_temporary());
450 Visit(rhs); 449 Visit(rhs);
451 __ pop(eax); 450 __ pop(eax);
452 } 451 }
453 __ mov(ecx, var->name()); 452 __ mov(ecx, var->name());
454 __ push(CodeGenerator::GlobalObject()); 453 __ push(CodeGenerator::GlobalObject());
455 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 454 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
456 __ call(ic, RelocInfo::CODE_TARGET); 455 __ call(ic, RelocInfo::CODE_TARGET);
457 // Overwrite the global object on the stack with the result if needed. 456 // Overwrite the global object on the stack with the result if needed.
458 if (destination.is_temporary()) { 457 switch (expr->location().type()) {
459 __ mov(Operand(esp, 0), eax); 458 case Location::NOWHERE:
460 } else { 459 __ add(Operand(esp), Immediate(kPointerSize));
461 ASSERT(destination.is_nowhere()); 460 break;
462 __ add(Operand(esp), Immediate(kPointerSize)); 461 case Location::TEMP:
462 __ mov(Operand(esp, 0), eax);
463 break;
463 } 464 }
464 } else { 465 } else {
465 // Local or parameter assignment. 466 // Local or parameter assignment.
466 467
467 // Code for the right-hand side expression depends on its type. 468 // Code for the right-hand side expression depends on its type.
468 if (rhs->AsLiteral() != NULL) { 469 if (rhs->AsLiteral() != NULL) {
469 // Two cases: 'temp <- (var = constant)', or 'var = constant' with a 470 // Two cases: 'temp <- (var = constant)', or 'var = constant' with a
470 // discarded result. Always perform the assignment. 471 // discarded result. Always perform the assignment.
471 __ mov(eax, rhs->AsLiteral()->handle()); 472 __ mov(eax, rhs->AsLiteral()->handle());
472 __ mov(Operand(ebp, SlotOffset(var->slot())), eax); 473 __ mov(Operand(ebp, SlotOffset(var->slot())), eax);
473 if (destination.is_temporary()) { 474 Move(expr->location(), eax);
474 // Case 'temp <- (var = constant)'. Save result.
475 __ push(eax);
476 }
477 } else { 475 } else {
478 ASSERT(rhs->location().is_temporary()); 476 ASSERT(rhs->location().is_temporary());
479 Visit(rhs); 477 Visit(rhs);
480 if (destination.is_temporary()) { 478 switch (expr->location().type()) {
481 // Case 'temp1 <- (var = temp0)'. Preserve right-hand-side 479 case Location::NOWHERE:
482 // temporary on the stack. 480 // Case 'var = temp'. Discard right-hand-side temporary.
483 __ mov(eax, Operand(esp, 0)); 481 Move(var->slot(), rhs->location());
484 __ mov(Operand(ebp, SlotOffset(var->slot())), eax); 482 break;
485 } else { 483 case Location::TEMP:
486 ASSERT(destination.is_nowhere()); 484 // Case 'temp1 <- (var = temp0)'. Preserve right-hand-side
487 // Case 'var = temp'. Discard right-hand-side temporary. 485 // temporary on the stack.
488 __ pop(Operand(ebp, SlotOffset(var->slot()))); 486 __ mov(eax, Operand(esp, 0));
487 __ mov(Operand(ebp, SlotOffset(var->slot())), eax);
488 break;
489 } 489 }
490 } 490 }
491 } 491 }
492 } 492 }
493 493
494 494
495 void FastCodeGenerator::VisitCall(Call* expr) { 495 void FastCodeGenerator::VisitCall(Call* expr) {
496 Expression* fun = expr->expression(); 496 Expression* fun = expr->expression();
497 ZoneList<Expression*>* args = expr->arguments(); 497 ZoneList<Expression*>* args = expr->arguments();
498 Variable* var = fun->AsVariableProxy()->AsVariable(); 498 Variable* var = fun->AsVariableProxy()->AsVariable();
(...skipping 10 matching lines...) Expand all
509 } 509 }
510 // Record source position for debugger 510 // Record source position for debugger
511 SetSourcePosition(expr->position()); 511 SetSourcePosition(expr->position());
512 // Call the IC initialization code. 512 // Call the IC initialization code.
513 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, 513 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count,
514 NOT_IN_LOOP); 514 NOT_IN_LOOP);
515 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT); 515 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT);
516 // Restore context register. 516 // Restore context register.
517 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 517 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
518 // Discard the function left on TOS. 518 // Discard the function left on TOS.
519 if (expr->location().is_temporary()) { 519 switch (expr->location().type()) {
520 __ mov(Operand(esp, 0), eax); 520 case Location::NOWHERE:
521 } else { 521 __ add(Operand(esp), Immediate(kPointerSize));
522 ASSERT(expr->location().is_nowhere()); 522 break;
523 __ add(Operand(esp), Immediate(kPointerSize)); 523 case Location::TEMP:
524 __ mov(Operand(esp, 0), eax);
525 break;
524 } 526 }
525 } 527 }
526 528
527 529
528 void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) { 530 void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
529 Comment cmnt(masm_, "[ CallRuntime"); 531 Comment cmnt(masm_, "[ CallRuntime");
530 ZoneList<Expression*>* args = expr->arguments(); 532 ZoneList<Expression*>* args = expr->arguments();
531 Runtime::Function* function = expr->function(); 533 Runtime::Function* function = expr->function();
532 534
533 ASSERT(function != NULL); 535 ASSERT(function != NULL);
534 536
535 // Push the arguments ("left-to-right"). 537 // Push the arguments ("left-to-right").
536 int arg_count = args->length(); 538 int arg_count = args->length();
537 for (int i = 0; i < arg_count; i++) { 539 for (int i = 0; i < arg_count; i++) {
538 Visit(args->at(i)); 540 Visit(args->at(i));
539 ASSERT(args->at(i)->location().is_temporary()); 541 ASSERT(args->at(i)->location().is_temporary());
540 } 542 }
541 543
542 __ CallRuntime(function, arg_count); 544 __ CallRuntime(function, arg_count);
543 if (expr->location().is_temporary()) { 545 Move(expr->location(), eax);
544 __ push(eax);
545 } else {
546 ASSERT(expr->location().is_nowhere());
547 }
548 } 546 }
549 547
550 548
551 void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { 549 void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
552 // Compile a short-circuited boolean or operation in a non-test 550 // Compile a short-circuited boolean or operation in a non-test
553 // context. 551 // context.
554 ASSERT(expr->op() == Token::OR); 552 ASSERT(expr->op() == Token::OR);
555 // Compile (e0 || e1) as if it were 553 // Compile (e0 || e1) as if it were
556 // (let (temp = e0) temp ? temp : e1). 554 // (let (temp = e0) temp ? temp : e1).
557 555
558 Label eval_right, done; 556 Label eval_right, done;
559 Location destination = expr->location(); 557 Location destination = expr->location();
560 Expression* left = expr->left(); 558 Expression* left = expr->left();
561 Expression* right = expr->right(); 559 Expression* right = expr->right();
562 560
563 // Use the shared ToBoolean stub to find the boolean value of the 561 // Use the shared ToBoolean stub to find the boolean value of the
564 // left-hand subexpression. Load the value into eax to perform some 562 // left-hand subexpression. Load the value into eax to perform some
565 // inlined checks assumed by the stub. 563 // inlined checks assumed by the stub.
566 564
567 // Compile the left-hand value into eax. Put it on the stack if we may 565 // Compile the left-hand value into eax. Put it on the stack if we may
568 // need it as the value of the whole expression. 566 // need it as the value of the whole expression.
569 if (left->AsLiteral() != NULL) { 567 if (left->AsLiteral() != NULL) {
570 __ mov(eax, left->AsLiteral()->handle()); 568 __ mov(eax, left->AsLiteral()->handle());
571 if (destination.is_temporary()) __ push(eax); 569 if (destination.is_temporary()) __ push(eax);
572 } else { 570 } else {
573 Visit(left); 571 Visit(left);
574 ASSERT(left->location().is_temporary()); 572 ASSERT(left->location().is_temporary());
575 if (destination.is_temporary()) { 573 switch (destination.type()) {
576 // Copy the left-hand value into eax because we may need it as the 574 case Location::NOWHERE:
577 // final result. 575 // Pop the left-hand value into eax because we will not need it as the
578 __ mov(eax, Operand(esp, 0)); 576 // final result.
579 } else { 577 __ pop(eax);
580 // Pop the left-hand value into eax because we will not need it as the 578 break;
581 // final result. 579 case Location::TEMP:
582 __ pop(eax); 580 // Copy the left-hand value into eax because we may need it as the
581 // final result.
582 __ mov(eax, Operand(esp, 0));
583 break;
583 } 584 }
584 } 585 }
585 // The left-hand value is in eax. It is also on the stack iff the 586 // The left-hand value is in eax. It is also on the stack iff the
586 // destination location is temporary. 587 // destination location is temporary.
587 588
588 // Perform fast checks assumed by the stub. 589 // Perform fast checks assumed by the stub.
589 __ cmp(eax, Factory::undefined_value()); // The undefined value is false. 590 __ cmp(eax, Factory::undefined_value()); // The undefined value is false.
590 __ j(equal, &eval_right); 591 __ j(equal, &eval_right);
591 __ cmp(eax, Factory::true_value()); // True is true. 592 __ cmp(eax, Factory::true_value()); // True is true.
592 __ j(equal, &done); 593 __ j(equal, &done);
(...skipping 12 matching lines...) Expand all
605 __ test(eax, Operand(eax)); // The stub returns nonzero for true. 606 __ test(eax, Operand(eax)); // The stub returns nonzero for true.
606 __ j(not_zero, &done); 607 __ j(not_zero, &done);
607 608
608 __ bind(&eval_right); 609 __ bind(&eval_right);
609 // Discard the left-hand value if present on the stack. 610 // Discard the left-hand value if present on the stack.
610 if (destination.is_temporary()) { 611 if (destination.is_temporary()) {
611 __ add(Operand(esp), Immediate(kPointerSize)); 612 __ add(Operand(esp), Immediate(kPointerSize));
612 } 613 }
613 // Save or discard the right-hand value as needed. 614 // Save or discard the right-hand value as needed.
614 if (right->AsLiteral() != NULL) { 615 if (right->AsLiteral() != NULL) {
615 if (destination.is_temporary()) { 616 Move(destination, right->AsLiteral());
616 __ push(Immediate(right->AsLiteral()->handle()));
617 } else {
618 ASSERT(destination.is_nowhere());
619 }
620 } else { 617 } else {
621 Visit(right); 618 Visit(right);
622 ASSERT(right->location().is_temporary()); 619 Move(destination, right->location());
623 if (destination.is_nowhere()) {
624 __ add(Operand(esp), Immediate(kPointerSize));
625 } else {
626 ASSERT(destination.is_temporary());
627 }
628 } 620 }
629 621
630 __ bind(&done); 622 __ bind(&done);
631 } 623 }
632 624
633 625
634 } } // namespace v8::internal 626 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/fast-codegen.cc ('k') | src/location.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698