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

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

Issue 3357022: Handle both global and local variables potentially shadowed by... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 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/full-codegen.h » ('j') | src/x64/full-codegen-x64.cc » ('J')
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 861 matching lines...) Expand 10 before | Expand all | Expand 10 after
872 Apply(context_, r0); 872 Apply(context_, r0);
873 } 873 }
874 874
875 875
876 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { 876 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
877 Comment cmnt(masm_, "[ VariableProxy"); 877 Comment cmnt(masm_, "[ VariableProxy");
878 EmitVariableLoad(expr->var(), context_); 878 EmitVariableLoad(expr->var(), context_);
879 } 879 }
880 880
881 881
882 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(
883 Slot* slot,
884 Label* slow) {
885 ASSERT(slot->type() == Slot::CONTEXT);
886 Register current = cp;
887 Register next = r3;
888 Register temp = r4;
889
890 for (Scope* s = scope(); s != slot->var()->scope(); s = s->outer_scope()) {
891 if (s->num_heap_slots() > 0) {
892 if (s->calls_eval()) {
893 // Check that extension is NULL.
894 __ ldr(temp, ContextOperand(current, Context::EXTENSION_INDEX));
895 __ tst(temp, temp);
896 __ b(ne, slow);
897 }
898 __ ldr(next, ContextOperand(current, Context::CLOSURE_INDEX));
899 __ ldr(next, FieldMemOperand(next, JSFunction::kContextOffset));
900 // Walk the rest of the chain using a single register without
Søren Thygesen Gjesse 2010/09/10 07:44:24 delete "using a single register"
Mads Ager (chromium) 2010/09/10 10:51:43 Done.
901 // clobbering esi.
Søren Thygesen Gjesse 2010/09/10 07:44:24 esi -> cp
Mads Ager (chromium) 2010/09/10 10:51:43 Done.
902 current = next;
903 }
904 }
905 // Check that last extension is NULL.
906 __ ldr(temp, ContextOperand(current, Context::EXTENSION_INDEX));
907 __ tst(temp, temp);
908 __ b(ne, slow);
909 __ ldr(temp, ContextOperand(current, Context::FCONTEXT_INDEX));
910 return ContextOperand(temp, slot->index());
911 }
912
913
914 void FullCodeGenerator::EmitDynamicLoadFromSlotFastCase(
915 Slot* slot,
916 TypeofState typeof_state,
917 Label* slow,
918 Label* done) {
919 // Generate fast-case code for variables that might be shadowed by
920 // eval-introduced variables. Eval is used a lot without
921 // introducing variables. In those cases, we do not want to
922 // perform a runtime call for all variables in the scope
923 // containing the eval.
924 if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) {
925 EmitLoadGlobalSlotCheckExtensions(slot, typeof_state, slow);
926 __ jmp(done);
927 } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) {
928 Slot* potential_slot = slot->var()->local_if_not_shadowed()->slot();
929 Expression* rewrite = slot->var()->local_if_not_shadowed()->rewrite();
930 if (potential_slot != NULL) {
931 // Generate fast case for locals that rewrite to slots.
932 __ ldr(r0, ContextSlotOperandCheckExtensions(potential_slot, slow));
933 if (potential_slot->var()->mode() == Variable::CONST) {
Søren Thygesen Gjesse 2010/09/10 07:44:24 Line 1071 below could use the same pattern (a cond
Mads Ager (chromium) 2010/09/10 10:51:43 Good catch. Done. :)
934 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
935 __ cmp(r0, ip);
936 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq);
937 }
938 __ jmp(done);
939 } else if (rewrite != NULL) {
940 // Generate fast case for calls of an argument function.
941 Property* property = rewrite->AsProperty();
942 if (property != NULL) {
943 VariableProxy* obj_proxy = property->obj()->AsVariableProxy();
944 Literal* key_literal = property->key()->AsLiteral();
945 if (obj_proxy != NULL &&
946 key_literal != NULL &&
947 obj_proxy->IsArguments() &&
948 key_literal->handle()->IsSmi()) {
949 // Load arguments object if there are no eval-introduced
950 // variables. Then load the argument from the arguments
951 // object using keyed load.
952 __ ldr(r1,
953 ContextSlotOperandCheckExtensions(obj_proxy->var()->slot(),
954 slow));
955 __ mov(r0, Operand(key_literal->handle()));
956 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
957 __ Call(ic, RelocInfo::CODE_TARGET);
958 __ jmp(done);
959 }
960 }
961 }
962 }
963 }
964
965
882 void FullCodeGenerator::EmitLoadGlobalSlotCheckExtensions( 966 void FullCodeGenerator::EmitLoadGlobalSlotCheckExtensions(
883 Slot* slot, 967 Slot* slot,
884 TypeofState typeof_state, 968 TypeofState typeof_state,
885 Label* slow) { 969 Label* slow) {
886 Register current = cp; 970 Register current = cp;
887 Register next = r1; 971 Register next = r1;
888 Register temp = r2; 972 Register temp = r2;
889 973
890 Scope* s = scope(); 974 Scope* s = scope();
891 while (s != NULL) { 975 while (s != NULL) {
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
955 // object (receiver) in r0. 1039 // object (receiver) in r0.
956 __ ldr(r0, CodeGenerator::GlobalObject()); 1040 __ ldr(r0, CodeGenerator::GlobalObject());
957 __ mov(r2, Operand(var->name())); 1041 __ mov(r2, Operand(var->name()));
958 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 1042 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
959 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); 1043 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT);
960 Apply(context, r0); 1044 Apply(context, r0);
961 1045
962 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { 1046 } else if (slot != NULL && slot->type() == Slot::LOOKUP) {
963 Label done, slow; 1047 Label done, slow;
964 1048
965 // Generate fast-case code for variables that might be shadowed by 1049 // Generate code for loading from variables potentially shadowed
966 // eval-introduced variables. Eval is used a lot without 1050 // by eval-introduced variables.
967 // introducing variables. In those cases, we do not want to 1051 EmitDynamicLoadFromSlotFastCase(slot, NOT_INSIDE_TYPEOF, &slow, &done);
968 // perform a runtime call for all variables in the scope
969 // containing the eval.
970 if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) {
971 EmitLoadGlobalSlotCheckExtensions(slot, NOT_INSIDE_TYPEOF, &slow);
972 Apply(context, r0);
973 __ jmp(&done);
974 }
975 1052
976 __ bind(&slow); 1053 __ bind(&slow);
977 Comment cmnt(masm_, "Lookup slot"); 1054 Comment cmnt(masm_, "Lookup slot");
978 __ mov(r1, Operand(var->name())); 1055 __ mov(r1, Operand(var->name()));
979 __ Push(cp, r1); // Context and name. 1056 __ Push(cp, r1); // Context and name.
980 __ CallRuntime(Runtime::kLoadContextSlot, 2); 1057 __ CallRuntime(Runtime::kLoadContextSlot, 2);
1058 __ bind(&done);
1059
981 Apply(context, r0); 1060 Apply(context, r0);
982 __ bind(&done);
983 1061
984 } else if (slot != NULL) { 1062 } else if (slot != NULL) {
985 Comment cmnt(masm_, (slot->type() == Slot::CONTEXT) 1063 Comment cmnt(masm_, (slot->type() == Slot::CONTEXT)
986 ? "Context slot" 1064 ? "Context slot"
987 : "Stack slot"); 1065 : "Stack slot");
988 if (var->mode() == Variable::CONST) { 1066 if (var->mode() == Variable::CONST) {
989 // Constants may be the hole value if they have not been initialized. 1067 // Constants may be the hole value if they have not been initialized.
990 // Unhole them. 1068 // Unhole them.
991 Label done; 1069 Label done;
992 MemOperand slot_operand = EmitSlotSearch(slot, r0); 1070 MemOperand slot_operand = EmitSlotSearch(slot, r0);
(...skipping 722 matching lines...) Expand 10 before | Expand all | Expand 10 after
1715 // Restore context register. 1793 // Restore context register.
1716 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 1794 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
1717 DropAndApply(1, context_, r0); 1795 DropAndApply(1, context_, r0);
1718 } else if (var != NULL && !var->is_this() && var->is_global()) { 1796 } else if (var != NULL && !var->is_this() && var->is_global()) {
1719 // Push global object as receiver for the call IC. 1797 // Push global object as receiver for the call IC.
1720 __ ldr(r0, CodeGenerator::GlobalObject()); 1798 __ ldr(r0, CodeGenerator::GlobalObject());
1721 __ push(r0); 1799 __ push(r0);
1722 EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT); 1800 EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT);
1723 } else if (var != NULL && var->slot() != NULL && 1801 } else if (var != NULL && var->slot() != NULL &&
1724 var->slot()->type() == Slot::LOOKUP) { 1802 var->slot()->type() == Slot::LOOKUP) {
1725 // Call to a lookup slot (dynamically introduced variable). Call the 1803 // Call to a lookup slot (dynamically introduced variable).
1726 // runtime to find the function to call (returned in eax) and the object 1804 Label slow, done;
1727 // holding it (returned in edx). 1805
1806 // Generate code for loading from variables potentially shadowed
1807 // by eval-introduced variables.
1808 EmitDynamicLoadFromSlotFastCase(var->slot(),
1809 NOT_INSIDE_TYPEOF,
1810 &slow,
1811 &done);
1812
1813 __ bind(&slow);
1814 // Call the runtime to find the function to call (returned in eax)
1815 // and the object holding it (returned in edx).
1728 __ push(context_register()); 1816 __ push(context_register());
1729 __ mov(r2, Operand(var->name())); 1817 __ mov(r2, Operand(var->name()));
1730 __ push(r2); 1818 __ push(r2);
1731 __ CallRuntime(Runtime::kLoadContextSlot, 2); 1819 __ CallRuntime(Runtime::kLoadContextSlot, 2);
Søren Thygesen Gjesse 2010/09/10 07:44:24 Maybe change these two pushes to Push(r0, r1). It
Mads Ager (chromium) 2010/09/10 10:51:43 Done.
1732 __ push(r0); // Function. 1820 __ push(r0); // Function.
1733 __ push(r1); // Receiver. 1821 __ push(r1); // Receiver.
1822
1823 // If fast case code has been generated, emit code to push the
1824 // function and receiver and have the slow path jump around this
1825 // code.
1826 if (done.is_linked()) {
1827 Label call;
1828 __ b(&call);
1829 __ bind(&done);
1830 // Push function.
1831 __ push(r0);
1832 // Push global receiver.
1833 __ ldr(r1, CodeGenerator::GlobalObject());
1834 __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset));
Søren Thygesen Gjesse 2010/09/10 07:44:24 Maybe change to Push(r0, r1), or even better have
Mads Ager (chromium) 2010/09/10 10:51:43 That would be neat. I made it Push(r0, r1) for now
1835 __ push(r1);
1836 __ bind(&call);
1837 }
1838
1734 EmitCallWithStub(expr); 1839 EmitCallWithStub(expr);
1735 } else if (fun->AsProperty() != NULL) { 1840 } else if (fun->AsProperty() != NULL) {
1736 // Call to an object property. 1841 // Call to an object property.
1737 Property* prop = fun->AsProperty(); 1842 Property* prop = fun->AsProperty();
1738 Literal* key = prop->key()->AsLiteral(); 1843 Literal* key = prop->key()->AsLiteral();
1739 if (key != NULL && key->handle()->IsSymbol()) { 1844 if (key != NULL && key->handle()->IsSymbol()) {
1740 // Call to a named property, use call IC. 1845 // Call to a named property, use call IC.
1741 VisitForValue(prop->obj(), kStack); 1846 VisitForValue(prop->obj(), kStack);
1742 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); 1847 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET);
1743 } else { 1848 } else {
(...skipping 1251 matching lines...) Expand 10 before | Expand all | Expand 10 after
2995 __ ldr(r0, CodeGenerator::GlobalObject()); 3100 __ ldr(r0, CodeGenerator::GlobalObject());
2996 __ mov(r2, Operand(proxy->name())); 3101 __ mov(r2, Operand(proxy->name()));
2997 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 3102 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
2998 // Use a regular load, not a contextual load, to avoid a reference 3103 // Use a regular load, not a contextual load, to avoid a reference
2999 // error. 3104 // error.
3000 __ Call(ic, RelocInfo::CODE_TARGET); 3105 __ Call(ic, RelocInfo::CODE_TARGET);
3001 if (where == kStack) __ push(r0); 3106 if (where == kStack) __ push(r0);
3002 } else if (proxy != NULL && 3107 } else if (proxy != NULL &&
3003 proxy->var()->slot() != NULL && 3108 proxy->var()->slot() != NULL &&
3004 proxy->var()->slot()->type() == Slot::LOOKUP) { 3109 proxy->var()->slot()->type() == Slot::LOOKUP) {
3110 Label done, slow;
3111
3112 // Generate code for loading from variables potentially shadowed
3113 // by eval-introduced variables.
3114 Slot* slot = proxy->var()->slot();
3115 EmitDynamicLoadFromSlotFastCase(slot, INSIDE_TYPEOF, &slow, &done);
3116
3117 __ bind(&slow);
3005 __ mov(r0, Operand(proxy->name())); 3118 __ mov(r0, Operand(proxy->name()));
3006 __ Push(cp, r0); 3119 __ Push(cp, r0);
3007 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); 3120 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
3121 __ bind(&done);
3122
3008 if (where == kStack) __ push(r0); 3123 if (where == kStack) __ push(r0);
3009 } else { 3124 } else {
3010 // This expression cannot throw a reference error at the top level. 3125 // This expression cannot throw a reference error at the top level.
3011 VisitForValue(expr, where); 3126 VisitForValue(expr, where);
3012 } 3127 }
3013 } 3128 }
3014 3129
3015 3130
3016 bool FullCodeGenerator::TryLiteralCompare(Token::Value op, 3131 bool FullCodeGenerator::TryLiteralCompare(Token::Value op,
3017 Expression* left, 3132 Expression* left,
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after
3290 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. 3405 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value.
3291 __ add(pc, r1, Operand(masm_->CodeObject())); 3406 __ add(pc, r1, Operand(masm_->CodeObject()));
3292 } 3407 }
3293 3408
3294 3409
3295 #undef __ 3410 #undef __
3296 3411
3297 } } // namespace v8::internal 3412 } } // namespace v8::internal
3298 3413
3299 #endif // V8_TARGET_ARCH_ARM 3414 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « no previous file | src/full-codegen.h » ('j') | src/x64/full-codegen-x64.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698