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

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

Issue 360054: Enable writes and reads of context slots in fast compiler. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 11 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ia32/fast-codegen-ia32.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2009 the V8 project authors. All rights reserved. 1 // Copyright 2009 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 400 matching lines...) Expand 10 before | Expand all | Expand 10 after
411 __ Push(boilerplate); 411 __ Push(boilerplate);
412 __ CallRuntime(Runtime::kNewClosure, 2); 412 __ CallRuntime(Runtime::kNewClosure, 2);
413 Move(expr->context(), rax); 413 Move(expr->context(), rax);
414 } 414 }
415 415
416 416
417 void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) { 417 void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
418 Comment cmnt(masm_, "[ VariableProxy"); 418 Comment cmnt(masm_, "[ VariableProxy");
419 Expression* rewrite = expr->var()->rewrite(); 419 Expression* rewrite = expr->var()->rewrite();
420 if (rewrite == NULL) { 420 if (rewrite == NULL) {
421 ASSERT(expr->var()->is_global());
421 Comment cmnt(masm_, "Global variable"); 422 Comment cmnt(masm_, "Global variable");
422 // Use inline caching. Variable name is passed in rcx and the global 423 // Use inline caching. Variable name is passed in rcx and the global
423 // object on the stack. 424 // object on the stack.
424 __ push(CodeGenerator::GlobalObject()); 425 __ push(CodeGenerator::GlobalObject());
425 __ Move(rcx, expr->name()); 426 __ Move(rcx, expr->name());
426 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 427 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
427 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); 428 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT);
428
429 // A test rax instruction following the call is used by the IC to 429 // A test rax instruction following the call is used by the IC to
430 // indicate that the inobject property case was inlined. Ensure there 430 // indicate that the inobject property case was inlined. Ensure there
431 // is no test rax instruction here. 431 // is no test rax instruction here.
432 __ nop();
433
432 DropAndMove(expr->context(), rax); 434 DropAndMove(expr->context(), rax);
433 } else { 435 } else {
434 Comment cmnt(masm_, "Stack slot"); 436 Slot* slot = rewrite->AsSlot();
435 Move(expr->context(), rewrite->AsSlot()); 437 ASSERT_NE(NULL, slot);
438 switch (slot->type()) {
439 case Slot::LOCAL:
440 case Slot::PARAMETER: {
441 Comment cmnt(masm_, "Stack slot");
442 Move(expr->context(), slot);
443 break;
444 }
445
446 case Slot::CONTEXT: {
447 Comment cmnt(masm_, "Context slot");
448 int chain_length =
449 function_->scope()->ContextChainLength(slot->var()->scope());
450 if (chain_length > 0) {
451 // Move up the chain of contexts to the context containing the slot.
452 __ movq(rax,
453 Operand(rsi, Context::SlotOffset(Context::CLOSURE_INDEX)));
454 // Load the function context (which is the incoming, outer context).
455 __ movq(rax, FieldOperand(rax, JSFunction::kContextOffset));
456 for (int i = 1; i < chain_length; i++) {
457 __ movq(rax,
458 Operand(rax, Context::SlotOffset(Context::CLOSURE_INDEX)));
459 __ movq(rax, FieldOperand(rax, JSFunction::kContextOffset));
460 }
461 // The context may be an intermediate context, not a function context.
462 __ movq(rax,
463 Operand(rax, Context::SlotOffset(Context::FCONTEXT_INDEX)));
464 } else { // Slot is in the current function context.
465 // The context may be an intermediate context, not a function context.
466 __ movq(rax,
467 Operand(rsi, Context::SlotOffset(Context::FCONTEXT_INDEX)));
468 }
469 __ movq(rax, Operand(rax, Context::SlotOffset(slot->index())));
470 Move(expr->context(), rax);
471 break;
472 }
473
474 case Slot::LOOKUP:
475 UNREACHABLE();
476 break;
477 }
436 } 478 }
437 } 479 }
438 480
439 481
440 void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { 482 void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
441 Comment cmnt(masm_, "[ RegExpLiteral"); 483 Comment cmnt(masm_, "[ RegExpLiteral");
442 Label done; 484 Label done;
443 // Registers will be used as follows: 485 // Registers will be used as follows:
444 // rdi = JS function. 486 // rdi = JS function.
445 // rbx = literals array. 487 // rbx = literals array.
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after
688 // rcx, and the global object on the stack. 730 // rcx, and the global object on the stack.
689 __ pop(rax); 731 __ pop(rax);
690 __ Move(rcx, var->name()); 732 __ Move(rcx, var->name());
691 __ push(CodeGenerator::GlobalObject()); 733 __ push(CodeGenerator::GlobalObject());
692 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 734 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
693 __ Call(ic, RelocInfo::CODE_TARGET); 735 __ Call(ic, RelocInfo::CODE_TARGET);
694 // Overwrite the global object on the stack with the result if needed. 736 // Overwrite the global object on the stack with the result if needed.
695 DropAndMove(expr->context(), rax); 737 DropAndMove(expr->context(), rax);
696 738
697 } else { 739 } else {
698 switch (expr->context()) { 740 Slot* slot = var->slot();
699 case Expression::kUninitialized: 741 ASSERT_NOT_NULL(slot); // Variables rewritten as properties not handled.
700 UNREACHABLE(); 742 switch (slot->type()) {
701 case Expression::kEffect: 743 case Slot::LOCAL:
702 // Perform assignment and discard value. 744 case Slot::PARAMETER: {
703 __ pop(Operand(rbp, SlotOffset(var->slot()))); 745 switch (expr->context()) {
704 break; 746 case Expression::kUninitialized:
705 case Expression::kValue: 747 UNREACHABLE();
706 // Perform assignment and preserve value. 748 case Expression::kEffect:
707 __ movq(rax, Operand(rsp, 0)); 749 // Perform assignment and discard value.
708 __ movq(Operand(rbp, SlotOffset(var->slot())), rax); 750 __ pop(Operand(rbp, SlotOffset(var->slot())));
709 break; 751 break;
710 case Expression::kTest: 752 case Expression::kValue:
711 // Perform assignment and test (and discard) value. 753 // Perform assignment and preserve value.
712 __ pop(rax); 754 __ movq(rax, Operand(rsp, 0));
713 __ movq(Operand(rbp, SlotOffset(var->slot())), rax); 755 __ movq(Operand(rbp, SlotOffset(var->slot())), rax);
714 TestAndBranch(rax, true_label_, false_label_); 756 break;
715 break; 757 case Expression::kTest:
716 case Expression::kValueTest: { 758 // Perform assignment and test (and discard) value.
717 Label discard; 759 __ pop(rax);
718 __ movq(rax, Operand(rsp, 0)); 760 __ movq(Operand(rbp, SlotOffset(var->slot())), rax);
719 __ movq(Operand(rbp, SlotOffset(var->slot())), rax); 761 TestAndBranch(rax, true_label_, false_label_);
720 TestAndBranch(rax, true_label_, &discard); 762 break;
721 __ bind(&discard); 763 case Expression::kValueTest: {
722 __ addq(rsp, Immediate(kPointerSize)); 764 Label discard;
723 __ jmp(false_label_); 765 __ movq(rax, Operand(rsp, 0));
766 __ movq(Operand(rbp, SlotOffset(var->slot())), rax);
767 TestAndBranch(rax, true_label_, &discard);
768 __ bind(&discard);
769 __ addq(rsp, Immediate(kPointerSize));
770 __ jmp(false_label_);
771 break;
772 }
773 case Expression::kTestValue: {
774 Label discard;
775 __ movq(rax, Operand(rsp, 0));
776 __ movq(Operand(rbp, SlotOffset(var->slot())), rax);
777 TestAndBranch(rax, &discard, false_label_);
778 __ bind(&discard);
779 __ addq(rsp, Immediate(kPointerSize));
780 __ jmp(true_label_);
781 break;
782 }
783 }
724 break; 784 break;
725 } 785 }
726 case Expression::kTestValue: { 786
727 Label discard; 787 case Slot::CONTEXT: {
728 __ movq(rax, Operand(rsp, 0)); 788 int chain_length =
729 __ movq(Operand(rbp, SlotOffset(var->slot())), rax); 789 function_->scope()->ContextChainLength(slot->var()->scope());
730 TestAndBranch(rax, &discard, false_label_); 790 if (chain_length > 0) {
731 __ bind(&discard); 791 // Move up the context chain to the context containing the slot.
732 __ addq(rsp, Immediate(kPointerSize)); 792 __ movq(rax,
733 __ jmp(true_label_); 793 Operand(rsi, Context::SlotOffset(Context::CLOSURE_INDEX)));
794 // Load the function context (which is the incoming, outer context).
795 __ movq(rax, FieldOperand(rax, JSFunction::kContextOffset));
796 for (int i = 1; i < chain_length; i++) {
797 __ movq(rax,
798 Operand(rax, Context::SlotOffset(Context::CLOSURE_INDEX)));
799 __ movq(rax, FieldOperand(rax, JSFunction::kContextOffset));
800 }
801 } else { // Slot is in the current context. Generate optimized code.
802 __ movq(rax, rsi); // RecordWrite destroys the object register.
803 }
804 if (FLAG_debug_code) {
805 __ cmpq(rax,
806 Operand(rax, Context::SlotOffset(Context::FCONTEXT_INDEX)));
807 __ Check(equal, "Context Slot chain length wrong.");
808 }
809 __ pop(rcx);
810 __ movq(Operand(rax, Context::SlotOffset(slot->index())), rcx);
811
812 // RecordWrite may destroy all its register arguments.
813 if (expr->context() == Expression::kValue) {
814 __ push(rcx);
815 } else if (expr->context() != Expression::kEffect) {
816 __ movq(rdx, rcx);
817 }
818 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize;
819 __ RecordWrite(rax, offset, rcx, rbx);
820 if (expr->context() != Expression::kEffect &&
821 expr->context() != Expression::kValue) {
822 Move(expr->context(), rdx);
823 }
734 break; 824 break;
735 } 825 }
826
827 case Slot::LOOKUP:
828 UNREACHABLE();
829 break;
736 } 830 }
737 } 831 }
738 } 832 }
739 833
740 834
741 void FastCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { 835 void FastCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
742 // Assignment to a property, using a named store IC. 836 // Assignment to a property, using a named store IC.
743 Property* prop = expr->target()->AsProperty(); 837 Property* prop = expr->target()->AsProperty();
744 ASSERT(prop != NULL); 838 ASSERT(prop != NULL);
745 ASSERT(prop->key()->AsLiteral() != NULL); 839 ASSERT(prop->key()->AsLiteral() != NULL);
(...skipping 663 matching lines...) Expand 10 before | Expand all | Expand 10 after
1409 true_label_ = saved_true; 1503 true_label_ = saved_true;
1410 false_label_ = saved_false; 1504 false_label_ = saved_false;
1411 // Convert current context to test context: End post-test code. 1505 // Convert current context to test context: End post-test code.
1412 } 1506 }
1413 1507
1414 1508
1415 #undef __ 1509 #undef __
1416 1510
1417 1511
1418 } } // namespace v8::internal 1512 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ia32/fast-codegen-ia32.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698