| 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 2043 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2054 } else { | 2054 } else { |
| 2055 VisitForStackValue(expr->obj()); | 2055 VisitForStackValue(expr->obj()); |
| 2056 VisitForAccumulatorValue(expr->key()); | 2056 VisitForAccumulatorValue(expr->key()); |
| 2057 __ pop(edx); | 2057 __ pop(edx); |
| 2058 EmitKeyedPropertyLoad(expr); | 2058 EmitKeyedPropertyLoad(expr); |
| 2059 context()->Plug(eax); | 2059 context()->Plug(eax); |
| 2060 } | 2060 } |
| 2061 } | 2061 } |
| 2062 | 2062 |
| 2063 | 2063 |
| 2064 void FullCodeGenerator::EmitCallWithIC(Call* expr, | 2064 void FullCodeGenerator::EmitCallWithIC(CallBase* expr, |
| 2065 Handle<Object> name, | 2065 Handle<Object> name, |
| 2066 RelocInfo::Mode mode) { | 2066 RelocInfo::Mode mode) { |
| 2067 // Code common for calls using the IC. | 2067 // Code common for calls using the IC. |
| 2068 ZoneList<Expression*>* args = expr->arguments(); | 2068 ZoneList<Expression*>* args = expr->arguments(); |
| 2069 int arg_count = args->length(); | 2069 int arg_count = args->length(); |
| 2070 { PreservePositionScope scope(masm()->positions_recorder()); | 2070 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2071 for (int i = 0; i < arg_count; i++) { | 2071 for (int i = 0; i < arg_count; i++) { |
| 2072 VisitForStackValue(args->at(i)); | 2072 VisitForStackValue(args->at(i)); |
| 2073 } | 2073 } |
| 2074 __ Set(ecx, Immediate(name)); | 2074 __ Set(ecx, Immediate(name)); |
| 2075 } | 2075 } |
| 2076 // Record source position of the IC call. | 2076 // Record source position of the IC call. |
| 2077 SetSourcePosition(expr->position()); | 2077 SetSourcePosition(expr->position()); |
| 2078 Handle<Code> ic = | 2078 Handle<Code> ic = |
| 2079 isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode); | 2079 isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode); |
| 2080 __ call(ic, mode, expr->id()); | 2080 __ call(ic, mode, expr->id()); |
| 2081 RecordJSReturnSite(expr); | 2081 RecordJSReturnSite(expr); |
| 2082 // Restore context register. | 2082 // Restore context register. |
| 2083 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 2083 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 2084 context()->Plug(eax); | 2084 context()->Plug(eax); |
| 2085 } | 2085 } |
| 2086 | 2086 |
| 2087 | 2087 |
| 2088 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, | 2088 void FullCodeGenerator::EmitKeyedCallWithIC(CallBase* expr, |
| 2089 Expression* key) { | 2089 Expression* key, |
| 2090 RelocInfo::Mode mode) { |
| 2090 // Load the key. | 2091 // Load the key. |
| 2091 VisitForAccumulatorValue(key); | 2092 VisitForAccumulatorValue(key); |
| 2092 | 2093 |
| 2093 // Swap the name of the function and the receiver on the stack to follow | 2094 // Swap the name of the function and the receiver on the stack to follow |
| 2094 // the calling convention for call ICs. | 2095 // the calling convention for call ICs. |
| 2095 __ pop(ecx); | 2096 __ pop(ecx); |
| 2096 __ push(eax); | 2097 __ push(eax); |
| 2097 __ push(ecx); | 2098 __ push(ecx); |
| 2098 | 2099 |
| 2099 // Load the arguments. | 2100 // Load the arguments. |
| 2100 ZoneList<Expression*>* args = expr->arguments(); | 2101 ZoneList<Expression*>* args = expr->arguments(); |
| 2101 int arg_count = args->length(); | 2102 int arg_count = args->length(); |
| 2102 { PreservePositionScope scope(masm()->positions_recorder()); | 2103 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2103 for (int i = 0; i < arg_count; i++) { | 2104 for (int i = 0; i < arg_count; i++) { |
| 2104 VisitForStackValue(args->at(i)); | 2105 VisitForStackValue(args->at(i)); |
| 2105 } | 2106 } |
| 2106 } | 2107 } |
| 2107 // Record source position of the IC call. | 2108 // Record source position of the IC call. |
| 2108 SetSourcePosition(expr->position()); | 2109 SetSourcePosition(expr->position()); |
| 2109 Handle<Code> ic = | 2110 Handle<Code> ic = |
| 2110 isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count); | 2111 isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count, mode); |
| 2111 __ mov(ecx, Operand(esp, (arg_count + 1) * kPointerSize)); // Key. | 2112 __ mov(ecx, Operand(esp, (arg_count + 1) * kPointerSize)); // Key. |
| 2112 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); | 2113 __ call(ic, mode, expr->id()); |
| 2113 RecordJSReturnSite(expr); | 2114 RecordJSReturnSite(expr); |
| 2114 // Restore context register. | 2115 // Restore context register. |
| 2115 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 2116 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 2116 context()->DropAndPlug(1, eax); // Drop the key still on the stack. | 2117 context()->DropAndPlug(1, eax); // Drop the key still on the stack. |
| 2117 } | 2118 } |
| 2118 | 2119 |
| 2119 | 2120 |
| 2120 void FullCodeGenerator::EmitCallWithStub(Call* expr, CallFunctionFlags flags) { | 2121 void FullCodeGenerator::EmitCallWithStub(Call* expr, CallFunctionFlags flags) { |
| 2121 // Code common for calls using the call stub. | 2122 // Code common for calls using the call stub. |
| 2122 ZoneList<Expression*>* args = expr->arguments(); | 2123 ZoneList<Expression*>* args = expr->arguments(); |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2270 | 2271 |
| 2271 } else if (property != NULL) { | 2272 } else if (property != NULL) { |
| 2272 { PreservePositionScope scope(masm()->positions_recorder()); | 2273 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2273 VisitForStackValue(property->obj()); | 2274 VisitForStackValue(property->obj()); |
| 2274 } | 2275 } |
| 2275 if (property->key()->IsPropertyName()) { | 2276 if (property->key()->IsPropertyName()) { |
| 2276 EmitCallWithIC(expr, | 2277 EmitCallWithIC(expr, |
| 2277 property->key()->AsLiteral()->handle(), | 2278 property->key()->AsLiteral()->handle(), |
| 2278 RelocInfo::CODE_TARGET); | 2279 RelocInfo::CODE_TARGET); |
| 2279 } else { | 2280 } else { |
| 2280 EmitKeyedCallWithIC(expr, property->key()); | 2281 EmitKeyedCallWithIC(expr, property->key(), RelocInfo::CODE_TARGET); |
| 2281 } | 2282 } |
| 2282 | 2283 |
| 2283 } else { | 2284 } else { |
| 2284 // Call to an arbitrary expression not handled specially above. | 2285 // Call to an arbitrary expression not handled specially above. |
| 2285 { PreservePositionScope scope(masm()->positions_recorder()); | 2286 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2286 VisitForStackValue(callee); | 2287 VisitForStackValue(callee); |
| 2287 } | 2288 } |
| 2288 // Load global receiver object. | 2289 // Load global receiver object. |
| 2289 __ mov(ebx, GlobalObjectOperand()); | 2290 __ mov(ebx, GlobalObjectOperand()); |
| 2290 __ push(FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset)); | 2291 __ push(FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset)); |
| 2291 // Emit function call. | 2292 // Emit function call. |
| 2292 EmitCallWithStub(expr, NO_CALL_FUNCTION_FLAGS); | 2293 EmitCallWithStub(expr, NO_CALL_FUNCTION_FLAGS); |
| 2293 } | 2294 } |
| 2294 | 2295 |
| 2295 #ifdef DEBUG | 2296 #ifdef DEBUG |
| 2296 // RecordJSReturnSite should have been called. | 2297 // RecordJSReturnSite should have been called. |
| 2297 ASSERT(expr->return_is_recorded_); | 2298 ASSERT(expr->return_is_recorded_); |
| 2298 #endif | 2299 #endif |
| 2299 } | 2300 } |
| 2300 | 2301 |
| 2301 | 2302 |
| 2302 void FullCodeGenerator::VisitCallNew(CallNew* expr) { | 2303 void FullCodeGenerator::VisitCallNew(CallNew* expr) { |
| 2304 #ifdef DEBUG |
| 2305 // We want to verify that RecordJSReturnSite gets called on all paths |
| 2306 // through this function. Avoid early returns. |
| 2307 expr->return_is_recorded_ = false; |
| 2308 #endif |
| 2309 |
| 2303 Comment cmnt(masm_, "[ CallNew"); | 2310 Comment cmnt(masm_, "[ CallNew"); |
| 2311 Expression* callee = expr->expression(); |
| 2312 Property* property = callee->AsProperty(); |
| 2313 |
| 2304 // According to ECMA-262, section 11.2.2, page 44, the function | 2314 // According to ECMA-262, section 11.2.2, page 44, the function |
| 2305 // expression in new calls must be evaluated before the | 2315 // expression in new calls must be evaluated before the |
| 2306 // arguments. | 2316 // arguments. |
| 2307 | 2317 |
| 2308 // Push constructor on the stack. If it's not a function it's used as | 2318 if (property != NULL) { |
| 2309 // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is | 2319 // TODO(mstarzinger): This bailout is only needed because we do not use |
| 2310 // ignored. | 2320 // type feedback in Crankshaft yet. |
| 2311 VisitForStackValue(expr->expression()); | 2321 PrepareForBailout(callee, TOS_REG); |
| 2322 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2323 VisitForStackValue(property->obj()); |
| 2324 } |
| 2325 if (property->key()->IsPropertyName()) { |
| 2326 EmitCallWithIC(expr, |
| 2327 property->key()->AsLiteral()->handle(), |
| 2328 RelocInfo::CONSTRUCT_CALL); |
| 2329 } else { |
| 2330 EmitKeyedCallWithIC(expr, property->key(), RelocInfo::CONSTRUCT_CALL); |
| 2331 } |
| 2312 | 2332 |
| 2313 // Push the arguments ("left-to-right") on the stack. | 2333 } else { |
| 2314 ZoneList<Expression*>* args = expr->arguments(); | 2334 // Push constructor on the stack. If it's not a function it's used as |
| 2315 int arg_count = args->length(); | 2335 // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is |
| 2316 for (int i = 0; i < arg_count; i++) { | 2336 // ignored. |
| 2317 VisitForStackValue(args->at(i)); | 2337 VisitForStackValue(callee); |
| 2338 |
| 2339 // Push the arguments ("left-to-right") on the stack. |
| 2340 ZoneList<Expression*>* args = expr->arguments(); |
| 2341 int arg_count = args->length(); |
| 2342 for (int i = 0; i < arg_count; i++) { |
| 2343 VisitForStackValue(args->at(i)); |
| 2344 } |
| 2345 |
| 2346 // Call the construct call builtin that handles allocation and |
| 2347 // constructor invocation. |
| 2348 SetSourcePosition(expr->position()); |
| 2349 |
| 2350 // Load function and argument count into edi and eax. |
| 2351 __ SafeSet(eax, Immediate(arg_count)); |
| 2352 __ mov(edi, Operand(esp, arg_count * kPointerSize)); |
| 2353 |
| 2354 Handle<Code> construct_builtin = isolate()->builtins()->JSConstructCall(); |
| 2355 __ call(construct_builtin, RelocInfo::CONSTRUCT_CALL); |
| 2356 context()->Plug(eax); |
| 2318 } | 2357 } |
| 2319 | |
| 2320 // Call the construct call builtin that handles allocation and | |
| 2321 // constructor invocation. | |
| 2322 SetSourcePosition(expr->position()); | |
| 2323 | |
| 2324 // Load function and argument count into edi and eax. | |
| 2325 __ SafeSet(eax, Immediate(arg_count)); | |
| 2326 __ mov(edi, Operand(esp, arg_count * kPointerSize)); | |
| 2327 | |
| 2328 Handle<Code> construct_builtin = | |
| 2329 isolate()->builtins()->JSConstructCall(); | |
| 2330 __ call(construct_builtin, RelocInfo::CONSTRUCT_CALL); | |
| 2331 context()->Plug(eax); | |
| 2332 } | 2358 } |
| 2333 | 2359 |
| 2334 | 2360 |
| 2335 void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) { | 2361 void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) { |
| 2336 ZoneList<Expression*>* args = expr->arguments(); | 2362 ZoneList<Expression*>* args = expr->arguments(); |
| 2337 ASSERT(args->length() == 1); | 2363 ASSERT(args->length() == 1); |
| 2338 | 2364 |
| 2339 VisitForAccumulatorValue(args->at(0)); | 2365 VisitForAccumulatorValue(args->at(0)); |
| 2340 | 2366 |
| 2341 Label materialize_true, materialize_false; | 2367 Label materialize_true, materialize_false; |
| (...skipping 2038 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4380 *context_length = 0; | 4406 *context_length = 0; |
| 4381 return previous_; | 4407 return previous_; |
| 4382 } | 4408 } |
| 4383 | 4409 |
| 4384 | 4410 |
| 4385 #undef __ | 4411 #undef __ |
| 4386 | 4412 |
| 4387 } } // namespace v8::internal | 4413 } } // namespace v8::internal |
| 4388 | 4414 |
| 4389 #endif // V8_TARGET_ARCH_IA32 | 4415 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |