Chromium Code Reviews

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

Issue 7039036: Fix calls of strict mode function with an implicit receiver. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Fix presubmit Created 9 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | | Annotate | Revision Log
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 112 matching lines...)
123 SetFunctionPosition(function()); 123 SetFunctionPosition(function());
124 Comment cmnt(masm_, "[ function compiled by full code generator"); 124 Comment cmnt(masm_, "[ function compiled by full code generator");
125 125
126 #ifdef DEBUG 126 #ifdef DEBUG
127 if (strlen(FLAG_stop_at) > 0 && 127 if (strlen(FLAG_stop_at) > 0 &&
128 info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { 128 info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
129 __ int3(); 129 __ int3();
130 } 130 }
131 #endif 131 #endif
132 132
133 // Strict mode functions need to replace the receiver with undefined
134 // when called with an implicit receiver. ecx is zero for explicit
135 // receiver calls and one for implicit receiver calls.
136 if (info->is_strict_mode()) {
137 Label ok;
138 __ test(ecx, Operand(ecx));
139 __ j(zero, &ok, Label::kNear);
140 // +1 for return address.
141 int receiver_offset = (scope()->num_parameters() + 1) * kPointerSize;
142 __ mov(Operand(esp, receiver_offset),
143 Immediate(isolate()->factory()->undefined_value()));
144 __ bind(&ok);
145 }
146
133 __ push(ebp); // Caller's frame pointer. 147 __ push(ebp); // Caller's frame pointer.
134 __ mov(ebp, esp); 148 __ mov(ebp, esp);
135 __ push(esi); // Callee's context. 149 __ push(esi); // Callee's context.
136 __ push(edi); // Callee's JS Function. 150 __ push(edi); // Callee's JS Function.
137 151
138 { Comment cmnt(masm_, "[ Allocate locals"); 152 { Comment cmnt(masm_, "[ Allocate locals");
139 int locals_count = scope()->num_stack_slots(); 153 int locals_count = scope()->num_stack_slots();
140 if (locals_count == 1) { 154 if (locals_count == 1) {
141 __ push(Immediate(isolate()->factory()->undefined_value())); 155 __ push(Immediate(isolate()->factory()->undefined_value()));
142 } else if (locals_count > 1) { 156 } else if (locals_count > 1) {
(...skipping 1894 matching lines...)
2037 int arg_count = args->length(); 2051 int arg_count = args->length();
2038 { PreservePositionScope scope(masm()->positions_recorder()); 2052 { PreservePositionScope scope(masm()->positions_recorder());
2039 for (int i = 0; i < arg_count; i++) { 2053 for (int i = 0; i < arg_count; i++) {
2040 VisitForStackValue(args->at(i)); 2054 VisitForStackValue(args->at(i));
2041 } 2055 }
2042 __ Set(ecx, Immediate(name)); 2056 __ Set(ecx, Immediate(name));
2043 } 2057 }
2044 // Record source position of the IC call. 2058 // Record source position of the IC call.
2045 SetSourcePosition(expr->position()); 2059 SetSourcePosition(expr->position());
2046 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 2060 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
2047 Handle<Code> ic = isolate()->stub_cache()->ComputeCallInitialize( 2061 Handle<Code> ic =
2048 arg_count, in_loop); 2062 isolate()->stub_cache()->ComputeCallInitialize(arg_count, in_loop, mode);
2049 EmitCallIC(ic, mode, expr->id()); 2063 EmitCallIC(ic, mode, expr->id());
2050 RecordJSReturnSite(expr); 2064 RecordJSReturnSite(expr);
2051 // Restore context register. 2065 // Restore context register.
2052 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 2066 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
2053 context()->Plug(eax); 2067 context()->Plug(eax);
2054 } 2068 }
2055 2069
2056 2070
2057 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, 2071 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr,
2058 Expression* key, 2072 Expression* key) {
2059 RelocInfo::Mode mode) {
2060 // Load the key. 2073 // Load the key.
2061 VisitForAccumulatorValue(key); 2074 VisitForAccumulatorValue(key);
2062 2075
2063 // Swap the name of the function and the receiver on the stack to follow 2076 // Swap the name of the function and the receiver on the stack to follow
2064 // the calling convention for call ICs. 2077 // the calling convention for call ICs.
2065 __ pop(ecx); 2078 __ pop(ecx);
2066 __ push(eax); 2079 __ push(eax);
2067 __ push(ecx); 2080 __ push(ecx);
2068 2081
2069 // Load the arguments. 2082 // Load the arguments.
2070 ZoneList<Expression*>* args = expr->arguments(); 2083 ZoneList<Expression*>* args = expr->arguments();
2071 int arg_count = args->length(); 2084 int arg_count = args->length();
2072 { PreservePositionScope scope(masm()->positions_recorder()); 2085 { PreservePositionScope scope(masm()->positions_recorder());
2073 for (int i = 0; i < arg_count; i++) { 2086 for (int i = 0; i < arg_count; i++) {
2074 VisitForStackValue(args->at(i)); 2087 VisitForStackValue(args->at(i));
2075 } 2088 }
2076 } 2089 }
2077 // Record source position of the IC call. 2090 // Record source position of the IC call.
2078 SetSourcePosition(expr->position()); 2091 SetSourcePosition(expr->position());
2079 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 2092 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
2080 Handle<Code> ic = isolate()->stub_cache()->ComputeKeyedCallInitialize( 2093 Handle<Code> ic = isolate()->stub_cache()->ComputeKeyedCallInitialize(
2081 arg_count, in_loop); 2094 arg_count, in_loop);
2082 __ mov(ecx, Operand(esp, (arg_count + 1) * kPointerSize)); // Key. 2095 __ mov(ecx, Operand(esp, (arg_count + 1) * kPointerSize)); // Key.
2083 EmitCallIC(ic, mode, expr->id()); 2096 EmitCallIC(ic, RelocInfo::CODE_TARGET, expr->id());
2084 RecordJSReturnSite(expr); 2097 RecordJSReturnSite(expr);
2085 // Restore context register. 2098 // Restore context register.
2086 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 2099 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
2087 context()->DropAndPlug(1, eax); // Drop the key still on the stack. 2100 context()->DropAndPlug(1, eax); // Drop the key still on the stack.
2088 } 2101 }
2089 2102
2090 2103
2091 void FullCodeGenerator::EmitCallWithStub(Call* expr, CallFunctionFlags flags) { 2104 void FullCodeGenerator::EmitCallWithStub(Call* expr, CallFunctionFlags flags) {
2092 // Code common for calls using the call stub. 2105 // Code common for calls using the call stub.
2093 ZoneList<Expression*>* args = expr->arguments(); 2106 ZoneList<Expression*>* args = expr->arguments();
(...skipping 90 matching lines...)
2184 } 2197 }
2185 2198
2186 // The runtime call returns a pair of values in eax (function) and 2199 // The runtime call returns a pair of values in eax (function) and
2187 // edx (receiver). Touch up the stack with the right values. 2200 // edx (receiver). Touch up the stack with the right values.
2188 __ mov(Operand(esp, (arg_count + 0) * kPointerSize), edx); 2201 __ mov(Operand(esp, (arg_count + 0) * kPointerSize), edx);
2189 __ mov(Operand(esp, (arg_count + 1) * kPointerSize), eax); 2202 __ mov(Operand(esp, (arg_count + 1) * kPointerSize), eax);
2190 } 2203 }
2191 // Record source position for debugger. 2204 // Record source position for debugger.
2192 SetSourcePosition(expr->position()); 2205 SetSourcePosition(expr->position());
2193 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 2206 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
2194 CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); 2207 CallFunctionStub stub(arg_count,
2208 in_loop,
2209 NON_VALUE_RECEIVER_MIGHT_BE_IMPLICIT);
Kevin Millikin (Chromium) 2011/05/18 15:57:23 Why not MIGHT_BE_VALUE | MIGHT_BE_IMPLICIT? Don't
Mads Ager (chromium) 2011/05/23 16:31:34 Yes, this does dodge the value check. I convinced
2195 __ CallStub(&stub); 2210 __ CallStub(&stub);
2196 RecordJSReturnSite(expr); 2211 RecordJSReturnSite(expr);
2197 // Restore context register. 2212 // Restore context register.
2198 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 2213 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
2199 context()->DropAndPlug(1, eax); 2214 context()->DropAndPlug(1, eax);
2200 } else if (var != NULL && !var->is_this() && var->is_global()) { 2215 } else if (var != NULL && !var->is_this() && var->is_global()) {
2201 // Push global object as receiver for the call IC. 2216 // Push global object as receiver for the call IC.
2202 __ push(GlobalObjectOperand()); 2217 __ push(GlobalObjectOperand());
2203 EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT); 2218 EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT);
2204 } else if (var != NULL && var->AsSlot() != NULL && 2219 } else if (var != NULL && var->AsSlot() != NULL &&
(...skipping 27 matching lines...)
2232 __ jmp(&call); 2247 __ jmp(&call);
2233 __ bind(&done); 2248 __ bind(&done);
2234 // Push function. 2249 // Push function.
2235 __ push(eax); 2250 __ push(eax);
2236 // Push global receiver. 2251 // Push global receiver.
2237 __ mov(ebx, GlobalObjectOperand()); 2252 __ mov(ebx, GlobalObjectOperand());
2238 __ push(FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset)); 2253 __ push(FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset));
2239 __ bind(&call); 2254 __ bind(&call);
2240 } 2255 }
2241 2256
2242 // The receiver is either the global receiver or a JSObject found by 2257 // The receiver is either the global receiver or an object found
2243 // LoadContextSlot. 2258 // by LoadContextSlot. That object could be the hole if the
2244 EmitCallWithStub(expr, NO_CALL_FUNCTION_FLAGS); 2259 // receiver is implicitly the global object.
2260 EmitCallWithStub(expr, RECEIVER_MIGHT_BE_VALUE);
Kevin Millikin (Chromium) 2011/05/18 15:57:23 Why MIGHT_BE_VALUE? It wasn't before, but I can s
Mads Ager (chromium) 2011/05/23 16:31:34 Yes, I need to change the name of the flags to mak
2245 } else if (fun->AsProperty() != NULL) { 2261 } else if (fun->AsProperty() != NULL) {
2246 // Call to an object property. 2262 // Call to an object property.
2247 Property* prop = fun->AsProperty(); 2263 Property* prop = fun->AsProperty();
2248 Literal* key = prop->key()->AsLiteral(); 2264 Literal* key = prop->key()->AsLiteral();
2249 if (key != NULL && key->handle()->IsSymbol()) { 2265 if (key != NULL && key->handle()->IsSymbol()) {
2250 // Call to a named property, use call IC. 2266 // Call to a named property, use call IC.
2251 { PreservePositionScope scope(masm()->positions_recorder()); 2267 { PreservePositionScope scope(masm()->positions_recorder());
2252 VisitForStackValue(prop->obj()); 2268 VisitForStackValue(prop->obj());
2253 } 2269 }
2254 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); 2270 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET);
(...skipping 22 matching lines...)
2277 // Push result (function). 2293 // Push result (function).
2278 __ push(eax); 2294 __ push(eax);
2279 // Push Global receiver. 2295 // Push Global receiver.
2280 __ mov(ecx, GlobalObjectOperand()); 2296 __ mov(ecx, GlobalObjectOperand());
2281 __ push(FieldOperand(ecx, GlobalObject::kGlobalReceiverOffset)); 2297 __ push(FieldOperand(ecx, GlobalObject::kGlobalReceiverOffset));
2282 EmitCallWithStub(expr, NO_CALL_FUNCTION_FLAGS); 2298 EmitCallWithStub(expr, NO_CALL_FUNCTION_FLAGS);
2283 } else { 2299 } else {
2284 { PreservePositionScope scope(masm()->positions_recorder()); 2300 { PreservePositionScope scope(masm()->positions_recorder());
2285 VisitForStackValue(prop->obj()); 2301 VisitForStackValue(prop->obj());
2286 } 2302 }
2287 EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET); 2303 EmitKeyedCallWithIC(expr, prop->key());
2288 } 2304 }
2289 } 2305 }
2290 } else { 2306 } else {
2291 { PreservePositionScope scope(masm()->positions_recorder()); 2307 { PreservePositionScope scope(masm()->positions_recorder());
2292 VisitForStackValue(fun); 2308 VisitForStackValue(fun);
2293 } 2309 }
2294 // Load global receiver object. 2310 // Load global receiver object.
2295 __ mov(ebx, GlobalObjectOperand()); 2311 __ mov(ebx, GlobalObjectOperand());
2296 __ push(FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset)); 2312 __ push(FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset));
2297 // Emit function call. 2313 // Emit function call.
(...skipping 1325 matching lines...)
3623 // Push the arguments ("left-to-right"). 3639 // Push the arguments ("left-to-right").
3624 int arg_count = args->length(); 3640 int arg_count = args->length();
3625 for (int i = 0; i < arg_count; i++) { 3641 for (int i = 0; i < arg_count; i++) {
3626 VisitForStackValue(args->at(i)); 3642 VisitForStackValue(args->at(i));
3627 } 3643 }
3628 3644
3629 if (expr->is_jsruntime()) { 3645 if (expr->is_jsruntime()) {
3630 // Call the JS runtime function via a call IC. 3646 // Call the JS runtime function via a call IC.
3631 __ Set(ecx, Immediate(expr->name())); 3647 __ Set(ecx, Immediate(expr->name()));
3632 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 3648 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
3649 RelocInfo::Mode mode = RelocInfo::CODE_TARGET;
3633 Handle<Code> ic = isolate()->stub_cache()->ComputeCallInitialize( 3650 Handle<Code> ic = isolate()->stub_cache()->ComputeCallInitialize(
3634 arg_count, in_loop); 3651 arg_count, in_loop, mode);
3635 EmitCallIC(ic, RelocInfo::CODE_TARGET, expr->id()); 3652 EmitCallIC(ic, mode, expr->id());
3636 // Restore context register. 3653 // Restore context register.
3637 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 3654 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
3638 } else { 3655 } else {
3639 // Call the C runtime function. 3656 // Call the C runtime function.
3640 __ CallRuntime(expr->function(), arg_count); 3657 __ CallRuntime(expr->function(), arg_count);
3641 } 3658 }
3642 context()->Plug(eax); 3659 context()->Plug(eax);
3643 } 3660 }
3644 3661
3645 3662
(...skipping 684 matching lines...)
4330 // And return. 4347 // And return.
4331 __ ret(0); 4348 __ ret(0);
4332 } 4349 }
4333 4350
4334 4351
4335 #undef __ 4352 #undef __
4336 4353
4337 } } // namespace v8::internal 4354 } } // namespace v8::internal
4338 4355
4339 #endif // V8_TARGET_ARCH_IA32 4356 #endif // V8_TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine