OLD | NEW |
---|---|
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...) Loading... | |
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...) Loading... | |
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...) Loading... | |
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...) Loading... | |
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...) Loading... | |
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...) Loading... | |
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...) Loading... | |
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 |
OLD | NEW |