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

Side by Side Diff: src/x64/full-codegen-x64.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
« src/arm/full-codegen-arm.cc ('K') | « src/x64/assembler-x64.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 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 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 925 matching lines...) Expand 10 before | Expand all | Expand 10 after
936 __ movq(rax, CodeGenerator::GlobalObject()); 936 __ movq(rax, CodeGenerator::GlobalObject());
937 __ Move(rcx, slot->var()->name()); 937 __ Move(rcx, slot->var()->name());
938 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 938 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
939 RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) 939 RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF)
940 ? RelocInfo::CODE_TARGET 940 ? RelocInfo::CODE_TARGET
941 : RelocInfo::CODE_TARGET_CONTEXT; 941 : RelocInfo::CODE_TARGET_CONTEXT;
942 __ call(ic, mode); 942 __ call(ic, mode);
943 } 943 }
944 944
945 945
946 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(
947 Slot* slot,
948 Label* slow) {
949 ASSERT(slot->type() == Slot::CONTEXT);
950 Register context = rsi;
951 Register temp = rbx;
952
953 for (Scope* s = scope(); s != slot->var()->scope(); s = s->outer_scope()) {
954 if (s->num_heap_slots() > 0) {
955 if (s->calls_eval()) {
956 // Check that extension is NULL.
957 __ cmpq(ContextOperand(context, Context::EXTENSION_INDEX),
958 Immediate(0));
959 __ j(not_equal, slow);
960 }
961 __ movq(temp, ContextOperand(context, Context::CLOSURE_INDEX));
962 __ movq(temp, FieldOperand(temp, JSFunction::kContextOffset));
963 // Walk the rest of the chain using a single register without
964 // clobbering esi.
Søren Thygesen Gjesse 2010/09/10 07:44:24 esi -> rsi
Mads Ager (chromium) 2010/09/10 10:51:43 Done.
965 context = temp;
966 }
967 }
968 // Check that last extension is NULL.
969 __ cmpq(ContextOperand(context, Context::EXTENSION_INDEX), Immediate(0));
970 __ j(not_equal, slow);
971 __ movq(temp, ContextOperand(context, Context::FCONTEXT_INDEX));
972 return ContextOperand(temp, slot->index());
973 }
974
975
976 void FullCodeGenerator::EmitDynamicLoadFromSlotFastCase(
977 Slot* slot,
978 TypeofState typeof_state,
979 Label* slow,
980 Label* done) {
981 // Generate fast-case code for variables that might be shadowed by
982 // eval-introduced variables. Eval is used a lot without
983 // introducing variables. In those cases, we do not want to
984 // perform a runtime call for all variables in the scope
985 // containing the eval.
986 if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) {
987 EmitLoadGlobalSlotCheckExtensions(slot, typeof_state, slow);
988 __ jmp(done);
989 } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) {
990 Slot* potential_slot = slot->var()->local_if_not_shadowed()->slot();
991 Expression* rewrite = slot->var()->local_if_not_shadowed()->rewrite();
992 if (potential_slot != NULL) {
993 // Generate fast case for locals that rewrite to slots.
994 __ movq(rax,
995 ContextSlotOperandCheckExtensions(potential_slot, slow));
996 if (potential_slot->var()->mode() == Variable::CONST) {
997 __ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
998 __ j(not_equal, done);
999 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
1000 }
1001 __ jmp(done);
1002 } else if (rewrite != NULL) {
1003 // Generate fast case for calls of an argument function.
1004 Property* property = rewrite->AsProperty();
1005 if (property != NULL) {
1006 VariableProxy* obj_proxy = property->obj()->AsVariableProxy();
1007 Literal* key_literal = property->key()->AsLiteral();
1008 if (obj_proxy != NULL &&
1009 key_literal != NULL &&
1010 obj_proxy->IsArguments() &&
1011 key_literal->handle()->IsSmi()) {
1012 // Load arguments object if there are no eval-introduced
1013 // variables. Then load the argument from the arguments
1014 // object using keyed load.
1015 __ movq(rdx,
1016 ContextSlotOperandCheckExtensions(obj_proxy->var()->slot(),
1017 slow));
1018 __ Move(rax, key_literal->handle());
1019 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
1020 __ call(ic, RelocInfo::CODE_TARGET);
1021 __ jmp(done);
1022 }
1023 }
1024 }
1025 }
1026 }
1027
1028
946 void FullCodeGenerator::EmitVariableLoad(Variable* var, 1029 void FullCodeGenerator::EmitVariableLoad(Variable* var,
947 Expression::Context context) { 1030 Expression::Context context) {
948 // Four cases: non-this global variables, lookup slots, all other 1031 // Four cases: non-this global variables, lookup slots, all other
949 // types of slots, and parameters that rewrite to explicit property 1032 // types of slots, and parameters that rewrite to explicit property
950 // accesses on the arguments object. 1033 // accesses on the arguments object.
951 Slot* slot = var->slot(); 1034 Slot* slot = var->slot();
952 Property* property = var->AsProperty(); 1035 Property* property = var->AsProperty();
953 1036
954 if (var->is_global() && !var->is_this()) { 1037 if (var->is_global() && !var->is_this()) {
955 Comment cmnt(masm_, "Global variable"); 1038 Comment cmnt(masm_, "Global variable");
956 // Use inline caching. Variable name is passed in rcx and the global 1039 // Use inline caching. Variable name is passed in rcx and the global
957 // object on the stack. 1040 // object on the stack.
958 __ Move(rcx, var->name()); 1041 __ Move(rcx, var->name());
959 __ movq(rax, CodeGenerator::GlobalObject()); 1042 __ movq(rax, CodeGenerator::GlobalObject());
960 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 1043 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
961 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); 1044 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT);
962 // A test rax instruction following the call is used by the IC to 1045 // A test rax instruction following the call is used by the IC to
963 // indicate that the inobject property case was inlined. Ensure there 1046 // indicate that the inobject property case was inlined. Ensure there
964 // is no test rax instruction here. 1047 // is no test rax instruction here.
965 __ nop(); 1048 __ nop();
966 Apply(context, rax); 1049 Apply(context, rax);
967 1050
968 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { 1051 } else if (slot != NULL && slot->type() == Slot::LOOKUP) {
969 Label done, slow; 1052 Label done, slow;
970 1053
971 // Generate fast-case code for variables that might be shadowed by 1054 // Generate code for loading from variables potentially shadowed
972 // eval-introduced variables. Eval is used a lot without 1055 // by eval-introduced variables.
973 // introducing variables. In those cases, we do not want to 1056 EmitDynamicLoadFromSlotFastCase(slot, NOT_INSIDE_TYPEOF, &slow, &done);
974 // perform a runtime call for all variables in the scope
975 // containing the eval.
976 if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) {
977 EmitLoadGlobalSlotCheckExtensions(slot, NOT_INSIDE_TYPEOF, &slow);
978 Apply(context, rax);
979 __ jmp(&done);
980 }
981 1057
982 __ bind(&slow); 1058 __ bind(&slow);
983 Comment cmnt(masm_, "Lookup slot"); 1059 Comment cmnt(masm_, "Lookup slot");
984 __ push(rsi); // Context. 1060 __ push(rsi); // Context.
985 __ Push(var->name()); 1061 __ Push(var->name());
986 __ CallRuntime(Runtime::kLoadContextSlot, 2); 1062 __ CallRuntime(Runtime::kLoadContextSlot, 2);
1063 __ bind(&done);
1064
987 Apply(context, rax); 1065 Apply(context, rax);
988 __ bind(&done);
989 1066
990 } else if (slot != NULL) { 1067 } else if (slot != NULL) {
991 Comment cmnt(masm_, (slot->type() == Slot::CONTEXT) 1068 Comment cmnt(masm_, (slot->type() == Slot::CONTEXT)
992 ? "Context slot" 1069 ? "Context slot"
993 : "Stack slot"); 1070 : "Stack slot");
994 if (var->mode() == Variable::CONST) { 1071 if (var->mode() == Variable::CONST) {
995 // Constants may be the hole value if they have not been initialized. 1072 // Constants may be the hole value if they have not been initialized.
996 // Unhole them. 1073 // Unhole them.
997 Label done; 1074 Label done;
998 MemOperand slot_operand = EmitSlotSearch(slot, rax); 1075 MemOperand slot_operand = EmitSlotSearch(slot, rax);
(...skipping 784 matching lines...) Expand 10 before | Expand all | Expand 10 after
1783 // Restore context register. 1860 // Restore context register.
1784 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 1861 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
1785 DropAndApply(1, context_, rax); 1862 DropAndApply(1, context_, rax);
1786 } else if (var != NULL && !var->is_this() && var->is_global()) { 1863 } else if (var != NULL && !var->is_this() && var->is_global()) {
1787 // Call to a global variable. 1864 // Call to a global variable.
1788 // Push global object as receiver for the call IC lookup. 1865 // Push global object as receiver for the call IC lookup.
1789 __ push(CodeGenerator::GlobalObject()); 1866 __ push(CodeGenerator::GlobalObject());
1790 EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT); 1867 EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT);
1791 } else if (var != NULL && var->slot() != NULL && 1868 } else if (var != NULL && var->slot() != NULL &&
1792 var->slot()->type() == Slot::LOOKUP) { 1869 var->slot()->type() == Slot::LOOKUP) {
1793 // Call to a lookup slot (dynamically introduced variable). Call 1870 // Call to a lookup slot (dynamically introduced variable).
1794 // the runtime to find the function to call (returned in rax) and 1871 Label slow, done;
1795 // the object holding it (returned in rdx). 1872
1873 // Generate code for loading from variables potentially shadowed
1874 // by eval-introduced variables.
1875 EmitDynamicLoadFromSlotFastCase(var->slot(),
1876 NOT_INSIDE_TYPEOF,
1877 &slow,
1878 &done);
1879
1880 __ bind(&slow);
1881 // Call the runtime to find the function to call (returned in rax)
1882 // and the object holding it (returned in rdx).
1796 __ push(context_register()); 1883 __ push(context_register());
1797 __ Push(var->name()); 1884 __ Push(var->name());
1798 __ CallRuntime(Runtime::kLoadContextSlot, 2); 1885 __ CallRuntime(Runtime::kLoadContextSlot, 2);
1799 __ push(rax); // Function. 1886 __ push(rax); // Function.
1800 __ push(rdx); // Receiver. 1887 __ push(rdx); // Receiver.
1888
1889 // If fast case code has been generated, emit code to push the
1890 // function and receiver and have the slow path jump around this
1891 // code.
1892 if (done.is_linked()) {
1893 Label call;
1894 __ jmp(&call);
1895 __ bind(&done);
1896 // Push function.
1897 __ push(rax);
1898 // Push global receiver.
1899 __ movq(rbx, CodeGenerator::GlobalObject());
1900 __ push(FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset));
1901 __ bind(&call);
1902 }
1903
1801 EmitCallWithStub(expr); 1904 EmitCallWithStub(expr);
1905
1802 } else if (fun->AsProperty() != NULL) { 1906 } else if (fun->AsProperty() != NULL) {
1803 // Call to an object property. 1907 // Call to an object property.
1804 Property* prop = fun->AsProperty(); 1908 Property* prop = fun->AsProperty();
1805 Literal* key = prop->key()->AsLiteral(); 1909 Literal* key = prop->key()->AsLiteral();
1806 if (key != NULL && key->handle()->IsSymbol()) { 1910 if (key != NULL && key->handle()->IsSymbol()) {
1807 // Call to a named property, use call IC. 1911 // Call to a named property, use call IC.
1808 VisitForValue(prop->obj(), kStack); 1912 VisitForValue(prop->obj(), kStack);
1809 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); 1913 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET);
1810 } else { 1914 } else {
1811 // Call to a keyed property. 1915 // Call to a keyed property.
(...skipping 1258 matching lines...) Expand 10 before | Expand all | Expand 10 after
3070 __ Move(rcx, proxy->name()); 3174 __ Move(rcx, proxy->name());
3071 __ movq(rax, CodeGenerator::GlobalObject()); 3175 __ movq(rax, CodeGenerator::GlobalObject());
3072 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 3176 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
3073 // Use a regular load, not a contextual load, to avoid a reference 3177 // Use a regular load, not a contextual load, to avoid a reference
3074 // error. 3178 // error.
3075 __ Call(ic, RelocInfo::CODE_TARGET); 3179 __ Call(ic, RelocInfo::CODE_TARGET);
3076 if (where == kStack) __ push(rax); 3180 if (where == kStack) __ push(rax);
3077 } else if (proxy != NULL && 3181 } else if (proxy != NULL &&
3078 proxy->var()->slot() != NULL && 3182 proxy->var()->slot() != NULL &&
3079 proxy->var()->slot()->type() == Slot::LOOKUP) { 3183 proxy->var()->slot()->type() == Slot::LOOKUP) {
3184 Label done, slow;
3185
3186 // Generate code for loading from variables potentially shadowed
3187 // by eval-introduced variables.
3188 Slot* slot = proxy->var()->slot();
3189 EmitDynamicLoadFromSlotFastCase(slot, INSIDE_TYPEOF, &slow, &done);
3190
3191 __ bind(&slow);
3080 __ push(rsi); 3192 __ push(rsi);
3081 __ Push(proxy->name()); 3193 __ Push(proxy->name());
3082 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); 3194 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
3195 __ bind(&done);
3196
3083 if (where == kStack) __ push(rax); 3197 if (where == kStack) __ push(rax);
3084 } else { 3198 } else {
3085 // This expression cannot throw a reference error at the top level. 3199 // This expression cannot throw a reference error at the top level.
3086 VisitForValue(expr, where); 3200 VisitForValue(expr, where);
3087 } 3201 }
3088 } 3202 }
3089 3203
3090 3204
3091 bool FullCodeGenerator::TryLiteralCompare(Token::Value op, 3205 bool FullCodeGenerator::TryLiteralCompare(Token::Value op,
3092 Expression* left, 3206 Expression* left,
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after
3356 __ ret(0); 3470 __ ret(0);
3357 } 3471 }
3358 3472
3359 3473
3360 #undef __ 3474 #undef __
3361 3475
3362 3476
3363 } } // namespace v8::internal 3477 } } // namespace v8::internal
3364 3478
3365 #endif // V8_TARGET_ARCH_X64 3479 #endif // V8_TARGET_ARCH_X64
OLDNEW
« src/arm/full-codegen-arm.cc ('K') | « src/x64/assembler-x64.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698