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

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

Issue 546006: Some cleanup of the toplevel code generator:... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 11 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 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
187 #ifdef ENABLE_DEBUGGER_SUPPORT 187 #ifdef ENABLE_DEBUGGER_SUPPORT
188 // Check that the size of the code used for returning matches what is 188 // Check that the size of the code used for returning matches what is
189 // expected by the debugger. 189 // expected by the debugger.
190 ASSERT_EQ(Assembler::kJSReturnSequenceLength, 190 ASSERT_EQ(Assembler::kJSReturnSequenceLength,
191 masm_->SizeOfCodeGeneratedSince(&check_exit_codesize)); 191 masm_->SizeOfCodeGeneratedSince(&check_exit_codesize));
192 #endif 192 #endif
193 } 193 }
194 } 194 }
195 195
196 196
197 void FastCodeGenerator::Move(Expression::Context context, Register source) { 197 void FastCodeGenerator::Apply(Expression::Context context,
198 Slot* slot,
199 Register scratch) {
Lasse Reichstein 2010/01/12 08:30:05 This function looks generic enough that it could b
200 switch (context) {
201 case Expression::kUninitialized:
202 UNREACHABLE();
203 case Expression::kEffect:
204 break;
205 case Expression::kValue: {
206 MemOperand location = EmitSlotSearch(slot, scratch);
207 __ push(location);
208 break;
209 }
210 case Expression::kTest:
211 case Expression::kValueTest:
212 case Expression::kTestValue:
213 Move(scratch, slot);
214 Apply(context, scratch);
215 break;
216 }
217 }
218
219
220 void FastCodeGenerator::Apply(Expression::Context context, Literal* lit) {
Lasse Reichstein 2010/01/12 08:30:05 If we had MacroAssembler::Push(Handle<Object> sour
198 switch (context) { 221 switch (context) {
199 case Expression::kUninitialized: 222 case Expression::kUninitialized:
200 UNREACHABLE(); 223 UNREACHABLE();
201 case Expression::kEffect: 224 case Expression::kEffect:
202 break; 225 break;
203 case Expression::kValue: 226 case Expression::kValue:
204 __ push(source); 227 __ push(Immediate(lit->handle()));
205 break; 228 break;
206 case Expression::kTest: 229 case Expression::kTest:
207 TestAndBranch(source, true_label_, false_label_); 230 case Expression::kValueTest:
231 case Expression::kTestValue:
232 __ mov(eax, lit->handle());
233 Apply(context, eax);
208 break; 234 break;
209 case Expression::kValueTest: {
210 Label discard;
211 __ push(source);
212 TestAndBranch(source, true_label_, &discard);
213 __ bind(&discard);
214 __ add(Operand(esp), Immediate(kPointerSize));
215 __ jmp(false_label_);
216 break;
217 }
218 case Expression::kTestValue: {
219 Label discard;
220 __ push(source);
221 TestAndBranch(source, &discard, false_label_);
222 __ bind(&discard);
223 __ add(Operand(esp), Immediate(kPointerSize));
224 __ jmp(true_label_);
225 }
226 } 235 }
227 } 236 }
228 237
229 238
230 void FastCodeGenerator::MoveTOS(Expression::Context context) { 239 void FastCodeGenerator::ApplyTOS(Expression::Context context) {
231 switch (context) { 240 switch (context) {
232 case Expression::kUninitialized: 241 case Expression::kUninitialized:
233 UNREACHABLE(); 242 UNREACHABLE();
234 case Expression::kEffect: 243 case Expression::kEffect:
235 __ Drop(1); 244 __ Drop(1);
236 break; 245 break;
237 case Expression::kValue: 246 case Expression::kValue:
238 break; 247 break;
239 case Expression::kTest: 248 case Expression::kTest:
240 __ pop(eax); 249 __ pop(eax);
241 TestAndBranch(eax, true_label_, false_label_); 250 TestAndBranch(eax, true_label_, false_label_);
242 break; 251 break;
243 case Expression::kValueTest: { 252 case Expression::kValueTest: {
244 Label discard; 253 Label discard;
245 __ mov(eax, Operand(esp, 0)); 254 __ mov(eax, Operand(esp, 0));
Lasse Reichstein 2010/01/12 08:30:05 With a function like MacroAssembler::MoveToStack(i
246 TestAndBranch(eax, true_label_, &discard); 255 TestAndBranch(eax, true_label_, &discard);
247 __ bind(&discard); 256 __ bind(&discard);
248 __ Drop(1); 257 __ Drop(1);
249 __ jmp(false_label_); 258 __ jmp(false_label_);
259 break;
260 }
261 case Expression::kTestValue: {
262 Label discard;
263 __ mov(eax, Operand(esp, 0));
264 TestAndBranch(eax, &discard, false_label_);
265 __ bind(&discard);
266 __ Drop(1);
267 __ jmp(true_label_);
268 }
269 }
270 }
271
272
273 void FastCodeGenerator::DropAndApply(int count,
274 Expression::Context context,
275 Register reg) {
Lasse Reichstein 2010/01/12 08:30:05 And this one too! (A good abstraction of the stack
276 ASSERT(count > 0);
277 ASSERT(!reg.is(esp));
278 switch (context) {
279 case Expression::kUninitialized:
280 UNREACHABLE();
281 case Expression::kEffect:
282 __ Drop(count);
283 break;
284 case Expression::kValue:
285 if (count > 1) __ Drop(count - 1);
286 __ mov(Operand(esp, 0), reg);
287 break;
288 case Expression::kTest:
289 __ Drop(count);
290 TestAndBranch(reg, true_label_, false_label_);
291 break;
292 case Expression::kValueTest: {
293 Label discard;
294 if (count > 1) __ Drop(count - 1);
295 __ mov(Operand(esp, 0), reg);
296 TestAndBranch(reg, true_label_, &discard);
297 __ bind(&discard);
298 __ Drop(1);
299 __ jmp(false_label_);
250 break; 300 break;
251 } 301 }
252 case Expression::kTestValue: { 302 case Expression::kTestValue: {
253 Label discard; 303 Label discard;
254 __ mov(eax, Operand(esp, 0)); 304 if (count > 1) __ Drop(count - 1);
255 TestAndBranch(eax, &discard, false_label_); 305 __ mov(Operand(esp, 0), reg);
306 TestAndBranch(reg, &discard, false_label_);
256 __ bind(&discard); 307 __ bind(&discard);
257 __ Drop(1); 308 __ Drop(1);
258 __ jmp(true_label_); 309 __ jmp(true_label_);
310 break;
259 } 311 }
260 } 312 }
261 } 313 }
262 314
263 315
264 MemOperand FastCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) { 316 MemOperand FastCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) {
265 switch (slot->type()) { 317 switch (slot->type()) {
266 case Slot::PARAMETER: 318 case Slot::PARAMETER:
267 case Slot::LOCAL: 319 case Slot::LOCAL:
268 return Operand(ebp, SlotOffset(slot)); 320 return Operand(ebp, SlotOffset(slot));
(...skipping 10 matching lines...) Expand all
279 return Operand(eax, 0); 331 return Operand(eax, 0);
280 } 332 }
281 333
282 334
283 void FastCodeGenerator::Move(Register destination, Slot* source) { 335 void FastCodeGenerator::Move(Register destination, Slot* source) {
284 MemOperand location = EmitSlotSearch(source, destination); 336 MemOperand location = EmitSlotSearch(source, destination);
285 __ mov(destination, location); 337 __ mov(destination, location);
286 } 338 }
287 339
288 340
289 void FastCodeGenerator::Move(Expression::Context context,
290 Slot* source,
291 Register scratch) {
292 switch (context) {
293 case Expression::kUninitialized:
294 UNREACHABLE();
295 case Expression::kEffect:
296 break;
297 case Expression::kValue: {
298 MemOperand location = EmitSlotSearch(source, scratch);
299 __ push(location);
300 break;
301 }
302 case Expression::kTest:
303 case Expression::kValueTest:
304 case Expression::kTestValue:
305 Move(scratch, source);
306 Move(context, scratch);
307 break;
308 }
309 }
310
311
312 void FastCodeGenerator::Move(Expression::Context context, Literal* expr) {
313 switch (context) {
314 case Expression::kUninitialized:
315 UNREACHABLE();
316 case Expression::kEffect:
317 break;
318 case Expression::kValue:
319 __ push(Immediate(expr->handle()));
320 break;
321 case Expression::kTest:
322 case Expression::kValueTest:
323 case Expression::kTestValue:
324 __ mov(eax, expr->handle());
325 Move(context, eax);
326 break;
327 }
328 }
329
330
331 void FastCodeGenerator::Move(Slot* dst, 341 void FastCodeGenerator::Move(Slot* dst,
332 Register src, 342 Register src,
333 Register scratch1, 343 Register scratch1,
334 Register scratch2) { 344 Register scratch2) {
335 ASSERT(dst->type() != Slot::LOOKUP); // Not yet implemented. 345 ASSERT(dst->type() != Slot::LOOKUP); // Not yet implemented.
336 ASSERT(!scratch1.is(src) && !scratch2.is(src)); 346 ASSERT(!scratch1.is(src) && !scratch2.is(src));
337 MemOperand location = EmitSlotSearch(dst, scratch1); 347 MemOperand location = EmitSlotSearch(dst, scratch1);
338 __ mov(location, src); 348 __ mov(location, src);
339 // Emit the write barrier code if the location is in the heap. 349 // Emit the write barrier code if the location is in the heap.
340 if (dst->type() == Slot::CONTEXT) { 350 if (dst->type() == Slot::CONTEXT) {
341 int offset = FixedArray::kHeaderSize + dst->index() * kPointerSize; 351 int offset = FixedArray::kHeaderSize + dst->index() * kPointerSize;
342 __ RecordWrite(scratch1, offset, src, scratch2); 352 __ RecordWrite(scratch1, offset, src, scratch2);
343 } 353 }
344 } 354 }
345 355
346 356
347 void FastCodeGenerator::DropAndMove(Expression::Context context,
348 Register source,
349 int count) {
350 ASSERT(count > 0);
351 switch (context) {
352 case Expression::kUninitialized:
353 UNREACHABLE();
354 case Expression::kEffect:
355 __ add(Operand(esp), Immediate(count * kPointerSize));
356 break;
357 case Expression::kValue:
358 if (count > 1) {
359 __ add(Operand(esp), Immediate((count - 1) * kPointerSize));
360 }
361 __ mov(Operand(esp, 0), source);
362 break;
363 case Expression::kTest:
364 ASSERT(!source.is(esp));
365 __ add(Operand(esp), Immediate(count * kPointerSize));
366 TestAndBranch(source, true_label_, false_label_);
367 break;
368 case Expression::kValueTest: {
369 Label discard;
370 if (count > 1) {
371 __ add(Operand(esp), Immediate((count - 1) * kPointerSize));
372 }
373 __ mov(Operand(esp, 0), source);
374 TestAndBranch(source, true_label_, &discard);
375 __ bind(&discard);
376 __ add(Operand(esp), Immediate(kPointerSize));
377 __ jmp(false_label_);
378 break;
379 }
380 case Expression::kTestValue: {
381 Label discard;
382 if (count > 1) {
383 __ add(Operand(esp), Immediate((count - 1) * kPointerSize));
384 }
385 __ mov(Operand(esp, 0), source);
386 TestAndBranch(source, &discard, false_label_);
387 __ bind(&discard);
388 __ add(Operand(esp), Immediate(kPointerSize));
389 __ jmp(true_label_);
390 break;
391 }
392 }
393 }
394
395
396 void FastCodeGenerator::TestAndBranch(Register source, 357 void FastCodeGenerator::TestAndBranch(Register source,
397 Label* true_label, 358 Label* true_label,
398 Label* false_label) { 359 Label* false_label) {
399 ASSERT_NE(NULL, true_label); 360 ASSERT_NE(NULL, true_label);
400 ASSERT_NE(NULL, false_label); 361 ASSERT_NE(NULL, false_label);
401 // Use the shared ToBoolean stub to compile the value in the register into 362 // Use the shared ToBoolean stub to compile the value in the register into
402 // control flow to the code generator's true and false labels. Perform 363 // control flow to the code generator's true and false labels. Perform
403 // the fast checks assumed by the stub. 364 // the fast checks assumed by the stub.
404 __ cmp(source, Factory::undefined_value()); // The undefined value is false. 365 __ cmp(source, Factory::undefined_value()); // The undefined value is false.
405 __ j(equal, false_label); 366 __ j(equal, false_label);
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
511 __ Set(eax, Immediate(Factory::the_hole_value())); 472 __ Set(eax, Immediate(Factory::the_hole_value()));
512 } 473 }
513 474
514 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 475 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
515 __ call(ic, RelocInfo::CODE_TARGET); 476 __ call(ic, RelocInfo::CODE_TARGET);
516 // Absence of a test eax instruction following the call 477 // Absence of a test eax instruction following the call
517 // indicates that none of the load was inlined. 478 // indicates that none of the load was inlined.
518 479
519 // Value in eax is ignored (declarations are statements). Receiver 480 // Value in eax is ignored (declarations are statements). Receiver
520 // and key on stack are discarded. 481 // and key on stack are discarded.
521 __ add(Operand(esp), Immediate(2 * kPointerSize)); 482 __ Drop(2);
522 } 483 }
523 } 484 }
524 } 485 }
525 486
526 487
527 void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { 488 void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
528 // Call the runtime to declare the globals. 489 // Call the runtime to declare the globals.
529 __ push(esi); // The context is the first argument. 490 __ push(esi); // The context is the first argument.
530 __ push(Immediate(pairs)); 491 __ push(Immediate(pairs));
531 __ push(Immediate(Smi::FromInt(is_eval_ ? 1 : 0))); 492 __ push(Immediate(Smi::FromInt(is_eval_ ? 1 : 0)));
532 __ CallRuntime(Runtime::kDeclareGlobals, 3); 493 __ CallRuntime(Runtime::kDeclareGlobals, 3);
533 // Return value is ignored. 494 // Return value is ignored.
534 } 495 }
535 496
536 497
537 void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { 498 void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
538 Comment cmnt(masm_, "[ FunctionLiteral"); 499 Comment cmnt(masm_, "[ FunctionLiteral");
539 500
540 // Build the function boilerplate and instantiate it. 501 // Build the function boilerplate and instantiate it.
541 Handle<JSFunction> boilerplate = 502 Handle<JSFunction> boilerplate =
542 Compiler::BuildBoilerplate(expr, script_, this); 503 Compiler::BuildBoilerplate(expr, script_, this);
543 if (HasStackOverflow()) return; 504 if (HasStackOverflow()) return;
544 505
545 ASSERT(boilerplate->IsBoilerplate()); 506 ASSERT(boilerplate->IsBoilerplate());
546 507
547 // Create a new closure. 508 // Create a new closure.
548 __ push(esi); 509 __ push(esi);
549 __ push(Immediate(boilerplate)); 510 __ push(Immediate(boilerplate));
550 __ CallRuntime(Runtime::kNewClosure, 2); 511 __ CallRuntime(Runtime::kNewClosure, 2);
551 Move(expr->context(), eax); 512 Apply(expr->context(), eax);
552 } 513 }
553 514
554 515
555 void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) { 516 void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
556 Comment cmnt(masm_, "[ VariableProxy"); 517 Comment cmnt(masm_, "[ VariableProxy");
557 EmitVariableLoad(expr->var(), expr->context()); 518 EmitVariableLoad(expr->var(), expr->context());
558 } 519 }
559 520
560 521
561 void FastCodeGenerator::EmitVariableLoad(Variable* var, 522 void FastCodeGenerator::EmitVariableLoad(Variable* var,
562 Expression::Context context) { 523 Expression::Context context) {
563 Expression* rewrite = var->rewrite(); 524 Expression* rewrite = var->rewrite();
564 if (rewrite == NULL) { 525 if (rewrite == NULL) {
565 ASSERT(var->is_global()); 526 ASSERT(var->is_global());
566 Comment cmnt(masm_, "Global variable"); 527 Comment cmnt(masm_, "Global variable");
567 // Use inline caching. Variable name is passed in ecx and the global 528 // Use inline caching. Variable name is passed in ecx and the global
568 // object on the stack. 529 // object on the stack.
569 __ push(CodeGenerator::GlobalObject()); 530 __ push(CodeGenerator::GlobalObject());
570 __ mov(ecx, var->name()); 531 __ mov(ecx, var->name());
571 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 532 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
572 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT); 533 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT);
573 // By emitting a nop we make sure that we do not have a test eax 534 // By emitting a nop we make sure that we do not have a test eax
574 // instruction after the call it is treated specially by the LoadIC code 535 // instruction after the call it is treated specially by the LoadIC code
575 // Remember that the assembler may choose to do peephole optimization 536 // Remember that the assembler may choose to do peephole optimization
576 // (eg, push/pop elimination). 537 // (eg, push/pop elimination).
577 __ nop(); 538 __ nop();
578 DropAndMove(context, eax); 539 DropAndApply(1, context, eax);
579 } else if (rewrite->AsSlot() != NULL) { 540 } else if (rewrite->AsSlot() != NULL) {
580 Slot* slot = rewrite->AsSlot(); 541 Slot* slot = rewrite->AsSlot();
581 if (FLAG_debug_code) { 542 if (FLAG_debug_code) {
582 switch (slot->type()) { 543 switch (slot->type()) {
583 case Slot::PARAMETER: 544 case Slot::PARAMETER:
584 case Slot::LOCAL: { 545 case Slot::LOCAL: {
585 Comment cmnt(masm_, "Stack slot"); 546 Comment cmnt(masm_, "Stack slot");
586 break; 547 break;
587 } 548 }
588 case Slot::CONTEXT: { 549 case Slot::CONTEXT: {
589 Comment cmnt(masm_, "Context slot"); 550 Comment cmnt(masm_, "Context slot");
590 break; 551 break;
591 } 552 }
592 case Slot::LOOKUP: 553 case Slot::LOOKUP:
593 UNIMPLEMENTED(); 554 UNIMPLEMENTED();
594 break; 555 break;
595 } 556 }
596 } 557 }
597 Move(context, slot, eax); 558 Apply(context, slot, eax);
598 } else { 559 } else {
599 Comment cmnt(masm_, "Variable rewritten to Property"); 560 Comment cmnt(masm_, "Variable rewritten to property");
600 // A variable has been rewritten into an explicit access to 561 // A variable has been rewritten into an explicit access to an object
601 // an object property. 562 // property.
602 Property* property = rewrite->AsProperty(); 563 Property* property = rewrite->AsProperty();
603 ASSERT_NOT_NULL(property); 564 ASSERT_NOT_NULL(property);
604 565
605 // Currently the only parameter expressions that can occur are 566 // The only property expressions that can occur are of the form
606 // on the form "slot[literal]". 567 // "slot[literal]".
607 568
608 // Check that the object is in a slot. 569 // Assert that the object is in a slot.
609 Variable* object_var = property->obj()->AsVariableProxy()->AsVariable(); 570 Variable* object_var = property->obj()->AsVariableProxy()->AsVariable();
610 ASSERT_NOT_NULL(object_var); 571 ASSERT_NOT_NULL(object_var);
611 Slot* object_slot = object_var->slot(); 572 Slot* object_slot = object_var->slot();
612 ASSERT_NOT_NULL(object_slot); 573 ASSERT_NOT_NULL(object_slot);
613 574
614 // Load the object. 575 // Load the object.
615 Move(Expression::kValue, object_slot, eax); 576 MemOperand object_loc = EmitSlotSearch(object_slot, eax);
577 __ push(object_loc);
616 578
617 // Check that the key is a smi. 579 // Assert that the key is a smi.
618 Literal* key_literal = property->key()->AsLiteral(); 580 Literal* key_literal = property->key()->AsLiteral();
619 ASSERT_NOT_NULL(key_literal); 581 ASSERT_NOT_NULL(key_literal);
620 ASSERT(key_literal->handle()->IsSmi()); 582 ASSERT(key_literal->handle()->IsSmi());
621 583
622 // Load the key. 584 // Load the key.
623 Move(Expression::kValue, key_literal); 585 __ push(Immediate(key_literal->handle()));
624 586
625 // Do a KEYED property load. 587 // Do a keyed property load.
626 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 588 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
627 __ call(ic, RelocInfo::CODE_TARGET); 589 __ call(ic, RelocInfo::CODE_TARGET);
628 // Notice: We must not have a "test eax, ..." instruction after 590 // Notice: We must not have a "test eax, ..." instruction after the
629 // the call. It is treated specially by the LoadIC code. 591 // call. It is treated specially by the LoadIC code.
630 __ nop(); 592 __ nop();
Lasse Reichstein 2010/01/12 08:30:05 Can we assume that DropAndMove does not start with
631 // Drop key and object left on the stack by IC. 593 // Drop key and object left on the stack by IC.
632 DropAndMove(context, eax, 2); 594 DropAndApply(2, context, eax);
633 } 595 }
634 } 596 }
635 597
636 598
637 void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { 599 void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
638 Comment cmnt(masm_, "[ RegExpLiteral"); 600 Comment cmnt(masm_, "[ RegExpLiteral");
639 Label done; 601 Label done;
640 // Registers will be used as follows: 602 // Registers will be used as follows:
641 // edi = JS function. 603 // edi = JS function.
642 // ebx = literals array. 604 // ebx = literals array.
643 // eax = regexp literal. 605 // eax = regexp literal.
644 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 606 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
645 __ mov(ebx, FieldOperand(edi, JSFunction::kLiteralsOffset)); 607 __ mov(ebx, FieldOperand(edi, JSFunction::kLiteralsOffset));
646 int literal_offset = 608 int literal_offset =
647 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; 609 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize;
648 __ mov(eax, FieldOperand(ebx, literal_offset)); 610 __ mov(eax, FieldOperand(ebx, literal_offset));
649 __ cmp(eax, Factory::undefined_value()); 611 __ cmp(eax, Factory::undefined_value());
650 __ j(not_equal, &done); 612 __ j(not_equal, &done);
651 // Create regexp literal using runtime function 613 // Create regexp literal using runtime function
652 // Result will be in eax. 614 // Result will be in eax.
653 __ push(ebx); 615 __ push(ebx);
654 __ push(Immediate(Smi::FromInt(expr->literal_index()))); 616 __ push(Immediate(Smi::FromInt(expr->literal_index())));
655 __ push(Immediate(expr->pattern())); 617 __ push(Immediate(expr->pattern()));
656 __ push(Immediate(expr->flags())); 618 __ push(Immediate(expr->flags()));
657 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); 619 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
658 // Label done: 620 // Label done:
659 __ bind(&done); 621 __ bind(&done);
660 Move(expr->context(), eax); 622 Apply(expr->context(), eax);
661 } 623 }
662 624
663 625
664 void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { 626 void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
665 Comment cmnt(masm_, "[ ObjectLiteral"); 627 Comment cmnt(masm_, "[ ObjectLiteral");
666 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 628 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
667 __ push(FieldOperand(edi, JSFunction::kLiteralsOffset)); 629 __ push(FieldOperand(edi, JSFunction::kLiteralsOffset));
668 __ push(Immediate(Smi::FromInt(expr->literal_index()))); 630 __ push(Immediate(Smi::FromInt(expr->literal_index())));
669 __ push(Immediate(expr->constant_properties())); 631 __ push(Immediate(expr->constant_properties()));
670 if (expr->depth() > 1) { 632 if (expr->depth() > 1) {
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
726 __ CallRuntime(Runtime::kDefineAccessor, 4); 688 __ CallRuntime(Runtime::kDefineAccessor, 4);
727 __ mov(eax, Operand(esp, 0)); // Restore result into eax. 689 __ mov(eax, Operand(esp, 0)); // Restore result into eax.
728 break; 690 break;
729 default: UNREACHABLE(); 691 default: UNREACHABLE();
730 } 692 }
731 } 693 }
732 switch (expr->context()) { 694 switch (expr->context()) {
733 case Expression::kUninitialized: 695 case Expression::kUninitialized:
734 UNREACHABLE(); 696 UNREACHABLE();
735 case Expression::kEffect: 697 case Expression::kEffect:
736 if (result_saved) __ add(Operand(esp), Immediate(kPointerSize)); 698 if (result_saved) __ Drop(1);
737 break; 699 break;
738 case Expression::kValue: 700 case Expression::kValue:
739 if (!result_saved) __ push(eax); 701 if (!result_saved) __ push(eax);
740 break; 702 break;
741 case Expression::kTest: 703 case Expression::kTest:
742 if (result_saved) __ pop(eax); 704 if (result_saved) __ pop(eax);
743 TestAndBranch(eax, true_label_, false_label_); 705 TestAndBranch(eax, true_label_, false_label_);
744 break; 706 break;
745 case Expression::kValueTest: { 707 case Expression::kValueTest: {
746 Label discard; 708 Label discard;
747 if (!result_saved) __ push(eax); 709 if (!result_saved) __ push(eax);
748 TestAndBranch(eax, true_label_, &discard); 710 TestAndBranch(eax, true_label_, &discard);
749 __ bind(&discard); 711 __ bind(&discard);
750 __ add(Operand(esp), Immediate(kPointerSize)); 712 __ Drop(1);
751 __ jmp(false_label_); 713 __ jmp(false_label_);
752 break; 714 break;
753 } 715 }
754 case Expression::kTestValue: { 716 case Expression::kTestValue: {
755 Label discard; 717 Label discard;
756 if (!result_saved) __ push(eax); 718 if (!result_saved) __ push(eax);
757 TestAndBranch(eax, &discard, false_label_); 719 TestAndBranch(eax, &discard, false_label_);
758 __ bind(&discard); 720 __ bind(&discard);
759 __ add(Operand(esp), Immediate(kPointerSize)); 721 __ Drop (1);
760 __ jmp(true_label_); 722 __ jmp(true_label_);
761 break; 723 break;
762 } 724 }
763 } 725 }
764 } 726 }
765 727
766 728
767 void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { 729 void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
768 Comment cmnt(masm_, "[ ArrayLiteral"); 730 Comment cmnt(masm_, "[ ArrayLiteral");
769 __ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 731 __ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
805 __ mov(FieldOperand(ebx, offset), eax); 767 __ mov(FieldOperand(ebx, offset), eax);
806 768
807 // Update the write barrier for the array store. 769 // Update the write barrier for the array store.
808 __ RecordWrite(ebx, offset, eax, ecx); 770 __ RecordWrite(ebx, offset, eax, ecx);
809 } 771 }
810 772
811 switch (expr->context()) { 773 switch (expr->context()) {
812 case Expression::kUninitialized: 774 case Expression::kUninitialized:
813 UNREACHABLE(); 775 UNREACHABLE();
814 case Expression::kEffect: 776 case Expression::kEffect:
815 if (result_saved) __ add(Operand(esp), Immediate(kPointerSize)); 777 if (result_saved) __ Drop(1);
816 break; 778 break;
817 case Expression::kValue: 779 case Expression::kValue:
818 if (!result_saved) __ push(eax); 780 if (!result_saved) __ push(eax);
819 break; 781 break;
820 case Expression::kTest: 782 case Expression::kTest:
821 if (result_saved) __ pop(eax); 783 if (result_saved) __ pop(eax);
822 TestAndBranch(eax, true_label_, false_label_); 784 TestAndBranch(eax, true_label_, false_label_);
823 break; 785 break;
824 case Expression::kValueTest: { 786 case Expression::kValueTest: {
825 Label discard; 787 Label discard;
826 if (!result_saved) __ push(eax); 788 if (!result_saved) __ push(eax);
827 TestAndBranch(eax, true_label_, &discard); 789 TestAndBranch(eax, true_label_, &discard);
828 __ bind(&discard); 790 __ bind(&discard);
829 __ add(Operand(esp), Immediate(kPointerSize)); 791 __ Drop(1);
830 __ jmp(false_label_); 792 __ jmp(false_label_);
831 break; 793 break;
832 } 794 }
833 case Expression::kTestValue: { 795 case Expression::kTestValue: {
834 Label discard; 796 Label discard;
835 if (!result_saved) __ push(eax); 797 if (!result_saved) __ push(eax);
836 TestAndBranch(eax, &discard, false_label_); 798 TestAndBranch(eax, &discard, false_label_);
837 __ bind(&discard); 799 __ bind(&discard);
838 __ add(Operand(esp), Immediate(kPointerSize)); 800 __ Drop(1);
839 __ jmp(true_label_); 801 __ jmp(true_label_);
840 break; 802 break;
841 } 803 }
842 } 804 }
843 } 805 }
844 806
845 807
846 void FastCodeGenerator::EmitNamedPropertyLoad(Property* prop, 808 void FastCodeGenerator::EmitNamedPropertyLoad(Property* prop,
847 Expression::Context context) { 809 Expression::Context context) {
848 SetSourcePosition(prop->position()); 810 SetSourcePosition(prop->position());
849 Literal* key = prop->key()->AsLiteral(); 811 Literal* key = prop->key()->AsLiteral();
850 __ mov(ecx, Immediate(key->handle())); 812 __ mov(ecx, Immediate(key->handle()));
851 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 813 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
852 __ call(ic, RelocInfo::CODE_TARGET); 814 __ call(ic, RelocInfo::CODE_TARGET);
853 Move(context, eax); 815 Apply(context, eax);
854 } 816 }
855 817
856 818
857 void FastCodeGenerator::EmitKeyedPropertyLoad(Property* prop, 819 void FastCodeGenerator::EmitKeyedPropertyLoad(Property* prop,
858 Expression::Context context) { 820 Expression::Context context) {
859 SetSourcePosition(prop->position()); 821 SetSourcePosition(prop->position());
860 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 822 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
861 __ call(ic, RelocInfo::CODE_TARGET); 823 __ call(ic, RelocInfo::CODE_TARGET);
862 Move(context, eax); 824 Apply(context, eax);
863 } 825 }
864 826
865 827
866 void FastCodeGenerator::EmitCompoundAssignmentOp(Token::Value op, 828 void FastCodeGenerator::EmitCompoundAssignmentOp(Token::Value op,
867 Expression::Context context) { 829 Expression::Context context) {
868 GenericBinaryOpStub stub(op, 830 GenericBinaryOpStub stub(op,
869 NO_OVERWRITE, 831 NO_OVERWRITE,
870 NO_GENERIC_BINARY_FLAGS); 832 NO_GENERIC_BINARY_FLAGS);
871 __ CallStub(&stub); 833 __ CallStub(&stub);
872 Move(context, eax); 834 Apply(context, eax);
873 } 835 }
874 836
875 837
876 void FastCodeGenerator::EmitVariableAssignment(Variable* var, 838 void FastCodeGenerator::EmitVariableAssignment(Variable* var,
877 Expression::Context context) { 839 Expression::Context context) {
878 ASSERT(var != NULL); 840 ASSERT(var != NULL);
879 ASSERT(var->is_global() || var->slot() != NULL); 841 ASSERT(var->is_global() || var->slot() != NULL);
880 if (var->is_global()) { 842 if (var->is_global()) {
881 // Assignment to a global variable. Use inline caching for the 843 // Assignment to a global variable. Use inline caching for the
882 // assignment. Right-hand-side value is passed in eax, variable name in 844 // assignment. Right-hand-side value is passed in eax, variable name in
883 // ecx, and the global object on the stack. 845 // ecx, and the global object on the stack.
884 __ pop(eax); 846 __ pop(eax);
885 __ mov(ecx, var->name()); 847 __ mov(ecx, var->name());
886 __ push(CodeGenerator::GlobalObject()); 848 __ push(CodeGenerator::GlobalObject());
887 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 849 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
888 __ call(ic, RelocInfo::CODE_TARGET); 850 __ call(ic, RelocInfo::CODE_TARGET);
889 // Overwrite the receiver on the stack with the result if needed. 851 // Overwrite the receiver on the stack with the result if needed.
890 DropAndMove(context, eax); 852 DropAndApply(1, context, eax);
891 853
892 } else if (var->slot() != NULL) { 854 } else if (var->slot() != NULL) {
893 Slot* slot = var->slot(); 855 Slot* slot = var->slot();
894 switch (slot->type()) { 856 switch (slot->type()) {
895 case Slot::LOCAL: 857 case Slot::LOCAL:
896 case Slot::PARAMETER: { 858 case Slot::PARAMETER: {
897 Operand target = Operand(ebp, SlotOffset(slot)); 859 Operand target = Operand(ebp, SlotOffset(slot));
898 switch (context) { 860 switch (context) {
899 case Expression::kUninitialized: 861 case Expression::kUninitialized:
900 UNREACHABLE(); 862 UNREACHABLE();
(...skipping 11 matching lines...) Expand all
912 __ pop(eax); 874 __ pop(eax);
913 __ mov(target, eax); 875 __ mov(target, eax);
914 TestAndBranch(eax, true_label_, false_label_); 876 TestAndBranch(eax, true_label_, false_label_);
915 break; 877 break;
916 case Expression::kValueTest: { 878 case Expression::kValueTest: {
917 Label discard; 879 Label discard;
918 __ mov(eax, Operand(esp, 0)); 880 __ mov(eax, Operand(esp, 0));
919 __ mov(target, eax); 881 __ mov(target, eax);
920 TestAndBranch(eax, true_label_, &discard); 882 TestAndBranch(eax, true_label_, &discard);
921 __ bind(&discard); 883 __ bind(&discard);
922 __ add(Operand(esp), Immediate(kPointerSize)); 884 __ Drop(1);
923 __ jmp(false_label_); 885 __ jmp(false_label_);
924 break; 886 break;
925 } 887 }
926 case Expression::kTestValue: { 888 case Expression::kTestValue: {
927 Label discard; 889 Label discard;
928 __ mov(eax, Operand(esp, 0)); 890 __ mov(eax, Operand(esp, 0));
929 __ mov(target, eax); 891 __ mov(target, eax);
930 TestAndBranch(eax, &discard, false_label_); 892 TestAndBranch(eax, &discard, false_label_);
931 __ bind(&discard); 893 __ bind(&discard);
932 __ add(Operand(esp), Immediate(kPointerSize)); 894 __ Drop(1);
933 __ jmp(true_label_); 895 __ jmp(true_label_);
934 break; 896 break;
935 } 897 }
936 } 898 }
937 break; 899 break;
938 } 900 }
939 901
940 case Slot::CONTEXT: { 902 case Slot::CONTEXT: {
941 MemOperand target = EmitSlotSearch(slot, ecx); 903 MemOperand target = EmitSlotSearch(slot, ecx);
942 __ pop(eax); 904 __ pop(eax);
943 __ mov(target, eax); 905 __ mov(target, eax);
944 906
945 // RecordWrite may destroy all its register arguments. 907 // RecordWrite may destroy all its register arguments.
946 if (context == Expression::kValue) { 908 if (context == Expression::kValue) {
947 __ push(eax); 909 __ push(eax);
948 } else if (context != Expression::kEffect) { 910 } else if (context != Expression::kEffect) {
949 __ mov(edx, eax); 911 __ mov(edx, eax);
950 } 912 }
951 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; 913 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize;
952 __ RecordWrite(ecx, offset, eax, ebx); 914 __ RecordWrite(ecx, offset, eax, ebx);
953 if (context != Expression::kEffect && 915 if (context != Expression::kEffect && context != Expression::kValue) {
954 context != Expression::kValue) { 916 Apply(context, edx);
955 Move(context, edx);
956 } 917 }
957 break; 918 break;
958 } 919 }
959 920
960 case Slot::LOOKUP: 921 case Slot::LOOKUP:
961 UNREACHABLE(); 922 UNREACHABLE();
962 break; 923 break;
963 } 924 }
964 } else { 925 } else {
965 // Variables rewritten as properties are not treated as variables in 926 // Variables rewritten as properties are not treated as variables in
(...skipping 23 matching lines...) Expand all
989 __ call(ic, RelocInfo::CODE_TARGET); 950 __ call(ic, RelocInfo::CODE_TARGET);
990 951
991 // If the assignment ends an initialization block, revert to fast case. 952 // If the assignment ends an initialization block, revert to fast case.
992 if (expr->ends_initialization_block()) { 953 if (expr->ends_initialization_block()) {
993 __ push(eax); // Result of assignment, saved even if not needed. 954 __ push(eax); // Result of assignment, saved even if not needed.
994 __ push(Operand(esp, kPointerSize)); // Receiver is under value. 955 __ push(Operand(esp, kPointerSize)); // Receiver is under value.
995 __ CallRuntime(Runtime::kToFastProperties, 1); 956 __ CallRuntime(Runtime::kToFastProperties, 1);
996 __ pop(eax); 957 __ pop(eax);
997 } 958 }
998 959
999 DropAndMove(expr->context(), eax); 960 DropAndApply(1, expr->context(), eax);
1000 } 961 }
1001 962
1002 963
1003 void FastCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { 964 void FastCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
1004 // Assignment to a property, using a keyed store IC. 965 // Assignment to a property, using a keyed store IC.
1005 966
1006 // If the assignment starts a block of assignments to the same object, 967 // If the assignment starts a block of assignments to the same object,
1007 // change to slow case to avoid the quadratic behavior of repeatedly 968 // change to slow case to avoid the quadratic behavior of repeatedly
1008 // adding fast properties. 969 // adding fast properties.
1009 if (expr->starts_initialization_block()) { 970 if (expr->starts_initialization_block()) {
(...skipping 12 matching lines...) Expand all
1022 // If the assignment ends an initialization block, revert to fast case. 983 // If the assignment ends an initialization block, revert to fast case.
1023 if (expr->ends_initialization_block()) { 984 if (expr->ends_initialization_block()) {
1024 __ push(eax); // Result of assignment, saved even if not needed. 985 __ push(eax); // Result of assignment, saved even if not needed.
1025 // Reciever is under the key and value. 986 // Reciever is under the key and value.
1026 __ push(Operand(esp, 2 * kPointerSize)); 987 __ push(Operand(esp, 2 * kPointerSize));
1027 __ CallRuntime(Runtime::kToFastProperties, 1); 988 __ CallRuntime(Runtime::kToFastProperties, 1);
1028 __ pop(eax); 989 __ pop(eax);
1029 } 990 }
1030 991
1031 // Receiver and key are still on stack. 992 // Receiver and key are still on stack.
1032 __ add(Operand(esp), Immediate(2 * kPointerSize)); 993 DropAndApply(2, expr->context(), eax);
1033 Move(expr->context(), eax);
1034 } 994 }
1035 995
1036 996
1037 void FastCodeGenerator::VisitProperty(Property* expr) { 997 void FastCodeGenerator::VisitProperty(Property* expr) {
1038 Comment cmnt(masm_, "[ Property"); 998 Comment cmnt(masm_, "[ Property");
1039 Expression* key = expr->key(); 999 Expression* key = expr->key();
1040 uint32_t dummy;
1041 1000
1042 // Record the source position for the property load. 1001 // Record the source position for the property load.
1043 SetSourcePosition(expr->position()); 1002 SetSourcePosition(expr->position());
1044 1003
1045 // Evaluate receiver. 1004 // Evaluate the receiver.
1046 Visit(expr->obj()); 1005 Visit(expr->obj());
1047 1006
1048 if (key->AsLiteral() != NULL && key->AsLiteral()->handle()->IsSymbol() && 1007 if (key->IsPropertyName()) {
1049 !String::cast(*(key->AsLiteral()->handle()))->AsArrayIndex(&dummy)) { 1008 // Do a named property load. The IC expects the property name in ecx
1050 // Do a NAMED property load. 1009 // and the receiver on the stack.
1051 // The IC expects the property name in ecx and the receiver on the stack.
1052 __ mov(ecx, Immediate(key->AsLiteral()->handle())); 1010 __ mov(ecx, Immediate(key->AsLiteral()->handle()));
1053 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 1011 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
1054 __ call(ic, RelocInfo::CODE_TARGET); 1012 __ call(ic, RelocInfo::CODE_TARGET);
1055 // By emitting a nop we make sure that we do not have a test eax 1013 // By emitting a nop we make sure that we do not have a test eax
1056 // instruction after the call it is treated specially by the LoadIC code. 1014 // instruction after the call it is treated specially by the LoadIC code.
1057 __ nop(); 1015 __ nop();
1016 DropAndApply(1, expr->context(), eax);
1058 } else { 1017 } else {
1059 // Do a KEYED property load. 1018 // Do a keyed property load.
1060 Visit(expr->key()); 1019 Visit(expr->key());
1061 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 1020 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
1062 __ call(ic, RelocInfo::CODE_TARGET); 1021 __ call(ic, RelocInfo::CODE_TARGET);
1063 // By emitting a nop we make sure that we do not have a "test eax,..." 1022 // By emitting a nop we make sure that we do not have a "test eax,..."
1064 // instruction after the call it is treated specially by the LoadIC code. 1023 // instruction after the call it is treated specially by the LoadIC code.
1065 __ nop(); 1024 __ nop();
1066 // Drop key left on the stack by IC. 1025 // Drop key left on the stack by IC.
1067 __ add(Operand(esp), Immediate(kPointerSize)); 1026 DropAndApply(2, expr->context(), eax);
1068 } 1027 }
1069 DropAndMove(expr->context(), eax);
1070 } 1028 }
1071 1029
1072 1030
1073 void FastCodeGenerator::EmitCallWithIC(Call* expr, 1031 void FastCodeGenerator::EmitCallWithIC(Call* expr,
1074 Handle<Object> name, 1032 Handle<Object> name,
1075 RelocInfo::Mode mode) { 1033 RelocInfo::Mode mode) {
1076 // Code common for calls using the IC. 1034 // Code common for calls using the IC.
1077 ZoneList<Expression*>* args = expr->arguments(); 1035 ZoneList<Expression*>* args = expr->arguments();
1078 int arg_count = args->length(); 1036 int arg_count = args->length();
1079 for (int i = 0; i < arg_count; i++) { 1037 for (int i = 0; i < arg_count; i++) {
1080 Visit(args->at(i)); 1038 Visit(args->at(i));
1081 ASSERT_EQ(Expression::kValue, args->at(i)->context()); 1039 ASSERT_EQ(Expression::kValue, args->at(i)->context());
1082 } 1040 }
1083 __ Set(ecx, Immediate(name)); 1041 __ Set(ecx, Immediate(name));
1084 // Record source position of the IC call. 1042 // Record source position of the IC call.
1085 SetSourcePosition(expr->position()); 1043 SetSourcePosition(expr->position());
1086 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 1044 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
1087 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop); 1045 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop);
1088 __ call(ic, mode); 1046 __ call(ic, mode);
1089 // Restore context register. 1047 // Restore context register.
1090 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 1048 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
1091 Move(expr->context(), eax); 1049 Apply(expr->context(), eax);
1092 } 1050 }
1093 1051
1094 1052
1095 void FastCodeGenerator::EmitCallWithStub(Call* expr) { 1053 void FastCodeGenerator::EmitCallWithStub(Call* expr) {
1096 // Code common for calls using the call stub. 1054 // Code common for calls using the call stub.
1097 ZoneList<Expression*>* args = expr->arguments(); 1055 ZoneList<Expression*>* args = expr->arguments();
1098 int arg_count = args->length(); 1056 int arg_count = args->length();
1099 for (int i = 0; i < arg_count; i++) { 1057 for (int i = 0; i < arg_count; i++) {
1100 Visit(args->at(i)); 1058 Visit(args->at(i));
1101 } 1059 }
1102 // Record source position for debugger. 1060 // Record source position for debugger.
1103 SetSourcePosition(expr->position()); 1061 SetSourcePosition(expr->position());
1104 CallFunctionStub stub(arg_count, NOT_IN_LOOP); 1062 CallFunctionStub stub(arg_count, NOT_IN_LOOP);
1105 __ CallStub(&stub); 1063 __ CallStub(&stub);
1106 // Restore context register. 1064 // Restore context register.
1107 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 1065 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
1108 DropAndMove(expr->context(), eax); 1066 DropAndApply(1, expr->context(), eax);
1109 } 1067 }
1110 1068
1111 1069
1112 void FastCodeGenerator::VisitCall(Call* expr) { 1070 void FastCodeGenerator::VisitCall(Call* expr) {
1113 Comment cmnt(masm_, "[ Call"); 1071 Comment cmnt(masm_, "[ Call");
1114 Expression* fun = expr->expression(); 1072 Expression* fun = expr->expression();
1115 Variable* var = fun->AsVariableProxy()->AsVariable(); 1073 Variable* var = fun->AsVariableProxy()->AsVariable();
1116 1074
1117 if (var != NULL && var->is_possibly_eval()) { 1075 if (var != NULL && var->is_possibly_eval()) {
1118 // Call to the identifier 'eval'. 1076 // Call to the identifier 'eval'.
(...skipping 20 matching lines...) Expand all
1139 Visit(prop->obj()); 1097 Visit(prop->obj());
1140 Visit(prop->key()); 1098 Visit(prop->key());
1141 // Record source code position for IC call. 1099 // Record source code position for IC call.
1142 SetSourcePosition(prop->position()); 1100 SetSourcePosition(prop->position());
1143 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 1101 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
1144 __ call(ic, RelocInfo::CODE_TARGET); 1102 __ call(ic, RelocInfo::CODE_TARGET);
1145 // By emitting a nop we make sure that we do not have a "test eax,..." 1103 // By emitting a nop we make sure that we do not have a "test eax,..."
1146 // instruction after the call it is treated specially by the LoadIC code. 1104 // instruction after the call it is treated specially by the LoadIC code.
1147 __ nop(); 1105 __ nop();
1148 // Drop key left on the stack by IC. 1106 // Drop key left on the stack by IC.
1149 __ add(Operand(esp), Immediate(kPointerSize)); 1107 __ Drop(1);
1150 // Pop receiver. 1108 // Pop receiver.
1151 __ pop(ebx); 1109 __ pop(ebx);
1152 // Push result (function). 1110 // Push result (function).
1153 __ push(eax); 1111 __ push(eax);
1154 // Push receiver object on stack. 1112 // Push receiver object on stack.
1155 if (prop->is_synthetic()) { 1113 if (prop->is_synthetic()) {
1156 __ push(CodeGenerator::GlobalObject()); 1114 __ push(CodeGenerator::GlobalObject());
1157 } else { 1115 } else {
1158 __ push(ebx); 1116 __ push(ebx);
1159 } 1117 }
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
1207 1165
1208 // Load function, arg_count into edi and eax. 1166 // Load function, arg_count into edi and eax.
1209 __ Set(eax, Immediate(arg_count)); 1167 __ Set(eax, Immediate(arg_count));
1210 // Function is in esp[arg_count + 1]. 1168 // Function is in esp[arg_count + 1].
1211 __ mov(edi, Operand(esp, eax, times_pointer_size, kPointerSize)); 1169 __ mov(edi, Operand(esp, eax, times_pointer_size, kPointerSize));
1212 1170
1213 Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall)); 1171 Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall));
1214 __ call(construct_builtin, RelocInfo::CONSTRUCT_CALL); 1172 __ call(construct_builtin, RelocInfo::CONSTRUCT_CALL);
1215 1173
1216 // Replace function on TOS with result in eax, or pop it. 1174 // Replace function on TOS with result in eax, or pop it.
1217 DropAndMove(expr->context(), eax); 1175 DropAndApply(1, expr->context(), eax);
1218 } 1176 }
1219 1177
1220 1178
1221 void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) { 1179 void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
1222 Comment cmnt(masm_, "[ CallRuntime"); 1180 Comment cmnt(masm_, "[ CallRuntime");
1223 ZoneList<Expression*>* args = expr->arguments(); 1181 ZoneList<Expression*>* args = expr->arguments();
1224 1182
1225 if (expr->is_jsruntime()) { 1183 if (expr->is_jsruntime()) {
1226 // Prepare for calling JS runtime function. 1184 // Prepare for calling JS runtime function.
1227 __ mov(eax, CodeGenerator::GlobalObject()); 1185 __ mov(eax, CodeGenerator::GlobalObject());
(...skipping 12 matching lines...) Expand all
1240 __ Set(ecx, Immediate(expr->name())); 1198 __ Set(ecx, Immediate(expr->name()));
1241 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 1199 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
1242 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop); 1200 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop);
1243 __ call(ic, RelocInfo::CODE_TARGET); 1201 __ call(ic, RelocInfo::CODE_TARGET);
1244 // Restore context register. 1202 // Restore context register.
1245 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 1203 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
1246 } else { 1204 } else {
1247 // Call the C runtime function. 1205 // Call the C runtime function.
1248 __ CallRuntime(expr->function(), arg_count); 1206 __ CallRuntime(expr->function(), arg_count);
1249 } 1207 }
1250 Move(expr->context(), eax); 1208 Apply(expr->context(), eax);
1251 } 1209 }
1252 1210
1253 1211
1254 void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { 1212 void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
1255 switch (expr->op()) { 1213 switch (expr->op()) {
1256 case Token::VOID: { 1214 case Token::VOID: {
1257 Comment cmnt(masm_, "[ UnaryOperation (VOID)"); 1215 Comment cmnt(masm_, "[ UnaryOperation (VOID)");
1258 Visit(expr->expression()); 1216 Visit(expr->expression());
1259 ASSERT_EQ(Expression::kEffect, expr->expression()->context()); 1217 ASSERT_EQ(Expression::kEffect, expr->expression()->context());
1260 switch (expr->context()) { 1218 switch (expr->context()) {
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
1362 __ push(esi); 1320 __ push(esi);
1363 __ push(Immediate(proxy->name())); 1321 __ push(Immediate(proxy->name()));
1364 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); 1322 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
1365 __ push(eax); 1323 __ push(eax);
1366 } else { 1324 } else {
1367 // This expression cannot throw a reference error at the top level. 1325 // This expression cannot throw a reference error at the top level.
1368 Visit(expr->expression()); 1326 Visit(expr->expression());
1369 } 1327 }
1370 1328
1371 __ CallRuntime(Runtime::kTypeof, 1); 1329 __ CallRuntime(Runtime::kTypeof, 1);
1372 Move(expr->context(), eax); 1330 Apply(expr->context(), eax);
1373 break; 1331 break;
1374 } 1332 }
1375 1333
1376 default: 1334 default:
1377 UNREACHABLE(); 1335 UNREACHABLE();
1378 } 1336 }
1379 } 1337 }
1380 1338
1381 1339
1382 void FastCodeGenerator::VisitCountOperation(CountOperation* expr) { 1340 void FastCodeGenerator::VisitCountOperation(CountOperation* expr) {
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
1462 // Store the value returned in eax. 1420 // Store the value returned in eax.
1463 switch (assign_type) { 1421 switch (assign_type) {
1464 case VARIABLE: 1422 case VARIABLE:
1465 __ push(eax); 1423 __ push(eax);
1466 if (expr->is_postfix()) { 1424 if (expr->is_postfix()) {
1467 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 1425 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
1468 Expression::kEffect); 1426 Expression::kEffect);
1469 // For all contexts except kEffect: We have the result on 1427 // For all contexts except kEffect: We have the result on
1470 // top of the stack. 1428 // top of the stack.
1471 if (expr->context() != Expression::kEffect) { 1429 if (expr->context() != Expression::kEffect) {
1472 MoveTOS(expr->context()); 1430 ApplyTOS(expr->context());
1473 } 1431 }
1474 } else { 1432 } else {
1475 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 1433 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
1476 expr->context()); 1434 expr->context());
1477 } 1435 }
1478 break; 1436 break;
1479 case NAMED_PROPERTY: { 1437 case NAMED_PROPERTY: {
1480 __ mov(ecx, prop->key()->AsLiteral()->handle()); 1438 __ mov(ecx, prop->key()->AsLiteral()->handle());
1481 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 1439 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
1482 __ call(ic, RelocInfo::CODE_TARGET); 1440 __ call(ic, RelocInfo::CODE_TARGET);
1483 // This nop signals to the IC that there is no inlined code at the call 1441 // This nop signals to the IC that there is no inlined code at the call
1484 // site for it to patch. 1442 // site for it to patch.
1485 __ nop(); 1443 __ nop();
1486 if (expr->is_postfix()) { 1444 if (expr->is_postfix()) {
1487 __ Drop(1); // Result is on the stack under the receiver. 1445 __ Drop(1); // Result is on the stack under the receiver.
1488 if (expr->context() != Expression::kEffect) { 1446 if (expr->context() != Expression::kEffect) {
1489 MoveTOS(expr->context()); 1447 ApplyTOS(expr->context());
1490 } 1448 }
1491 } else { 1449 } else {
1492 DropAndMove(expr->context(), eax); 1450 DropAndApply(1, expr->context(), eax);
1493 } 1451 }
1494 break; 1452 break;
1495 } 1453 }
1496 case KEYED_PROPERTY: { 1454 case KEYED_PROPERTY: {
1497 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 1455 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
1498 __ call(ic, RelocInfo::CODE_TARGET); 1456 __ call(ic, RelocInfo::CODE_TARGET);
1499 // This nop signals to the IC that there is no inlined code at the call 1457 // This nop signals to the IC that there is no inlined code at the call
1500 // site for it to patch. 1458 // site for it to patch.
1501 __ nop(); 1459 __ nop();
1502 if (expr->is_postfix()) { 1460 if (expr->is_postfix()) {
1503 __ Drop(2); // Result is on the stack under the key and the receiver. 1461 __ Drop(2); // Result is on the stack under the key and the receiver.
1504 if (expr->context() != Expression::kEffect) { 1462 if (expr->context() != Expression::kEffect) {
1505 MoveTOS(expr->context()); 1463 ApplyTOS(expr->context());
1506 } 1464 }
1507 } else { 1465 } else {
1508 DropAndMove(expr->context(), eax, 2); 1466 DropAndApply(2, expr->context(), eax);
1509 } 1467 }
1510 break; 1468 break;
1511 } 1469 }
1512 } 1470 }
1513 } 1471 }
1514 1472
1515 1473
1516 void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { 1474 void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
1517 Comment cmnt(masm_, "[ BinaryOperation"); 1475 Comment cmnt(masm_, "[ BinaryOperation");
1518 switch (expr->op()) { 1476 switch (expr->op()) {
(...skipping 22 matching lines...) Expand all
1541 case Token::SAR: { 1499 case Token::SAR: {
1542 ASSERT_EQ(Expression::kValue, expr->left()->context()); 1500 ASSERT_EQ(Expression::kValue, expr->left()->context());
1543 ASSERT_EQ(Expression::kValue, expr->right()->context()); 1501 ASSERT_EQ(Expression::kValue, expr->right()->context());
1544 1502
1545 Visit(expr->left()); 1503 Visit(expr->left());
1546 Visit(expr->right()); 1504 Visit(expr->right());
1547 GenericBinaryOpStub stub(expr->op(), 1505 GenericBinaryOpStub stub(expr->op(),
1548 NO_OVERWRITE, 1506 NO_OVERWRITE,
1549 NO_GENERIC_BINARY_FLAGS); 1507 NO_GENERIC_BINARY_FLAGS);
1550 __ CallStub(&stub); 1508 __ CallStub(&stub);
1551 Move(expr->context(), eax); 1509 Apply(expr->context(), eax);
1552 1510
1553 break; 1511 break;
1554 } 1512 }
1555 default: 1513 default:
1556 UNREACHABLE(); 1514 UNREACHABLE();
1557 } 1515 }
1558 } 1516 }
1559 1517
1560 1518
1561 void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) { 1519 void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
1712 break; 1670 break;
1713 } 1671 }
1714 true_label_ = saved_true; 1672 true_label_ = saved_true;
1715 false_label_ = saved_false; 1673 false_label_ = saved_false;
1716 // Convert current context to test context: End post-test code. 1674 // Convert current context to test context: End post-test code.
1717 } 1675 }
1718 1676
1719 1677
1720 void FastCodeGenerator::VisitThisFunction(ThisFunction* expr) { 1678 void FastCodeGenerator::VisitThisFunction(ThisFunction* expr) {
1721 __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 1679 __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
1722 Move(expr->context(), eax); 1680 Apply(expr->context(), eax);
1723 } 1681 }
1724 1682
1725 1683
1726 Register FastCodeGenerator::result_register() { return eax; } 1684 Register FastCodeGenerator::result_register() { return eax; }
1727 1685
1728 1686
1729 Register FastCodeGenerator::context_register() { return esi; } 1687 Register FastCodeGenerator::context_register() { return esi; }
1730 1688
1731 1689
1732 void FastCodeGenerator::StoreToFrameField(int frame_offset, Register value) { 1690 void FastCodeGenerator::StoreToFrameField(int frame_offset, Register value) {
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1767 __ add(Operand(edx), Immediate(masm_->CodeObject())); 1725 __ add(Operand(edx), Immediate(masm_->CodeObject()));
1768 __ mov(Operand(esp, 0), edx); 1726 __ mov(Operand(esp, 0), edx);
1769 // And return. 1727 // And return.
1770 __ ret(0); 1728 __ ret(0);
1771 } 1729 }
1772 1730
1773 1731
1774 #undef __ 1732 #undef __
1775 1733
1776 } } // namespace v8::internal 1734 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698