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

Side by Side Diff: src/arm/full-codegen-arm.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, 3 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 | « no previous file | src/ast.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 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 29 matching lines...) Expand all
40 40
41 #include "arm/code-stubs-arm.h" 41 #include "arm/code-stubs-arm.h"
42 42
43 namespace v8 { 43 namespace v8 {
44 namespace internal { 44 namespace internal {
45 45
46 #define __ ACCESS_MASM(masm_) 46 #define __ ACCESS_MASM(masm_)
47 47
48 48
49 static unsigned GetPropertyId(Property* property) { 49 static unsigned GetPropertyId(Property* property) {
50 if (property->is_synthetic()) return AstNode::kNoNumber;
51 return property->id(); 50 return property->id();
52 } 51 }
53 52
54 53
55 // A patch site is a location in the code which it is possible to patch. This 54 // A patch site is a location in the code which it is possible to patch. This
56 // class has a number of methods to emit the code which is patchable and the 55 // class has a number of methods to emit the code which is patchable and the
57 // method EmitPatchInfo to record a marker back to the patchable code. This 56 // method EmitPatchInfo to record a marker back to the patchable code. This
58 // marker is a cmp rx, #yyy instruction, and x * 0x00000fff + yyy (raw 12 bit 57 // marker is a cmp rx, #yyy instruction, and x * 0x00000fff + yyy (raw 12 bit
59 // immediate value is used) is the delta from the pc to the first instruction of 58 // immediate value is used) is the delta from the pc to the first instruction of
60 // the patchable code. 59 // the patchable code.
(...skipping 626 matching lines...) Expand 10 before | Expand all | Expand 10 after
687 } 686 }
688 } 687 }
689 688
690 689
691 void FullCodeGenerator::EmitDeclaration(Variable* variable, 690 void FullCodeGenerator::EmitDeclaration(Variable* variable,
692 Variable::Mode mode, 691 Variable::Mode mode,
693 FunctionLiteral* function) { 692 FunctionLiteral* function) {
694 Comment cmnt(masm_, "[ Declaration"); 693 Comment cmnt(masm_, "[ Declaration");
695 ASSERT(variable != NULL); // Must have been resolved. 694 ASSERT(variable != NULL); // Must have been resolved.
696 Slot* slot = variable->AsSlot(); 695 Slot* slot = variable->AsSlot();
697 Property* prop = variable->AsProperty(); 696 ASSERT(slot != NULL);
697 switch (slot->type()) {
698 case Slot::PARAMETER:
699 case Slot::LOCAL:
700 if (mode == Variable::CONST) {
701 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
702 __ str(ip, MemOperand(fp, SlotOffset(slot)));
703 } else if (function != NULL) {
704 VisitForAccumulatorValue(function);
705 __ str(result_register(), MemOperand(fp, SlotOffset(slot)));
706 }
707 break;
698 708
699 if (slot != NULL) { 709 case Slot::CONTEXT:
700 switch (slot->type()) { 710 // We bypass the general EmitSlotSearch because we know more about
701 case Slot::PARAMETER: 711 // this specific context.
702 case Slot::LOCAL:
703 if (mode == Variable::CONST) {
704 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
705 __ str(ip, MemOperand(fp, SlotOffset(slot)));
706 } else if (function != NULL) {
707 VisitForAccumulatorValue(function);
708 __ str(result_register(), MemOperand(fp, SlotOffset(slot)));
709 }
710 break;
711 712
712 case Slot::CONTEXT: 713 // The variable in the decl always resides in the current function
713 // We bypass the general EmitSlotSearch because we know more about 714 // context.
714 // this specific context. 715 ASSERT_EQ(0, scope()->ContextChainLength(variable->scope()));
716 if (FLAG_debug_code) {
717 // Check that we're not inside a with or catch context.
718 __ ldr(r1, FieldMemOperand(cp, HeapObject::kMapOffset));
719 __ CompareRoot(r1, Heap::kWithContextMapRootIndex);
720 __ Check(ne, "Declaration in with context.");
721 __ CompareRoot(r1, Heap::kCatchContextMapRootIndex);
722 __ Check(ne, "Declaration in catch context.");
723 }
724 if (mode == Variable::CONST) {
725 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
726 __ str(ip, ContextOperand(cp, slot->index()));
727 // No write barrier since the_hole_value is in old space.
728 } else if (function != NULL) {
729 VisitForAccumulatorValue(function);
730 __ str(result_register(), ContextOperand(cp, slot->index()));
731 int offset = Context::SlotOffset(slot->index());
732 // We know that we have written a function, which is not a smi.
733 __ mov(r1, Operand(cp));
734 __ RecordWrite(r1, Operand(offset), r2, result_register());
735 }
736 break;
715 737
716 // The variable in the decl always resides in the current function 738 case Slot::LOOKUP: {
717 // context. 739 __ mov(r2, Operand(variable->name()));
718 ASSERT_EQ(0, scope()->ContextChainLength(variable->scope())); 740 // Declaration nodes are always introduced in one of two modes.
719 if (FLAG_debug_code) { 741 ASSERT(mode == Variable::VAR ||
720 // Check that we're not inside a with or catch context. 742 mode == Variable::CONST ||
721 __ ldr(r1, FieldMemOperand(cp, HeapObject::kMapOffset)); 743 mode == Variable::LET);
722 __ CompareRoot(r1, Heap::kWithContextMapRootIndex); 744 PropertyAttributes attr = (mode == Variable::CONST) ? READ_ONLY : NONE;
723 __ Check(ne, "Declaration in with context."); 745 __ mov(r1, Operand(Smi::FromInt(attr)));
724 __ CompareRoot(r1, Heap::kCatchContextMapRootIndex); 746 // Push initial value, if any.
725 __ Check(ne, "Declaration in catch context."); 747 // Note: For variables we must not push an initial value (such as
726 } 748 // 'undefined') because we may have a (legal) redeclaration and we
727 if (mode == Variable::CONST) { 749 // must not destroy the current value.
728 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 750 if (mode == Variable::CONST) {
729 __ str(ip, ContextOperand(cp, slot->index())); 751 __ LoadRoot(r0, Heap::kTheHoleValueRootIndex);
730 // No write barrier since the_hole_value is in old space. 752 __ Push(cp, r2, r1, r0);
731 } else if (function != NULL) { 753 } else if (function != NULL) {
732 VisitForAccumulatorValue(function); 754 __ Push(cp, r2, r1);
733 __ str(result_register(), ContextOperand(cp, slot->index())); 755 // Push initial value for function declaration.
734 int offset = Context::SlotOffset(slot->index()); 756 VisitForStackValue(function);
735 // We know that we have written a function, which is not a smi. 757 } else {
736 __ mov(r1, Operand(cp)); 758 __ mov(r0, Operand(Smi::FromInt(0))); // No initial value!
737 __ RecordWrite(r1, Operand(offset), r2, result_register()); 759 __ Push(cp, r2, r1, r0);
738 }
739 break;
740
741 case Slot::LOOKUP: {
742 __ mov(r2, Operand(variable->name()));
743 // Declaration nodes are always introduced in one of two modes.
744 ASSERT(mode == Variable::VAR ||
745 mode == Variable::CONST ||
746 mode == Variable::LET);
747 PropertyAttributes attr = (mode == Variable::CONST) ? READ_ONLY : NONE;
748 __ mov(r1, Operand(Smi::FromInt(attr)));
749 // Push initial value, if any.
750 // Note: For variables we must not push an initial value (such as
751 // 'undefined') because we may have a (legal) redeclaration and we
752 // must not destroy the current value.
753 if (mode == Variable::CONST) {
754 __ LoadRoot(r0, Heap::kTheHoleValueRootIndex);
755 __ Push(cp, r2, r1, r0);
756 } else if (function != NULL) {
757 __ Push(cp, r2, r1);
758 // Push initial value for function declaration.
759 VisitForStackValue(function);
760 } else {
761 __ mov(r0, Operand(Smi::FromInt(0))); // No initial value!
762 __ Push(cp, r2, r1, r0);
763 }
764 __ CallRuntime(Runtime::kDeclareContextSlot, 4);
765 break;
766 } 760 }
767 } 761 __ CallRuntime(Runtime::kDeclareContextSlot, 4);
768 762 break;
769 } else if (prop != NULL) {
770 // A const declaration aliasing a parameter is an illegal redeclaration.
771 ASSERT(mode != Variable::CONST);
772 if (function != NULL) {
773 // We are declaring a function that rewrites to a property.
774 // Use (keyed) IC to set the initial value. We cannot visit the
775 // rewrite because it's shared and we risk recording duplicate AST
776 // IDs for bailouts from optimized code.
777 ASSERT(prop->obj()->AsVariableProxy() != NULL);
778 { AccumulatorValueContext for_object(this);
779 EmitVariableLoad(prop->obj()->AsVariableProxy());
780 }
781
782 __ push(r0);
783 VisitForAccumulatorValue(function);
784 __ pop(r2);
785
786 ASSERT(prop->key()->AsLiteral() != NULL &&
787 prop->key()->AsLiteral()->handle()->IsSmi());
788 __ mov(r1, Operand(prop->key()->AsLiteral()->handle()));
789
790 Handle<Code> ic = is_strict_mode()
791 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict()
792 : isolate()->builtins()->KeyedStoreIC_Initialize();
793 __ Call(ic);
794 // Value in r0 is ignored (declarations are statements).
795 } 763 }
796 } 764 }
797 } 765 }
798 766
799 767
800 void FullCodeGenerator::VisitDeclaration(Declaration* decl) { 768 void FullCodeGenerator::VisitDeclaration(Declaration* decl) {
801 EmitDeclaration(decl->proxy()->var(), decl->mode(), decl->fun()); 769 EmitDeclaration(decl->proxy()->var(), decl->mode(), decl->fun());
802 } 770 }
803 771
804 772
(...skipping 1460 matching lines...) Expand 10 before | Expand all | Expand 10 after
2265 Property* prop = fun->AsProperty(); 2233 Property* prop = fun->AsProperty();
2266 Literal* key = prop->key()->AsLiteral(); 2234 Literal* key = prop->key()->AsLiteral();
2267 if (key != NULL && key->handle()->IsSymbol()) { 2235 if (key != NULL && key->handle()->IsSymbol()) {
2268 // Call to a named property, use call IC. 2236 // Call to a named property, use call IC.
2269 { PreservePositionScope scope(masm()->positions_recorder()); 2237 { PreservePositionScope scope(masm()->positions_recorder());
2270 VisitForStackValue(prop->obj()); 2238 VisitForStackValue(prop->obj());
2271 } 2239 }
2272 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); 2240 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET);
2273 } else { 2241 } else {
2274 // Call to a keyed property. 2242 // Call to a keyed property.
2275 // For a synthetic property use keyed load IC followed by function call, 2243 { PreservePositionScope scope(masm()->positions_recorder());
2276 // for a regular property use EmitKeyedCallWithIC. 2244 VisitForStackValue(prop->obj());
2277 if (prop->is_synthetic()) {
2278 // Do not visit the object and key subexpressions (they are shared
2279 // by all occurrences of the same rewritten parameter).
2280 ASSERT(prop->obj()->AsVariableProxy() != NULL);
2281 ASSERT(prop->obj()->AsVariableProxy()->var()->AsSlot() != NULL);
2282 Slot* slot = prop->obj()->AsVariableProxy()->var()->AsSlot();
2283 MemOperand operand = EmitSlotSearch(slot, r1);
2284 __ ldr(r1, operand);
2285
2286 ASSERT(prop->key()->AsLiteral() != NULL);
2287 ASSERT(prop->key()->AsLiteral()->handle()->IsSmi());
2288 __ mov(r0, Operand(prop->key()->AsLiteral()->handle()));
2289
2290 // Record source code position for IC call.
2291 SetSourcePosition(prop->position());
2292
2293 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
2294 __ Call(ic, RelocInfo::CODE_TARGET, GetPropertyId(prop));
2295 __ ldr(r1, GlobalObjectOperand());
2296 __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset));
2297 __ Push(r0, r1); // Function, receiver.
2298 EmitCallWithStub(expr, NO_CALL_FUNCTION_FLAGS);
2299 } else {
2300 { PreservePositionScope scope(masm()->positions_recorder());
2301 VisitForStackValue(prop->obj());
2302 }
2303 EmitKeyedCallWithIC(expr, prop->key());
2304 } 2245 }
2246 EmitKeyedCallWithIC(expr, prop->key());
2305 } 2247 }
2306 } else { 2248 } else {
2307 { PreservePositionScope scope(masm()->positions_recorder()); 2249 { PreservePositionScope scope(masm()->positions_recorder());
2308 VisitForStackValue(fun); 2250 VisitForStackValue(fun);
2309 } 2251 }
2310 // Load global receiver object. 2252 // Load global receiver object.
2311 __ ldr(r1, GlobalObjectOperand()); 2253 __ ldr(r1, GlobalObjectOperand());
2312 __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); 2254 __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset));
2313 __ push(r1); 2255 __ push(r1);
2314 // Emit function call. 2256 // Emit function call.
(...skipping 1342 matching lines...) Expand 10 before | Expand all | Expand 10 after
3657 3599
3658 3600
3659 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { 3601 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
3660 switch (expr->op()) { 3602 switch (expr->op()) {
3661 case Token::DELETE: { 3603 case Token::DELETE: {
3662 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); 3604 Comment cmnt(masm_, "[ UnaryOperation (DELETE)");
3663 Property* prop = expr->expression()->AsProperty(); 3605 Property* prop = expr->expression()->AsProperty();
3664 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); 3606 Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
3665 3607
3666 if (prop != NULL) { 3608 if (prop != NULL) {
3667 if (prop->is_synthetic()) { 3609 VisitForStackValue(prop->obj());
3668 // Result of deleting parameters is false, even when they rewrite 3610 VisitForStackValue(prop->key());
3669 // to accesses on the arguments object. 3611 __ mov(r1, Operand(Smi::FromInt(strict_mode_flag())));
3670 context()->Plug(false); 3612 __ push(r1);
3671 } else { 3613 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
3672 VisitForStackValue(prop->obj()); 3614 context()->Plug(r0);
3673 VisitForStackValue(prop->key());
3674 __ mov(r1, Operand(Smi::FromInt(strict_mode_flag())));
3675 __ push(r1);
3676 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
3677 context()->Plug(r0);
3678 }
3679 } else if (var != NULL) { 3615 } else if (var != NULL) {
3680 // Delete of an unqualified identifier is disallowed in strict mode 3616 // Delete of an unqualified identifier is disallowed in strict mode
3681 // but "delete this" is. 3617 // but "delete this" is.
3682 ASSERT(strict_mode_flag() == kNonStrictMode || var->is_this()); 3618 ASSERT(strict_mode_flag() == kNonStrictMode || var->is_this());
3683 if (var->is_global()) { 3619 if (var->is_global()) {
3684 __ ldr(r2, GlobalObjectOperand()); 3620 __ ldr(r2, GlobalObjectOperand());
3685 __ mov(r1, Operand(var->name())); 3621 __ mov(r1, Operand(var->name()));
3686 __ mov(r0, Operand(Smi::FromInt(kNonStrictMode))); 3622 __ mov(r0, Operand(Smi::FromInt(kNonStrictMode)));
3687 __ Push(r2, r1, r0); 3623 __ Push(r2, r1, r0);
3688 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); 3624 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
(...skipping 606 matching lines...) Expand 10 before | Expand all | Expand 10 after
4295 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. 4231 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value.
4296 __ add(pc, r1, Operand(masm_->CodeObject())); 4232 __ add(pc, r1, Operand(masm_->CodeObject()));
4297 } 4233 }
4298 4234
4299 4235
4300 #undef __ 4236 #undef __
4301 4237
4302 } } // namespace v8::internal 4238 } } // namespace v8::internal
4303 4239
4304 #endif // V8_TARGET_ARCH_ARM 4240 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « no previous file | src/ast.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698