Chromium Code Reviews| 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...) Expand 10 before | Expand all | Expand 10 after 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...) Expand 10 before | Expand all | Expand 10 after 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...) Expand 10 before | Expand all | Expand 10 after 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...) Expand all 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...) Expand all 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...) Expand 10 before | Expand all | Expand 10 after 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...) Expand 10 before | Expand all | Expand 10 after 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 |