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

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

Issue 342035: Move the Location class into the AST Expression class as a member.... (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
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) { 111 void FastCodeGenerator::Move(Expression::Context context, Slot* source) {
112 switch (destination.type()) { 112 switch (context) {
113 case Location::kUninitialized: 113 case Expression::kUninitialized:
114 UNREACHABLE(); 114 UNREACHABLE();
115 case Location::kEffect: 115 case Expression::kEffect:
116 break; 116 break;
117 case Location::kValue: 117 case Expression::kValue:
118 __ push(Operand(ebp, SlotOffset(source))); 118 __ push(Operand(ebp, SlotOffset(source)));
119 break; 119 break;
120 } 120 }
121 } 121 }
122 122
123 123
124 void FastCodeGenerator::Move(Location destination, Literal* expr) { 124 void FastCodeGenerator::Move(Expression::Context context, Literal* expr) {
125 switch (destination.type()) { 125 switch (context) {
126 case Location::kUninitialized: 126 case Expression::kUninitialized:
127 UNREACHABLE(); 127 UNREACHABLE();
128 case Location::kEffect: 128 case Expression::kEffect:
129 break; 129 break;
130 case Location::kValue: 130 case Expression::kValue:
131 __ push(Immediate(expr->handle())); 131 __ push(Immediate(expr->handle()));
132 break; 132 break;
133 } 133 }
134 } 134 }
135 135
136 136
137 void FastCodeGenerator::Move(Slot* destination, Location source) { 137 void FastCodeGenerator::DropAndMove(Expression::Context context,
138 switch (source.type()) { 138 Register source) {
139 case Location::kUninitialized: // Fall through. 139 switch (context) {
140 case Location::kEffect: 140 case Expression::kUninitialized:
141 UNREACHABLE(); 141 UNREACHABLE();
142 case Location::kValue: 142 case Expression::kEffect:
143 __ pop(Operand(ebp, SlotOffset(destination)));
144 break;
145 }
146 }
147
148
149 void FastCodeGenerator::DropAndMove(Location destination, Register source) {
150 switch (destination.type()) {
151 case Location::kUninitialized:
152 UNREACHABLE();
153 case Location::kEffect:
154 __ add(Operand(esp), Immediate(kPointerSize)); 143 __ add(Operand(esp), Immediate(kPointerSize));
155 break; 144 break;
156 case Location::kValue: 145 case Expression::kValue:
157 __ mov(Operand(esp, 0), source); 146 __ mov(Operand(esp, 0), source);
158 break; 147 break;
159 } 148 }
160 } 149 }
161 150
162 151
163 void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { 152 void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
164 // Call the runtime to declare the globals. 153 // Call the runtime to declare the globals.
165 __ push(esi); // The context is the first argument. 154 __ push(esi); // The context is the first argument.
166 __ push(Immediate(pairs)); 155 __ push(Immediate(pairs));
167 __ push(Immediate(Smi::FromInt(is_eval_ ? 1 : 0))); 156 __ push(Immediate(Smi::FromInt(is_eval_ ? 1 : 0)));
168 __ CallRuntime(Runtime::kDeclareGlobals, 3); 157 __ CallRuntime(Runtime::kDeclareGlobals, 3);
169 // Return value is ignored. 158 // Return value is ignored.
170 } 159 }
171 160
172 161
173 void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { 162 void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
174 Comment cmnt(masm_, "[ ReturnStatement"); 163 Comment cmnt(masm_, "[ ReturnStatement");
175 SetStatementPosition(stmt); 164 SetStatementPosition(stmt);
176 Expression* expr = stmt->expression(); 165 Expression* expr = stmt->expression();
177 // Complete the statement based on the type of the subexpression. 166 Visit(expr);
178 if (expr->AsLiteral() != NULL) { 167 ASSERT_EQ(Expression::kValue, expr->context());
179 __ mov(eax, expr->AsLiteral()->handle()); 168 __ pop(eax);
William Hesse 2009/10/29 15:15:25 Restore optimization?
Kevin Millikin (Chromium) 2009/10/29 16:36:10 Done.
180 } else {
181 Visit(expr);
182 Move(eax, expr->location());
183 }
184 169
185 if (FLAG_trace) { 170 if (FLAG_trace) {
186 __ push(eax); 171 __ push(eax);
187 __ CallRuntime(Runtime::kTraceExit, 1); 172 __ CallRuntime(Runtime::kTraceExit, 1);
188 } 173 }
189 __ RecordJSReturn(); 174 __ RecordJSReturn();
190 175
191 // Do not use the leave instruction here because it is too short to 176 // Do not use the leave instruction here because it is too short to
192 // patch with the code required by the debugger. 177 // patch with the code required by the debugger.
193 __ mov(esp, ebp); 178 __ mov(esp, ebp);
194 __ pop(ebp); 179 __ pop(ebp);
195 __ ret((function_->scope()->num_parameters() + 1) * kPointerSize); 180 __ ret((function_->scope()->num_parameters() + 1) * kPointerSize);
196 } 181 }
197 182
198 183
199 void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { 184 void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
200 Comment cmnt(masm_, "[ FunctionLiteral"); 185 Comment cmnt(masm_, "[ FunctionLiteral");
201 186
202 // Build the function boilerplate and instantiate it. 187 // Build the function boilerplate and instantiate it.
203 Handle<JSFunction> boilerplate = BuildBoilerplate(expr); 188 Handle<JSFunction> boilerplate = BuildBoilerplate(expr);
204 if (HasStackOverflow()) return; 189 if (HasStackOverflow()) return;
205 190
206 ASSERT(boilerplate->IsBoilerplate()); 191 ASSERT(boilerplate->IsBoilerplate());
207 192
208 // Create a new closure. 193 // Create a new closure.
209 __ push(esi); 194 __ push(esi);
210 __ push(Immediate(boilerplate)); 195 __ push(Immediate(boilerplate));
211 __ CallRuntime(Runtime::kNewClosure, 2); 196 __ CallRuntime(Runtime::kNewClosure, 2);
212 Move(expr->location(), eax); 197 Move(expr->context(), eax);
213 } 198 }
214 199
215 200
216 void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) { 201 void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
217 Comment cmnt(masm_, "[ VariableProxy"); 202 Comment cmnt(masm_, "[ VariableProxy");
218 Expression* rewrite = expr->var()->rewrite(); 203 Expression* rewrite = expr->var()->rewrite();
219 if (rewrite == NULL) { 204 if (rewrite == NULL) {
220 Comment cmnt(masm_, "Global variable"); 205 Comment cmnt(masm_, "Global variable");
221 // Use inline caching. Variable name is passed in ecx and the global 206 // Use inline caching. Variable name is passed in ecx and the global
222 // object on the stack. 207 // object on the stack.
223 __ push(CodeGenerator::GlobalObject()); 208 __ push(CodeGenerator::GlobalObject());
224 __ mov(ecx, expr->name()); 209 __ mov(ecx, expr->name());
225 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 210 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
226 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT); 211 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT);
227 // By emitting a nop we make sure that we do not have a test eax 212 // By emitting a nop we make sure that we do not have a test eax
228 // instruction after the call it is treated specially by the LoadIC code 213 // instruction after the call it is treated specially by the LoadIC code
229 // Remember that the assembler may choose to do peephole optimization 214 // Remember that the assembler may choose to do peephole optimization
230 // (eg, push/pop elimination). 215 // (eg, push/pop elimination).
231 __ nop(); 216 __ nop();
232 217
233 DropAndMove(expr->location(), eax); 218 DropAndMove(expr->context(), eax);
234 } else { 219 } else {
235 Comment cmnt(masm_, "Stack slot"); 220 Comment cmnt(masm_, "Stack slot");
236 Move(expr->location(), rewrite->AsSlot()); 221 Move(expr->context(), rewrite->AsSlot());
237 } 222 }
238 } 223 }
239 224
240 225
241 void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { 226 void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
242 Comment cmnt(masm_, "[ RegExp Literal"); 227 Comment cmnt(masm_, "[ RegExp Literal");
243 Label done; 228 Label done;
244 // Registers will be used as follows: 229 // Registers will be used as follows:
245 // edi = JS function. 230 // edi = JS function.
246 // ebx = literals array. 231 // ebx = literals array.
247 // eax = regexp literal. 232 // eax = regexp literal.
248 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 233 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
249 __ mov(ebx, FieldOperand(edi, JSFunction::kLiteralsOffset)); 234 __ mov(ebx, FieldOperand(edi, JSFunction::kLiteralsOffset));
250 int literal_offset = 235 int literal_offset =
251 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; 236 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize;
252 __ mov(eax, FieldOperand(ebx, literal_offset)); 237 __ mov(eax, FieldOperand(ebx, literal_offset));
253 __ cmp(eax, Factory::undefined_value()); 238 __ cmp(eax, Factory::undefined_value());
254 __ j(not_equal, &done); 239 __ j(not_equal, &done);
255 // Create regexp literal using runtime function 240 // Create regexp literal using runtime function
256 // Result will be in eax. 241 // Result will be in eax.
257 __ push(ebx); 242 __ push(ebx);
258 __ push(Immediate(Smi::FromInt(expr->literal_index()))); 243 __ push(Immediate(Smi::FromInt(expr->literal_index())));
259 __ push(Immediate(expr->pattern())); 244 __ push(Immediate(expr->pattern()));
260 __ push(Immediate(expr->flags())); 245 __ push(Immediate(expr->flags()));
261 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); 246 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
262 // Label done: 247 // Label done:
263 __ bind(&done); 248 __ bind(&done);
264 Move(expr->location(), eax); 249 Move(expr->context(), eax);
265 } 250 }
266 251
267 252
268 void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { 253 void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
269 Comment cmnt(masm_, "[ ObjectLiteral"); 254 Comment cmnt(masm_, "[ ObjectLiteral");
270 Label exists; 255 Label exists;
271 // Registers will be used as follows: 256 // Registers will be used as follows:
272 // edi = JS function. 257 // edi = JS function.
273 // ebx = literals array. 258 // ebx = literals array.
274 // eax = boilerplate 259 // eax = boilerplate
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
311 if (!result_saved) { 296 if (!result_saved) {
312 __ push(eax); // Save result on the stack 297 __ push(eax); // Save result on the stack
313 result_saved = true; 298 result_saved = true;
314 } 299 }
315 switch (property->kind()) { 300 switch (property->kind()) {
316 case ObjectLiteral::Property::MATERIALIZED_LITERAL: // fall through 301 case ObjectLiteral::Property::MATERIALIZED_LITERAL: // fall through
317 ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); 302 ASSERT(!CompileTimeValue::IsCompileTimeValue(value));
318 case ObjectLiteral::Property::COMPUTED: 303 case ObjectLiteral::Property::COMPUTED:
319 if (key->handle()->IsSymbol()) { 304 if (key->handle()->IsSymbol()) {
320 Visit(value); 305 Visit(value);
321 Move(eax, value->location()); 306 ASSERT_EQ(Expression::kValue, value->context());
307 __ pop(eax);
322 __ mov(ecx, Immediate(key->handle())); 308 __ mov(ecx, Immediate(key->handle()));
323 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 309 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
324 __ call(ic, RelocInfo::CODE_TARGET); 310 __ call(ic, RelocInfo::CODE_TARGET);
325 // StoreIC leaves the receiver on the stack. 311 // StoreIC leaves the receiver on the stack.
326 break; 312 break;
327 } 313 }
328 // fall through 314 // fall through
329 case ObjectLiteral::Property::PROTOTYPE: 315 case ObjectLiteral::Property::PROTOTYPE:
330 __ push(eax); 316 __ push(eax);
331 Visit(key); 317 Visit(key);
332 ASSERT(key->location().is_value()); 318 ASSERT_EQ(Expression::kValue, key->context());
333 Visit(value); 319 Visit(value);
334 ASSERT(value->location().is_value()); 320 ASSERT_EQ(Expression::kValue, value->context());
335 __ CallRuntime(Runtime::kSetProperty, 3); 321 __ CallRuntime(Runtime::kSetProperty, 3);
336 __ mov(eax, Operand(esp, 0)); // Restore result into eax. 322 __ mov(eax, Operand(esp, 0)); // Restore result into eax.
337 break; 323 break;
338 case ObjectLiteral::Property::SETTER: // fall through 324 case ObjectLiteral::Property::SETTER: // fall through
339 case ObjectLiteral::Property::GETTER: 325 case ObjectLiteral::Property::GETTER:
340 __ push(eax); 326 __ push(eax);
341 Visit(key); 327 Visit(key);
342 ASSERT(key->location().is_value()); 328 ASSERT_EQ(Expression::kValue, key->context());
343 __ push(Immediate(property->kind() == ObjectLiteral::Property::SETTER ? 329 __ push(Immediate(property->kind() == ObjectLiteral::Property::SETTER ?
344 Smi::FromInt(1) : 330 Smi::FromInt(1) :
345 Smi::FromInt(0))); 331 Smi::FromInt(0)));
346 Visit(value); 332 Visit(value);
347 ASSERT(value->location().is_value()); 333 ASSERT_EQ(Expression::kValue, value->context());
348 __ CallRuntime(Runtime::kDefineAccessor, 4); 334 __ CallRuntime(Runtime::kDefineAccessor, 4);
349 __ mov(eax, Operand(esp, 0)); // Restore result into eax. 335 __ mov(eax, Operand(esp, 0)); // Restore result into eax.
350 break; 336 break;
351 default: UNREACHABLE(); 337 default: UNREACHABLE();
352 } 338 }
353 } 339 }
354 switch (expr->location().type()) { 340 switch (expr->context()) {
355 case Location::kUninitialized: 341 case Expression::kUninitialized:
356 UNREACHABLE(); 342 UNREACHABLE();
357 case Location::kEffect: 343 case Expression::kEffect:
358 if (result_saved) __ add(Operand(esp), Immediate(kPointerSize)); 344 if (result_saved) __ add(Operand(esp), Immediate(kPointerSize));
359 break; 345 break;
360 case Location::kValue: 346 case Expression::kValue:
361 if (!result_saved) __ push(eax); 347 if (!result_saved) __ push(eax);
362 break; 348 break;
363 } 349 }
364 } 350 }
365 351
366 352
367 void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { 353 void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
368 Comment cmnt(masm_, "[ ArrayLiteral"); 354 Comment cmnt(masm_, "[ ArrayLiteral");
369 Label make_clone; 355 Label make_clone;
370 356
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
405 if (subexpr->AsLiteral() != NULL || 391 if (subexpr->AsLiteral() != NULL ||
406 CompileTimeValue::IsCompileTimeValue(subexpr)) { 392 CompileTimeValue::IsCompileTimeValue(subexpr)) {
407 continue; 393 continue;
408 } 394 }
409 395
410 if (!result_saved) { 396 if (!result_saved) {
411 __ push(eax); 397 __ push(eax);
412 result_saved = true; 398 result_saved = true;
413 } 399 }
414 Visit(subexpr); 400 Visit(subexpr);
415 ASSERT(subexpr->location().is_value()); 401 ASSERT_EQ(Expression::kValue, subexpr->context());
416 402
417 // Store the subexpression value in the array's elements. 403 // Store the subexpression value in the array's elements.
418 __ pop(eax); // Subexpression value. 404 __ pop(eax); // Subexpression value.
419 __ mov(ebx, Operand(esp, 0)); // Copy of array literal. 405 __ mov(ebx, Operand(esp, 0)); // Copy of array literal.
420 __ mov(ebx, FieldOperand(ebx, JSObject::kElementsOffset)); 406 __ mov(ebx, FieldOperand(ebx, JSObject::kElementsOffset));
421 int offset = FixedArray::kHeaderSize + (i * kPointerSize); 407 int offset = FixedArray::kHeaderSize + (i * kPointerSize);
422 __ mov(FieldOperand(ebx, offset), eax); 408 __ mov(FieldOperand(ebx, offset), eax);
423 409
424 // Update the write barrier for the array store. 410 // Update the write barrier for the array store.
425 __ RecordWrite(ebx, offset, eax, ecx); 411 __ RecordWrite(ebx, offset, eax, ecx);
426 } 412 }
427 413
428 switch (expr->location().type()) { 414 switch (expr->context()) {
429 case Location::kUninitialized: 415 case Expression::kUninitialized:
430 UNREACHABLE(); 416 UNREACHABLE();
431 case Location::kEffect: 417 case Expression::kEffect:
432 if (result_saved) __ add(Operand(esp), Immediate(kPointerSize)); 418 if (result_saved) __ add(Operand(esp), Immediate(kPointerSize));
433 break; 419 break;
434 case Location::kValue: 420 case Expression::kValue:
435 if (!result_saved) __ push(eax); 421 if (!result_saved) __ push(eax);
436 break; 422 break;
437 } 423 }
438 } 424 }
439 425
440 426
441 void FastCodeGenerator::VisitAssignment(Assignment* expr) { 427 void FastCodeGenerator::VisitAssignment(Assignment* expr) {
442 Comment cmnt(masm_, "[ Assignment"); 428 Comment cmnt(masm_, "[ Assignment");
443 ASSERT(expr->op() == Token::ASSIGN || expr->op() == Token::INIT_VAR); 429 ASSERT(expr->op() == Token::ASSIGN || expr->op() == Token::INIT_VAR);
444 430
445 // Left-hand side can only be a global or a (parameter or local) slot. 431 // Left-hand side can only be a global or a (parameter or local) slot.
446 Variable* var = expr->target()->AsVariableProxy()->AsVariable(); 432 Variable* var = expr->target()->AsVariableProxy()->AsVariable();
447 ASSERT(var != NULL); 433 ASSERT(var != NULL);
448 ASSERT(var->is_global() || var->slot() != NULL); 434 ASSERT(var->is_global() || var->slot() != NULL);
449 435
450 Expression* rhs = expr->value(); 436 Expression* rhs = expr->value();
451 if (var->is_global()) { 437 if (var->is_global()) {
452 // Assignment to a global variable, use inline caching. Right-hand-side 438 // Assignment to a global variable, use inline caching. Right-hand-side
453 // value is passed in eax, variable name in ecx, and the global object 439 // value is passed in eax, variable name in ecx, and the global object
454 // on the stack. 440 // on the stack.
455 441
456 // Code for the right-hand-side expression depends on its type. 442 // Code for the right-hand-side expression depends on its type.
457 if (rhs->AsLiteral() != NULL) { 443 if (rhs->AsLiteral() != NULL) {
458 __ mov(eax, rhs->AsLiteral()->handle()); 444 __ mov(eax, rhs->AsLiteral()->handle());
459 } else { 445 } else {
460 ASSERT(rhs->location().is_value()); 446 ASSERT_EQ(Expression::kValue, rhs->context());
461 Visit(rhs); 447 Visit(rhs);
462 __ pop(eax); 448 __ pop(eax);
463 } 449 }
464 __ mov(ecx, var->name()); 450 __ mov(ecx, var->name());
465 __ push(CodeGenerator::GlobalObject()); 451 __ push(CodeGenerator::GlobalObject());
466 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 452 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
467 __ call(ic, RelocInfo::CODE_TARGET); 453 __ call(ic, RelocInfo::CODE_TARGET);
468 // Overwrite the global object on the stack with the result if needed. 454 // Overwrite the global object on the stack with the result if needed.
469 DropAndMove(expr->location(), eax); 455 DropAndMove(expr->context(), eax);
470 } else { 456 } else {
471 // Local or parameter assignment. 457 // Local or parameter assignment.
472 458
473 // Code for the right-hand side expression depends on its type. 459 // Code for the right-hand side expression depends on its type.
474 if (rhs->AsLiteral() != NULL) { 460 if (rhs->AsLiteral() != NULL) {
475 // Two cases: 'temp <- (var = constant)', or 'var = constant' with a 461 // Two cases: 'temp <- (var = constant)', or 'var = constant' with a
476 // discarded result. Always perform the assignment. 462 // discarded result. Always perform the assignment.
477 __ mov(eax, rhs->AsLiteral()->handle()); 463 __ mov(eax, rhs->AsLiteral()->handle());
478 __ mov(Operand(ebp, SlotOffset(var->slot())), eax); 464 __ mov(Operand(ebp, SlotOffset(var->slot())), eax);
479 Move(expr->location(), eax); 465 Move(expr->context(), eax);
480 } else { 466 } else {
481 ASSERT(rhs->location().is_value()); 467 ASSERT_EQ(Expression::kValue, rhs->context());
482 Visit(rhs); 468 Visit(rhs);
483 switch (expr->location().type()) { 469 switch (expr->context()) {
484 case Location::kUninitialized: 470 case Expression::kUninitialized:
485 UNREACHABLE(); 471 UNREACHABLE();
486 case Location::kEffect: 472 case Expression::kEffect:
487 // Case 'var = temp'. Discard right-hand-side temporary. 473 // Case 'var = temp'. Discard right-hand-side temporary.
488 Move(var->slot(), rhs->location()); 474 __ pop(Operand(ebp, SlotOffset(var->slot())));
489 break; 475 break;
490 case Location::kValue: 476 case Expression::kValue:
491 // Case 'temp1 <- (var = temp0)'. Preserve right-hand-side 477 // Case 'temp1 <- (var = temp0)'. Preserve right-hand-side
492 // temporary on the stack. 478 // temporary on the stack.
493 __ mov(eax, Operand(esp, 0)); 479 __ mov(eax, Operand(esp, 0));
494 __ mov(Operand(ebp, SlotOffset(var->slot())), eax); 480 __ mov(Operand(ebp, SlotOffset(var->slot())), eax);
495 break; 481 break;
496 } 482 }
497 } 483 }
498 } 484 }
499 } 485 }
500 486
(...skipping 23 matching lines...) Expand all
524 // Do a KEYED property load. 510 // Do a KEYED property load.
525 Visit(expr->key()); 511 Visit(expr->key());
526 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 512 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
527 __ call(ic, RelocInfo::CODE_TARGET); 513 __ call(ic, RelocInfo::CODE_TARGET);
528 // By emitting a nop we make sure that we do not have a "test eax,..." 514 // By emitting a nop we make sure that we do not have a "test eax,..."
529 // instruction after the call it is treated specially by the LoadIC code. 515 // instruction after the call it is treated specially by the LoadIC code.
530 __ nop(); 516 __ nop();
531 // Drop key left on the stack by IC. 517 // Drop key left on the stack by IC.
532 __ add(Operand(esp), Immediate(kPointerSize)); 518 __ add(Operand(esp), Immediate(kPointerSize));
533 } 519 }
534 switch (expr->location().type()) { 520 DropAndMove(expr->context(), eax);
535 case Location::kUninitialized:
536 UNREACHABLE();
537 case Location::kValue:
538 __ mov(Operand(esp, 0), eax);
539 break;
540 case Location::kEffect:
541 __ add(Operand(esp), Immediate(kPointerSize));
542 break;
543 }
544 } 521 }
545 522
546 523
547 void FastCodeGenerator::VisitCall(Call* expr) { 524 void FastCodeGenerator::VisitCall(Call* expr) {
548 Expression* fun = expr->expression(); 525 Expression* fun = expr->expression();
549 ZoneList<Expression*>* args = expr->arguments(); 526 ZoneList<Expression*>* args = expr->arguments();
550 Variable* var = fun->AsVariableProxy()->AsVariable(); 527 Variable* var = fun->AsVariableProxy()->AsVariable();
551 ASSERT(var != NULL && !var->is_this() && var->is_global()); 528 ASSERT(var != NULL && !var->is_this() && var->is_global());
552 ASSERT(!var->is_possibly_eval()); 529 ASSERT(!var->is_possibly_eval());
553 530
554 __ push(Immediate(var->name())); 531 __ push(Immediate(var->name()));
555 // Push global object (receiver). 532 // Push global object (receiver).
556 __ push(CodeGenerator::GlobalObject()); 533 __ push(CodeGenerator::GlobalObject());
557 int arg_count = args->length(); 534 int arg_count = args->length();
558 for (int i = 0; i < arg_count; i++) { 535 for (int i = 0; i < arg_count; i++) {
559 Visit(args->at(i)); 536 Visit(args->at(i));
560 ASSERT(args->at(i)->location().is_value()); 537 ASSERT_EQ(Expression::kValue, args->at(i)->context());
561 } 538 }
562 // Record source position for debugger 539 // Record source position for debugger
563 SetSourcePosition(expr->position()); 540 SetSourcePosition(expr->position());
564 // Call the IC initialization code. 541 // Call the IC initialization code.
565 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, 542 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count,
566 NOT_IN_LOOP); 543 NOT_IN_LOOP);
567 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT); 544 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT);
568 // Restore context register. 545 // Restore context register.
569 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 546 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
570 // Discard the function left on TOS. 547 // Discard the function left on TOS.
571 DropAndMove(expr->location(), eax); 548 DropAndMove(expr->context(), eax);
572 } 549 }
573 550
574 551
575 void FastCodeGenerator::VisitCallNew(CallNew* node) { 552 void FastCodeGenerator::VisitCallNew(CallNew* expr) {
576 Comment cmnt(masm_, "[ CallNew"); 553 Comment cmnt(masm_, "[ CallNew");
577 // According to ECMA-262, section 11.2.2, page 44, the function 554 // According to ECMA-262, section 11.2.2, page 44, the function
578 // expression in new calls must be evaluated before the 555 // expression in new calls must be evaluated before the
579 // arguments. 556 // arguments.
580 // Push function on the stack. 557 // Push function on the stack.
581 Visit(node->expression()); 558 Visit(expr->expression());
582 ASSERT(node->expression()->location().is_value()); 559 ASSERT_EQ(Expression::kValue, expr->expression()->context());
583 560
584 // Push global object (receiver). 561 // Push global object (receiver).
585 __ push(CodeGenerator::GlobalObject()); 562 __ push(CodeGenerator::GlobalObject());
586 563
587 // Push the arguments ("left-to-right") on the stack. 564 // Push the arguments ("left-to-right") on the stack.
588 ZoneList<Expression*>* args = node->arguments(); 565 ZoneList<Expression*>* args = expr->arguments();
589 int arg_count = args->length(); 566 int arg_count = args->length();
590 for (int i = 0; i < arg_count; i++) { 567 for (int i = 0; i < arg_count; i++) {
591 Visit(args->at(i)); 568 Visit(args->at(i));
592 ASSERT(args->at(i)->location().is_value()); 569 ASSERT_EQ(Expression::kValue, args->at(i)->context());
593 // If location is value, it is already on the stack, 570 // If location is value, it is already on the stack,
594 // so nothing to do here. 571 // so nothing to do here.
595 } 572 }
596 573
597 // Call the construct call builtin that handles allocation and 574 // Call the construct call builtin that handles allocation and
598 // constructor invocation. 575 // constructor invocation.
599 SetSourcePosition(node->position()); 576 SetSourcePosition(expr->position());
600 577
601 // Load function, arg_count into edi and eax. 578 // Load function, arg_count into edi and eax.
602 __ Set(eax, Immediate(arg_count)); 579 __ Set(eax, Immediate(arg_count));
603 // Function is in esp[arg_count + 1]. 580 // Function is in esp[arg_count + 1].
604 __ mov(edi, Operand(esp, eax, times_pointer_size, kPointerSize)); 581 __ mov(edi, Operand(esp, eax, times_pointer_size, kPointerSize));
605 582
606 Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall)); 583 Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall));
607 __ call(construct_builtin, RelocInfo::CONSTRUCT_CALL); 584 __ call(construct_builtin, RelocInfo::CONSTRUCT_CALL);
608 585
609 // Replace function on TOS with result in eax, or pop it. 586 // Replace function on TOS with result in eax, or pop it.
610 DropAndMove(node->location(), eax); 587 DropAndMove(expr->context(), eax);
611 } 588 }
612 589
613 590
614 void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) { 591 void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
615 Comment cmnt(masm_, "[ CallRuntime"); 592 Comment cmnt(masm_, "[ CallRuntime");
616 ZoneList<Expression*>* args = expr->arguments(); 593 ZoneList<Expression*>* args = expr->arguments();
617 Runtime::Function* function = expr->function(); 594 Runtime::Function* function = expr->function();
618 595
619 ASSERT(function != NULL); 596 ASSERT(function != NULL);
620 597
621 // Push the arguments ("left-to-right"). 598 // Push the arguments ("left-to-right").
622 int arg_count = args->length(); 599 int arg_count = args->length();
623 for (int i = 0; i < arg_count; i++) { 600 for (int i = 0; i < arg_count; i++) {
624 Visit(args->at(i)); 601 Visit(args->at(i));
625 ASSERT(args->at(i)->location().is_value()); 602 ASSERT_EQ(Expression::kValue, args->at(i)->context());
626 } 603 }
627 604
628 __ CallRuntime(function, arg_count); 605 __ CallRuntime(function, arg_count);
629 Move(expr->location(), eax); 606 Move(expr->context(), eax);
630 } 607 }
631 608
632 609
633 void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { 610 void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
634 switch (expr->op()) { 611 switch (expr->op()) {
635 case Token::COMMA: 612 case Token::COMMA:
636 ASSERT(expr->left()->location().is_effect()); 613 ASSERT_EQ(Expression::kValue, expr->left()->context());
637 ASSERT_EQ(expr->right()->location().type(), expr->location().type()); 614 ASSERT_EQ(expr->context(), expr->right()->context());
638 Visit(expr->left()); 615 Visit(expr->left());
639 Visit(expr->right()); 616 Visit(expr->right());
640 break; 617 break;
641 618
642 case Token::OR: 619 case Token::OR:
643 case Token::AND: 620 case Token::AND:
644 EmitLogicalOperation(expr); 621 EmitLogicalOperation(expr);
645 break; 622 break;
646 623
647 case Token::ADD: 624 case Token::ADD:
648 case Token::SUB: 625 case Token::SUB:
649 case Token::DIV: 626 case Token::DIV:
650 case Token::MOD: 627 case Token::MOD:
651 case Token::MUL: 628 case Token::MUL:
652 case Token::BIT_OR: 629 case Token::BIT_OR:
653 case Token::BIT_AND: 630 case Token::BIT_AND:
654 case Token::BIT_XOR: 631 case Token::BIT_XOR:
655 case Token::SHL: 632 case Token::SHL:
656 case Token::SHR: 633 case Token::SHR:
657 case Token::SAR: { 634 case Token::SAR: {
658 ASSERT(expr->left()->location().is_value()); 635 ASSERT_EQ(Expression::kValue, expr->left()->context());
659 ASSERT(expr->right()->location().is_value()); 636 ASSERT_EQ(Expression::kValue, expr->right()->context());
660 637
661 Visit(expr->left()); 638 Visit(expr->left());
662 Visit(expr->right()); 639 Visit(expr->right());
663 GenericBinaryOpStub stub(expr->op(), 640 GenericBinaryOpStub stub(expr->op(),
664 NO_OVERWRITE, 641 NO_OVERWRITE,
665 NO_GENERIC_BINARY_FLAGS); 642 NO_GENERIC_BINARY_FLAGS);
666 __ CallStub(&stub); 643 __ CallStub(&stub);
667 Move(expr->location(), eax); 644 Move(expr->context(), eax);
668 645
669 break; 646 break;
670 } 647 }
671 default: 648 default:
672 UNREACHABLE(); 649 UNREACHABLE();
673 } 650 }
674 } 651 }
675 652
676 653
677 void FastCodeGenerator::EmitLogicalOperation(BinaryOperation* expr) { 654 void FastCodeGenerator::EmitLogicalOperation(BinaryOperation* expr) {
678 // Compile a short-circuited boolean operation in a non-test context. 655 // Compile a short-circuited boolean operation in a non-test context.
679 656
680 // Compile (e0 || e1) or (e0 && e1) as if it were 657 // Compile (e0 || e1) or (e0 && e1) as if it were
681 // (let (temp = e0) temp [or !temp, for &&] ? temp : e1). 658 // (let (temp = e0) temp [or !temp, for &&] ? temp : e1).
682 659
683 Label eval_right, done; 660 Label eval_right, done;
684 Label *left_true, *left_false; // Where to branch to if lhs has that value. 661 Label *left_true, *left_false; // Where to branch to if lhs has that value.
685 if (expr->op() == Token::OR) { 662 if (expr->op() == Token::OR) {
686 left_true = &done; 663 left_true = &done;
687 left_false = &eval_right; 664 left_false = &eval_right;
688 } else { 665 } else {
689 left_true = &eval_right; 666 left_true = &eval_right;
690 left_false = &done; 667 left_false = &done;
691 } 668 }
692 Location destination = expr->location(); 669 Expression::Context context = expr->context();
693 Expression* left = expr->left(); 670 Expression* left = expr->left();
694 Expression* right = expr->right(); 671 Expression* right = expr->right();
695 672
696 // Use the shared ToBoolean stub to find the boolean value of the 673 // Use the shared ToBoolean stub to find the boolean value of the
697 // left-hand subexpression. Load the value into eax to perform some 674 // left-hand subexpression. Load the value into eax to perform some
698 // inlined checks assumed by the stub. 675 // inlined checks assumed by the stub.
699 676
700 // Compile the left-hand value into eax. Put it on the stack if we may 677 // Compile the left-hand value into eax. Put it on the stack if we may
701 // need it as the value of the whole expression. 678 // need it as the value of the whole expression.
702 if (left->AsLiteral() != NULL) { 679 if (left->AsLiteral() != NULL) {
703 __ mov(eax, left->AsLiteral()->handle()); 680 __ mov(eax, left->AsLiteral()->handle());
704 if (destination.is_value()) __ push(eax); 681 if (context == Expression::kValue) __ push(eax);
705 } else { 682 } else {
706 Visit(left); 683 Visit(left);
707 ASSERT(left->location().is_value()); 684 ASSERT_EQ(Expression::kValue, left->context());
708 switch (destination.type()) { 685 switch (context) {
709 case Location::kUninitialized: 686 case Expression::kUninitialized:
710 UNREACHABLE(); 687 UNREACHABLE();
711 case Location::kEffect: 688 case Expression::kEffect:
712 // Pop the left-hand value into eax because we will not need it as the 689 // Pop the left-hand value into eax because we will not need it as the
713 // final result. 690 // final result.
714 __ pop(eax); 691 __ pop(eax);
715 break; 692 break;
716 case Location::kValue: 693 case Expression::kValue:
717 // Copy the left-hand value into eax because we may need it as the 694 // Copy the left-hand value into eax because we may need it as the
718 // final result. 695 // final result.
719 __ mov(eax, Operand(esp, 0)); 696 __ mov(eax, Operand(esp, 0));
720 break; 697 break;
721 } 698 }
722 } 699 }
723 // The left-hand value is in eax. It is also on the stack iff the 700 // The left-hand value is in eax. It is also on the stack iff the
724 // destination location is value. 701 // destination location is value.
725 702
726 // Perform fast checks assumed by the stub. 703 // Perform fast checks assumed by the stub.
727 __ cmp(eax, Factory::undefined_value()); // The undefined value is false. 704 __ cmp(eax, Factory::undefined_value()); // The undefined value is false.
728 __ j(equal, left_false); 705 __ j(equal, left_false);
729 __ cmp(eax, Factory::true_value()); // True is true. 706 __ cmp(eax, Factory::true_value()); // True is true.
730 __ j(equal, left_true); 707 __ j(equal, left_true);
731 __ cmp(eax, Factory::false_value()); // False is false. 708 __ cmp(eax, Factory::false_value()); // False is false.
732 __ j(equal, left_false); 709 __ j(equal, left_false);
733 ASSERT(kSmiTag == 0); 710 ASSERT_EQ(0, kSmiTag);
734 __ test(eax, Operand(eax)); // The smi zero is false. 711 __ test(eax, Operand(eax)); // The smi zero is false.
735 __ j(zero, left_false); 712 __ j(zero, left_false);
736 __ test(eax, Immediate(kSmiTagMask)); // All other smis are true. 713 __ test(eax, Immediate(kSmiTagMask)); // All other smis are true.
737 __ j(zero, left_true); 714 __ j(zero, left_true);
738 715
739 // Call the stub for all other cases. 716 // Call the stub for all other cases.
740 __ push(eax); 717 __ push(eax);
741 ToBooleanStub stub; 718 ToBooleanStub stub;
742 __ CallStub(&stub); 719 __ CallStub(&stub);
743 __ test(eax, Operand(eax)); // The stub returns nonzero for true. 720 __ test(eax, Operand(eax)); // The stub returns nonzero for true.
744 if (expr->op() == Token::OR) { 721 if (expr->op() == Token::OR) {
745 __ j(not_zero, &done); 722 __ j(not_zero, &done);
746 } else { 723 } else {
747 __ j(zero, &done); 724 __ j(zero, &done);
748 } 725 }
749 726
750 __ bind(&eval_right); 727 __ bind(&eval_right);
751 // Discard the left-hand value if present on the stack. 728 // Discard the left-hand value if present on the stack.
752 if (destination.is_value()) { 729 if (context == Expression::kValue) {
753 __ add(Operand(esp), Immediate(kPointerSize)); 730 __ add(Operand(esp), Immediate(kPointerSize));
754 } 731 }
755 // Save or discard the right-hand value as needed. 732 // Save or discard the right-hand value as needed.
756 Visit(right); 733 Visit(right);
757 ASSERT_EQ(destination.type(), right->location().type()); 734 ASSERT_EQ(context, right->context());
758 735
759 __ bind(&done); 736 __ bind(&done);
760 } 737 }
761 738
762 739
763 } } // namespace v8::internal 740 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698