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

Side by Side Diff: src/ia32/full-codegen-ia32.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
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 929 matching lines...) Expand 10 before | Expand all | Expand 10 after
940 __ mov(eax, CodeGenerator::GlobalObject()); 940 __ mov(eax, CodeGenerator::GlobalObject());
941 __ mov(ecx, slot->var()->name()); 941 __ mov(ecx, slot->var()->name());
942 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 942 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
943 RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) 943 RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF)
944 ? RelocInfo::CODE_TARGET 944 ? RelocInfo::CODE_TARGET
945 : RelocInfo::CODE_TARGET_CONTEXT; 945 : RelocInfo::CODE_TARGET_CONTEXT;
946 __ call(ic, mode); 946 __ call(ic, mode);
947 } 947 }
948 948
949 949
950 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(
951 Slot* slot,
952 Label* slow) {
953 ASSERT(slot->type() == Slot::CONTEXT);
954 Register context = esi;
955 Register temp = ebx;
956
957 for (Scope* s = scope(); s != slot->var()->scope(); s = s->outer_scope()) {
958 if (s->num_heap_slots() > 0) {
959 if (s->calls_eval()) {
960 // Check that extension is NULL.
961 __ cmp(ContextOperand(context, Context::EXTENSION_INDEX),
962 Immediate(0));
963 __ j(not_equal, slow);
964 }
965 __ mov(temp, ContextOperand(context, Context::CLOSURE_INDEX));
966 __ mov(temp, FieldOperand(temp, JSFunction::kContextOffset));
967 // Walk the rest of the chain using a single register without
968 // clobbering esi.
969 context = temp;
970 }
971 }
972 // Check that last extension is NULL.
973 __ cmp(ContextOperand(context, Context::EXTENSION_INDEX), Immediate(0));
974 __ j(not_equal, slow);
975 __ mov(temp, ContextOperand(context, Context::FCONTEXT_INDEX));
976 return ContextOperand(temp, slot->index());
977 }
978
979
980 void FullCodeGenerator::EmitDynamicLoadFromSlotFastCase(
981 Slot* slot,
982 TypeofState typeof_state,
983 Label* slow,
984 Label* done) {
985 // Generate fast-case code for variables that might be shadowed by
986 // eval-introduced variables. Eval is used a lot without
987 // introducing variables. In those cases, we do not want to
988 // perform a runtime call for all variables in the scope
989 // containing the eval.
990 if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) {
991 EmitLoadGlobalSlotCheckExtensions(slot, typeof_state, slow);
992 __ jmp(done);
993 } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) {
994 Slot* potential_slot = slot->var()->local_if_not_shadowed()->slot();
995 Expression* rewrite = slot->var()->local_if_not_shadowed()->rewrite();
996 if (potential_slot != NULL) {
997 // Generate fast case for locals that rewrite to slots.
998 __ mov(eax,
999 ContextSlotOperandCheckExtensions(potential_slot, slow));
1000 if (potential_slot->var()->mode() == Variable::CONST) {
1001 __ cmp(eax, Factory::the_hole_value());
1002 __ j(not_equal, done);
1003 __ mov(eax, Factory::undefined_value());
1004 }
1005 __ jmp(done);
1006 } else if (rewrite != NULL) {
1007 // Generate fast case for calls of an argument function.
1008 Property* property = rewrite->AsProperty();
1009 if (property != NULL) {
1010 VariableProxy* obj_proxy = property->obj()->AsVariableProxy();
1011 Literal* key_literal = property->key()->AsLiteral();
1012 if (obj_proxy != NULL &&
1013 key_literal != NULL &&
1014 obj_proxy->IsArguments() &&
1015 key_literal->handle()->IsSmi()) {
1016 // Load arguments object if there are no eval-introduced
1017 // variables. Then load the argument from the arguments
1018 // object using keyed load.
1019 __ mov(edx,
1020 ContextSlotOperandCheckExtensions(obj_proxy->var()->slot(),
1021 slow));
1022 __ mov(eax, Immediate(key_literal->handle()));
1023 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
1024 __ call(ic, RelocInfo::CODE_TARGET);
1025 __ jmp(done);
1026 }
1027 }
1028 }
1029 }
1030 }
1031
1032
950 void FullCodeGenerator::EmitVariableLoad(Variable* var, 1033 void FullCodeGenerator::EmitVariableLoad(Variable* var,
951 Expression::Context context) { 1034 Expression::Context context) {
952 // Four cases: non-this global variables, lookup slots, all other 1035 // Four cases: non-this global variables, lookup slots, all other
953 // types of slots, and parameters that rewrite to explicit property 1036 // types of slots, and parameters that rewrite to explicit property
954 // accesses on the arguments object. 1037 // accesses on the arguments object.
955 Slot* slot = var->slot(); 1038 Slot* slot = var->slot();
956 Property* property = var->AsProperty(); 1039 Property* property = var->AsProperty();
957 1040
958 if (var->is_global() && !var->is_this()) { 1041 if (var->is_global() && !var->is_this()) {
959 Comment cmnt(masm_, "Global variable"); 1042 Comment cmnt(masm_, "Global variable");
960 // Use inline caching. Variable name is passed in ecx and the global 1043 // Use inline caching. Variable name is passed in ecx and the global
961 // object on the stack. 1044 // object on the stack.
962 __ mov(eax, CodeGenerator::GlobalObject()); 1045 __ mov(eax, CodeGenerator::GlobalObject());
963 __ mov(ecx, var->name()); 1046 __ mov(ecx, var->name());
964 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 1047 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
965 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT); 1048 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT);
966 // By emitting a nop we make sure that we do not have a test eax 1049 // By emitting a nop we make sure that we do not have a test eax
967 // instruction after the call it is treated specially by the LoadIC code 1050 // instruction after the call it is treated specially by the LoadIC code
968 // Remember that the assembler may choose to do peephole optimization 1051 // Remember that the assembler may choose to do peephole optimization
969 // (eg, push/pop elimination). 1052 // (eg, push/pop elimination).
970 __ nop(); 1053 __ nop();
971 Apply(context, eax); 1054 Apply(context, eax);
972 1055
973 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { 1056 } else if (slot != NULL && slot->type() == Slot::LOOKUP) {
974 Label done, slow; 1057 Label done, slow;
975 1058
976 // Generate fast-case code for variables that might be shadowed by 1059 // Generate code for loading from variables potentially shadowed
977 // eval-introduced variables. Eval is used a lot without 1060 // by eval-introduced variables.
978 // introducing variables. In those cases, we do not want to 1061 EmitDynamicLoadFromSlotFastCase(slot, NOT_INSIDE_TYPEOF, &slow, &done);
979 // perform a runtime call for all variables in the scope
980 // containing the eval.
981 if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) {
982 EmitLoadGlobalSlotCheckExtensions(slot, NOT_INSIDE_TYPEOF, &slow);
983 Apply(context, eax);
984 __ jmp(&done);
985 }
986 1062
987 __ bind(&slow); 1063 __ bind(&slow);
988 Comment cmnt(masm_, "Lookup slot"); 1064 Comment cmnt(masm_, "Lookup slot");
989 __ push(esi); // Context. 1065 __ push(esi); // Context.
990 __ push(Immediate(var->name())); 1066 __ push(Immediate(var->name()));
991 __ CallRuntime(Runtime::kLoadContextSlot, 2); 1067 __ CallRuntime(Runtime::kLoadContextSlot, 2);
1068 __ bind(&done);
1069
992 Apply(context, eax); 1070 Apply(context, eax);
993 __ bind(&done);
994 1071
995 } else if (slot != NULL) { 1072 } else if (slot != NULL) {
996 Comment cmnt(masm_, (slot->type() == Slot::CONTEXT) 1073 Comment cmnt(masm_, (slot->type() == Slot::CONTEXT)
997 ? "Context slot" 1074 ? "Context slot"
998 : "Stack slot"); 1075 : "Stack slot");
999 if (var->mode() == Variable::CONST) { 1076 if (var->mode() == Variable::CONST) {
1000 // Constants may be the hole value if they have not been initialized. 1077 // Constants may be the hole value if they have not been initialized.
1001 // Unhole them. 1078 // Unhole them.
1002 Label done; 1079 Label done;
1003 MemOperand slot_operand = EmitSlotSearch(slot, eax); 1080 MemOperand slot_operand = EmitSlotSearch(slot, eax);
(...skipping 1019 matching lines...) Expand 10 before | Expand all | Expand 10 after
2023 __ CallStub(&stub); 2100 __ CallStub(&stub);
2024 // Restore context register. 2101 // Restore context register.
2025 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 2102 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
2026 DropAndApply(1, context_, eax); 2103 DropAndApply(1, context_, eax);
2027 } else if (var != NULL && !var->is_this() && var->is_global()) { 2104 } else if (var != NULL && !var->is_this() && var->is_global()) {
2028 // Push global object as receiver for the call IC. 2105 // Push global object as receiver for the call IC.
2029 __ push(CodeGenerator::GlobalObject()); 2106 __ push(CodeGenerator::GlobalObject());
2030 EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT); 2107 EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT);
2031 } else if (var != NULL && var->slot() != NULL && 2108 } else if (var != NULL && var->slot() != NULL &&
2032 var->slot()->type() == Slot::LOOKUP) { 2109 var->slot()->type() == Slot::LOOKUP) {
2033 // Call to a lookup slot (dynamically introduced variable). Call the 2110 // Call to a lookup slot (dynamically introduced variable).
2034 // runtime to find the function to call (returned in eax) and the object 2111 Label slow, done;
2035 // holding it (returned in edx). 2112
2113 // Generate code for loading from variables potentially shadowed
2114 // by eval-introduced variables.
2115 EmitDynamicLoadFromSlotFastCase(var->slot(),
2116 NOT_INSIDE_TYPEOF,
2117 &slow,
2118 &done);
2119
2120 __ bind(&slow);
2121 // Call the runtime to find the function to call (returned in eax)
2122 // and the object holding it (returned in edx).
2036 __ push(context_register()); 2123 __ push(context_register());
2037 __ push(Immediate(var->name())); 2124 __ push(Immediate(var->name()));
2038 __ CallRuntime(Runtime::kLoadContextSlot, 2); 2125 __ CallRuntime(Runtime::kLoadContextSlot, 2);
2039 __ push(eax); // Function. 2126 __ push(eax); // Function.
2040 __ push(edx); // Receiver. 2127 __ push(edx); // Receiver.
2128
2129 // If fast case code has been generated, emit code to push the
2130 // function and receiver and have the slow path jump around this
2131 // code.
2132 if (done.is_linked()) {
2133 Label call;
2134 __ jmp(&call);
2135 __ bind(&done);
2136 // Push function.
2137 __ push(eax);
2138 // Push global receiver.
2139 __ mov(ebx, CodeGenerator::GlobalObject());
2140 __ push(FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset));
2141 __ bind(&call);
2142 }
2143
2041 EmitCallWithStub(expr); 2144 EmitCallWithStub(expr);
2042 } else if (fun->AsProperty() != NULL) { 2145 } else if (fun->AsProperty() != NULL) {
2043 // Call to an object property. 2146 // Call to an object property.
2044 Property* prop = fun->AsProperty(); 2147 Property* prop = fun->AsProperty();
2045 Literal* key = prop->key()->AsLiteral(); 2148 Literal* key = prop->key()->AsLiteral();
2046 if (key != NULL && key->handle()->IsSymbol()) { 2149 if (key != NULL && key->handle()->IsSymbol()) {
2047 // Call to a named property, use call IC. 2150 // Call to a named property, use call IC.
2048 VisitForValue(prop->obj(), kStack); 2151 VisitForValue(prop->obj(), kStack);
2049 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); 2152 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET);
2050 } else { 2153 } else {
(...skipping 1283 matching lines...) Expand 10 before | Expand all | Expand 10 after
3334 __ mov(eax, CodeGenerator::GlobalObject()); 3437 __ mov(eax, CodeGenerator::GlobalObject());
3335 __ mov(ecx, Immediate(proxy->name())); 3438 __ mov(ecx, Immediate(proxy->name()));
3336 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 3439 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
3337 // Use a regular load, not a contextual load, to avoid a reference 3440 // Use a regular load, not a contextual load, to avoid a reference
3338 // error. 3441 // error.
3339 __ call(ic, RelocInfo::CODE_TARGET); 3442 __ call(ic, RelocInfo::CODE_TARGET);
3340 if (where == kStack) __ push(eax); 3443 if (where == kStack) __ push(eax);
3341 } else if (proxy != NULL && 3444 } else if (proxy != NULL &&
3342 proxy->var()->slot() != NULL && 3445 proxy->var()->slot() != NULL &&
3343 proxy->var()->slot()->type() == Slot::LOOKUP) { 3446 proxy->var()->slot()->type() == Slot::LOOKUP) {
3447 Label done, slow;
3448
3449 // Generate code for loading from variables potentially shadowed
3450 // by eval-introduced variables.
3451 Slot* slot = proxy->var()->slot();
3452 EmitDynamicLoadFromSlotFastCase(slot, INSIDE_TYPEOF, &slow, &done);
3453
3454 __ bind(&slow);
3344 __ push(esi); 3455 __ push(esi);
3345 __ push(Immediate(proxy->name())); 3456 __ push(Immediate(proxy->name()));
3346 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); 3457 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
3458 __ bind(&done);
3459
3347 if (where == kStack) __ push(eax); 3460 if (where == kStack) __ push(eax);
3348 } else { 3461 } else {
3349 // This expression cannot throw a reference error at the top level. 3462 // This expression cannot throw a reference error at the top level.
3350 VisitForValue(expr, where); 3463 VisitForValue(expr, where);
3351 } 3464 }
3352 } 3465 }
3353 3466
3354 3467
3355 bool FullCodeGenerator::TryLiteralCompare(Token::Value op, 3468 bool FullCodeGenerator::TryLiteralCompare(Token::Value op,
3356 Expression* left, 3469 Expression* left,
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after
3620 // And return. 3733 // And return.
3621 __ ret(0); 3734 __ ret(0);
3622 } 3735 }
3623 3736
3624 3737
3625 #undef __ 3738 #undef __
3626 3739
3627 } } // namespace v8::internal 3740 } } // namespace v8::internal
3628 3741
3629 #endif // V8_TARGET_ARCH_IA32 3742 #endif // V8_TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698