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

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

Issue 7753030: Remove code handling parameters rewritten to properties (aka synthetic properties). (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 9 years, 4 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
« no previous file with comments | « src/mips/full-codegen-mips.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 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 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 27 matching lines...) Expand all
38 #include "scopes.h" 38 #include "scopes.h"
39 #include "stub-cache.h" 39 #include "stub-cache.h"
40 40
41 namespace v8 { 41 namespace v8 {
42 namespace internal { 42 namespace internal {
43 43
44 #define __ ACCESS_MASM(masm_) 44 #define __ ACCESS_MASM(masm_)
45 45
46 46
47 static unsigned GetPropertyId(Property* property) { 47 static unsigned GetPropertyId(Property* property) {
48 if (property->is_synthetic()) return AstNode::kNoNumber;
49 return property->id(); 48 return property->id();
50 } 49 }
51 50
52 51
53 class JumpPatchSite BASE_EMBEDDED { 52 class JumpPatchSite BASE_EMBEDDED {
54 public: 53 public:
55 explicit JumpPatchSite(MacroAssembler* masm) 54 explicit JumpPatchSite(MacroAssembler* masm)
56 : masm_(masm) { 55 : masm_(masm) {
57 #ifdef DEBUG 56 #ifdef DEBUG
58 info_emitted_ = false; 57 info_emitted_ = false;
(...skipping 599 matching lines...) Expand 10 before | Expand all | Expand 10 after
658 } 657 }
659 } 658 }
660 659
661 660
662 void FullCodeGenerator::EmitDeclaration(Variable* variable, 661 void FullCodeGenerator::EmitDeclaration(Variable* variable,
663 Variable::Mode mode, 662 Variable::Mode mode,
664 FunctionLiteral* function) { 663 FunctionLiteral* function) {
665 Comment cmnt(masm_, "[ Declaration"); 664 Comment cmnt(masm_, "[ Declaration");
666 ASSERT(variable != NULL); // Must have been resolved. 665 ASSERT(variable != NULL); // Must have been resolved.
667 Slot* slot = variable->AsSlot(); 666 Slot* slot = variable->AsSlot();
668 Property* prop = variable->AsProperty(); 667 ASSERT(slot != NULL);
668 switch (slot->type()) {
669 case Slot::PARAMETER:
670 case Slot::LOCAL:
671 if (mode == Variable::CONST) {
672 __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
673 __ movq(Operand(rbp, SlotOffset(slot)), kScratchRegister);
674 } else if (function != NULL) {
675 VisitForAccumulatorValue(function);
676 __ movq(Operand(rbp, SlotOffset(slot)), result_register());
677 }
678 break;
669 679
670 if (slot != NULL) { 680 case Slot::CONTEXT:
671 switch (slot->type()) { 681 // We bypass the general EmitSlotSearch because we know more about
672 case Slot::PARAMETER: 682 // this specific context.
673 case Slot::LOCAL:
674 if (mode == Variable::CONST) {
675 __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
676 __ movq(Operand(rbp, SlotOffset(slot)), kScratchRegister);
677 } else if (function != NULL) {
678 VisitForAccumulatorValue(function);
679 __ movq(Operand(rbp, SlotOffset(slot)), result_register());
680 }
681 break;
682 683
683 case Slot::CONTEXT: 684 // The variable in the decl always resides in the current function
684 // We bypass the general EmitSlotSearch because we know more about 685 // context.
685 // this specific context. 686 ASSERT_EQ(0, scope()->ContextChainLength(variable->scope()));
687 if (FLAG_debug_code) {
688 // Check that we're not inside a with or catch context.
689 __ movq(rbx, FieldOperand(rsi, HeapObject::kMapOffset));
690 __ CompareRoot(rbx, Heap::kWithContextMapRootIndex);
691 __ Check(not_equal, "Declaration in with context.");
692 __ CompareRoot(rbx, Heap::kCatchContextMapRootIndex);
693 __ Check(not_equal, "Declaration in catch context.");
694 }
695 if (mode == Variable::CONST) {
696 __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
697 __ movq(ContextOperand(rsi, slot->index()), kScratchRegister);
698 // No write barrier since the hole value is in old space.
699 } else if (function != NULL) {
700 VisitForAccumulatorValue(function);
701 __ movq(ContextOperand(rsi, slot->index()), result_register());
702 int offset = Context::SlotOffset(slot->index());
703 __ movq(rbx, rsi);
704 __ RecordWrite(rbx, offset, result_register(), rcx);
705 }
706 break;
686 707
687 // The variable in the decl always resides in the current function 708 case Slot::LOOKUP: {
688 // context. 709 __ push(rsi);
689 ASSERT_EQ(0, scope()->ContextChainLength(variable->scope())); 710 __ Push(variable->name());
690 if (FLAG_debug_code) { 711 // Declaration nodes are always introduced in one of two modes.
691 // Check that we're not inside a with or catch context. 712 ASSERT(mode == Variable::VAR ||
692 __ movq(rbx, FieldOperand(rsi, HeapObject::kMapOffset)); 713 mode == Variable::CONST ||
693 __ CompareRoot(rbx, Heap::kWithContextMapRootIndex); 714 mode == Variable::LET);
694 __ Check(not_equal, "Declaration in with context."); 715 PropertyAttributes attr = (mode == Variable::CONST) ? READ_ONLY : NONE;
695 __ CompareRoot(rbx, Heap::kCatchContextMapRootIndex); 716 __ Push(Smi::FromInt(attr));
696 __ Check(not_equal, "Declaration in catch context."); 717 // Push initial value, if any.
697 } 718 // Note: For variables we must not push an initial value (such as
698 if (mode == Variable::CONST) { 719 // 'undefined') because we may have a (legal) redeclaration and we
699 __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex); 720 // must not destroy the current value.
700 __ movq(ContextOperand(rsi, slot->index()), kScratchRegister); 721 if (mode == Variable::CONST) {
701 // No write barrier since the hole value is in old space. 722 __ PushRoot(Heap::kTheHoleValueRootIndex);
702 } else if (function != NULL) { 723 } else if (function != NULL) {
703 VisitForAccumulatorValue(function); 724 VisitForStackValue(function);
704 __ movq(ContextOperand(rsi, slot->index()), result_register()); 725 } else {
705 int offset = Context::SlotOffset(slot->index()); 726 __ Push(Smi::FromInt(0)); // no initial value!
706 __ movq(rbx, rsi);
707 __ RecordWrite(rbx, offset, result_register(), rcx);
708 }
709 break;
710
711 case Slot::LOOKUP: {
712 __ push(rsi);
713 __ Push(variable->name());
714 // Declaration nodes are always introduced in one of two modes.
715 ASSERT(mode == Variable::VAR ||
716 mode == Variable::CONST ||
717 mode == Variable::LET);
718 PropertyAttributes attr = (mode == Variable::CONST) ? READ_ONLY : NONE;
719 __ Push(Smi::FromInt(attr));
720 // Push initial value, if any.
721 // Note: For variables we must not push an initial value (such as
722 // 'undefined') because we may have a (legal) redeclaration and we
723 // must not destroy the current value.
724 if (mode == Variable::CONST) {
725 __ PushRoot(Heap::kTheHoleValueRootIndex);
726 } else if (function != NULL) {
727 VisitForStackValue(function);
728 } else {
729 __ Push(Smi::FromInt(0)); // no initial value!
730 }
731 __ CallRuntime(Runtime::kDeclareContextSlot, 4);
732 break;
733 } 727 }
734 } 728 __ CallRuntime(Runtime::kDeclareContextSlot, 4);
735 729 break;
736 } else if (prop != NULL) {
737 // A const declaration aliasing a parameter is an illegal redeclaration.
738 ASSERT(mode != Variable::CONST);
739 if (function != NULL) {
740 // We are declaring a function that rewrites to a property.
741 // Use (keyed) IC to set the initial value. We cannot visit the
742 // rewrite because it's shared and we risk recording duplicate AST
743 // IDs for bailouts from optimized code.
744 ASSERT(prop->obj()->AsVariableProxy() != NULL);
745 { AccumulatorValueContext for_object(this);
746 EmitVariableLoad(prop->obj()->AsVariableProxy());
747 }
748 __ push(rax);
749 VisitForAccumulatorValue(function);
750 __ pop(rdx);
751 ASSERT(prop->key()->AsLiteral() != NULL &&
752 prop->key()->AsLiteral()->handle()->IsSmi());
753 __ Move(rcx, prop->key()->AsLiteral()->handle());
754
755 Handle<Code> ic = is_strict_mode()
756 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict()
757 : isolate()->builtins()->KeyedStoreIC_Initialize();
758 __ call(ic);
759 } 730 }
760 } 731 }
761 } 732 }
762 733
763 734
764 void FullCodeGenerator::VisitDeclaration(Declaration* decl) { 735 void FullCodeGenerator::VisitDeclaration(Declaration* decl) {
765 EmitDeclaration(decl->proxy()->var(), decl->mode(), decl->fun()); 736 EmitDeclaration(decl->proxy()->var(), decl->mode(), decl->fun());
766 } 737 }
767 738
768 739
(...skipping 1393 matching lines...) Expand 10 before | Expand all | Expand 10 after
2162 Property* prop = fun->AsProperty(); 2133 Property* prop = fun->AsProperty();
2163 Literal* key = prop->key()->AsLiteral(); 2134 Literal* key = prop->key()->AsLiteral();
2164 if (key != NULL && key->handle()->IsSymbol()) { 2135 if (key != NULL && key->handle()->IsSymbol()) {
2165 // Call to a named property, use call IC. 2136 // Call to a named property, use call IC.
2166 { PreservePositionScope scope(masm()->positions_recorder()); 2137 { PreservePositionScope scope(masm()->positions_recorder());
2167 VisitForStackValue(prop->obj()); 2138 VisitForStackValue(prop->obj());
2168 } 2139 }
2169 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); 2140 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET);
2170 } else { 2141 } else {
2171 // Call to a keyed property. 2142 // Call to a keyed property.
2172 // For a synthetic property use keyed load IC followed by function call, 2143 { PreservePositionScope scope(masm()->positions_recorder());
2173 // for a regular property use EmitKeyedCallWithIC. 2144 VisitForStackValue(prop->obj());
2174 if (prop->is_synthetic()) {
2175 // Do not visit the object and key subexpressions (they are shared
2176 // by all occurrences of the same rewritten parameter).
2177 ASSERT(prop->obj()->AsVariableProxy() != NULL);
2178 ASSERT(prop->obj()->AsVariableProxy()->var()->AsSlot() != NULL);
2179 Slot* slot = prop->obj()->AsVariableProxy()->var()->AsSlot();
2180 MemOperand operand = EmitSlotSearch(slot, rdx);
2181 __ movq(rdx, operand);
2182
2183 ASSERT(prop->key()->AsLiteral() != NULL);
2184 ASSERT(prop->key()->AsLiteral()->handle()->IsSmi());
2185 __ Move(rax, prop->key()->AsLiteral()->handle());
2186
2187 // Record source code position for IC call.
2188 SetSourcePosition(prop->position());
2189
2190 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
2191 __ call(ic, RelocInfo::CODE_TARGET, GetPropertyId(prop));
2192 // Push result (function).
2193 __ push(rax);
2194 // Push Global receiver.
2195 __ movq(rcx, GlobalObjectOperand());
2196 __ push(FieldOperand(rcx, GlobalObject::kGlobalReceiverOffset));
2197 EmitCallWithStub(expr, NO_CALL_FUNCTION_FLAGS);
2198 } else {
2199 { PreservePositionScope scope(masm()->positions_recorder());
2200 VisitForStackValue(prop->obj());
2201 }
2202 EmitKeyedCallWithIC(expr, prop->key());
2203 } 2145 }
2146 EmitKeyedCallWithIC(expr, prop->key());
2204 } 2147 }
2205 } else { 2148 } else {
2206 { PreservePositionScope scope(masm()->positions_recorder()); 2149 { PreservePositionScope scope(masm()->positions_recorder());
2207 VisitForStackValue(fun); 2150 VisitForStackValue(fun);
2208 } 2151 }
2209 // Load global receiver object. 2152 // Load global receiver object.
2210 __ movq(rbx, GlobalObjectOperand()); 2153 __ movq(rbx, GlobalObjectOperand());
2211 __ push(FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset)); 2154 __ push(FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset));
2212 // Emit function call. 2155 // Emit function call.
2213 EmitCallWithStub(expr, NO_CALL_FUNCTION_FLAGS); 2156 EmitCallWithStub(expr, NO_CALL_FUNCTION_FLAGS);
(...skipping 1378 matching lines...) Expand 10 before | Expand all | Expand 10 after
3592 3535
3593 3536
3594 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { 3537 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
3595 switch (expr->op()) { 3538 switch (expr->op()) {
3596 case Token::DELETE: { 3539 case Token::DELETE: {
3597 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); 3540 Comment cmnt(masm_, "[ UnaryOperation (DELETE)");
3598 Property* prop = expr->expression()->AsProperty(); 3541 Property* prop = expr->expression()->AsProperty();
3599 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); 3542 Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
3600 3543
3601 if (prop != NULL) { 3544 if (prop != NULL) {
3602 if (prop->is_synthetic()) { 3545 VisitForStackValue(prop->obj());
3603 // Result of deleting parameters is false, even when they rewrite 3546 VisitForStackValue(prop->key());
3604 // to accesses on the arguments object. 3547 __ Push(Smi::FromInt(strict_mode_flag()));
3605 context()->Plug(false); 3548 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
3606 } else { 3549 context()->Plug(rax);
3607 VisitForStackValue(prop->obj());
3608 VisitForStackValue(prop->key());
3609 __ Push(Smi::FromInt(strict_mode_flag()));
3610 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
3611 context()->Plug(rax);
3612 }
3613 } else if (var != NULL) { 3550 } else if (var != NULL) {
3614 // Delete of an unqualified identifier is disallowed in strict mode 3551 // Delete of an unqualified identifier is disallowed in strict mode
3615 // but "delete this" is. 3552 // but "delete this" is.
3616 ASSERT(strict_mode_flag() == kNonStrictMode || var->is_this()); 3553 ASSERT(strict_mode_flag() == kNonStrictMode || var->is_this());
3617 if (var->is_global()) { 3554 if (var->is_global()) {
3618 __ push(GlobalObjectOperand()); 3555 __ push(GlobalObjectOperand());
3619 __ Push(var->name()); 3556 __ Push(var->name());
3620 __ Push(Smi::FromInt(kNonStrictMode)); 3557 __ Push(Smi::FromInt(kNonStrictMode));
3621 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); 3558 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
3622 context()->Plug(rax); 3559 context()->Plug(rax);
(...skipping 614 matching lines...) Expand 10 before | Expand all | Expand 10 after
4237 __ jmp(rdx); 4174 __ jmp(rdx);
4238 } 4175 }
4239 4176
4240 4177
4241 #undef __ 4178 #undef __
4242 4179
4243 4180
4244 } } // namespace v8::internal 4181 } } // namespace v8::internal
4245 4182
4246 #endif // V8_TARGET_ARCH_X64 4183 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/mips/full-codegen-mips.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698