| OLD | NEW |
| 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 1985 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1996 context()->Plug(eax); | 1996 context()->Plug(eax); |
| 1997 } | 1997 } |
| 1998 | 1998 |
| 1999 | 1999 |
| 2000 void FullCodeGenerator::EmitCallWithIC(Call* expr, | 2000 void FullCodeGenerator::EmitCallWithIC(Call* expr, |
| 2001 Handle<Object> name, | 2001 Handle<Object> name, |
| 2002 RelocInfo::Mode mode) { | 2002 RelocInfo::Mode mode) { |
| 2003 // Code common for calls using the IC. | 2003 // Code common for calls using the IC. |
| 2004 ZoneList<Expression*>* args = expr->arguments(); | 2004 ZoneList<Expression*>* args = expr->arguments(); |
| 2005 int arg_count = args->length(); | 2005 int arg_count = args->length(); |
| 2006 { PreserveStatementPositionScope scope(masm()->positions_recorder()); | 2006 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2007 for (int i = 0; i < arg_count; i++) { | 2007 for (int i = 0; i < arg_count; i++) { |
| 2008 VisitForStackValue(args->at(i)); | 2008 VisitForStackValue(args->at(i)); |
| 2009 } | 2009 } |
| 2010 __ Set(ecx, Immediate(name)); | 2010 __ Set(ecx, Immediate(name)); |
| 2011 } | 2011 } |
| 2012 // Record source position of the IC call. | 2012 // Record source position of the IC call. |
| 2013 SetSourcePosition(expr->position(), FORCED_POSITION); | 2013 SetSourcePosition(expr->position()); |
| 2014 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 2014 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
| 2015 Handle<Code> ic = StubCache::ComputeCallInitialize(arg_count, in_loop); | 2015 Handle<Code> ic = StubCache::ComputeCallInitialize(arg_count, in_loop); |
| 2016 EmitCallIC(ic, mode); | 2016 EmitCallIC(ic, mode); |
| 2017 // Restore context register. | 2017 // Restore context register. |
| 2018 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 2018 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 2019 context()->Plug(eax); | 2019 context()->Plug(eax); |
| 2020 } | 2020 } |
| 2021 | 2021 |
| 2022 | 2022 |
| 2023 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, | 2023 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, |
| 2024 Expression* key, | 2024 Expression* key, |
| 2025 RelocInfo::Mode mode) { | 2025 RelocInfo::Mode mode) { |
| 2026 // Load the key. | 2026 // Load the key. |
| 2027 VisitForAccumulatorValue(key); | 2027 VisitForAccumulatorValue(key); |
| 2028 | 2028 |
| 2029 // Swap the name of the function and the receiver on the stack to follow | 2029 // Swap the name of the function and the receiver on the stack to follow |
| 2030 // the calling convention for call ICs. | 2030 // the calling convention for call ICs. |
| 2031 __ pop(ecx); | 2031 __ pop(ecx); |
| 2032 __ push(eax); | 2032 __ push(eax); |
| 2033 __ push(ecx); | 2033 __ push(ecx); |
| 2034 | 2034 |
| 2035 // Load the arguments. | 2035 // Load the arguments. |
| 2036 ZoneList<Expression*>* args = expr->arguments(); | 2036 ZoneList<Expression*>* args = expr->arguments(); |
| 2037 int arg_count = args->length(); | 2037 int arg_count = args->length(); |
| 2038 { PreserveStatementPositionScope scope(masm()->positions_recorder()); | 2038 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2039 for (int i = 0; i < arg_count; i++) { | 2039 for (int i = 0; i < arg_count; i++) { |
| 2040 VisitForStackValue(args->at(i)); | 2040 VisitForStackValue(args->at(i)); |
| 2041 } | 2041 } |
| 2042 } | 2042 } |
| 2043 // Record source position of the IC call. | 2043 // Record source position of the IC call. |
| 2044 SetSourcePosition(expr->position(), FORCED_POSITION); | 2044 SetSourcePosition(expr->position()); |
| 2045 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 2045 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
| 2046 Handle<Code> ic = StubCache::ComputeKeyedCallInitialize(arg_count, in_loop); | 2046 Handle<Code> ic = StubCache::ComputeKeyedCallInitialize(arg_count, in_loop); |
| 2047 __ mov(ecx, Operand(esp, (arg_count + 1) * kPointerSize)); // Key. | 2047 __ mov(ecx, Operand(esp, (arg_count + 1) * kPointerSize)); // Key. |
| 2048 EmitCallIC(ic, mode); | 2048 EmitCallIC(ic, mode); |
| 2049 // Restore context register. | 2049 // Restore context register. |
| 2050 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 2050 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 2051 context()->DropAndPlug(1, eax); // Drop the key still on the stack. | 2051 context()->DropAndPlug(1, eax); // Drop the key still on the stack. |
| 2052 } | 2052 } |
| 2053 | 2053 |
| 2054 | 2054 |
| 2055 void FullCodeGenerator::EmitCallWithStub(Call* expr) { | 2055 void FullCodeGenerator::EmitCallWithStub(Call* expr) { |
| 2056 // Code common for calls using the call stub. | 2056 // Code common for calls using the call stub. |
| 2057 ZoneList<Expression*>* args = expr->arguments(); | 2057 ZoneList<Expression*>* args = expr->arguments(); |
| 2058 int arg_count = args->length(); | 2058 int arg_count = args->length(); |
| 2059 { PreserveStatementPositionScope scope(masm()->positions_recorder()); | 2059 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2060 for (int i = 0; i < arg_count; i++) { | 2060 for (int i = 0; i < arg_count; i++) { |
| 2061 VisitForStackValue(args->at(i)); | 2061 VisitForStackValue(args->at(i)); |
| 2062 } | 2062 } |
| 2063 } | 2063 } |
| 2064 // Record source position for debugger. | 2064 // Record source position for debugger. |
| 2065 SetSourcePosition(expr->position(), FORCED_POSITION); | 2065 SetSourcePosition(expr->position()); |
| 2066 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 2066 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
| 2067 CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); | 2067 CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); |
| 2068 __ CallStub(&stub); | 2068 __ CallStub(&stub); |
| 2069 // Restore context register. | 2069 // Restore context register. |
| 2070 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 2070 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 2071 context()->DropAndPlug(1, eax); | 2071 context()->DropAndPlug(1, eax); |
| 2072 } | 2072 } |
| 2073 | 2073 |
| 2074 | 2074 |
| 2075 void FullCodeGenerator::VisitCall(Call* expr) { | 2075 void FullCodeGenerator::VisitCall(Call* expr) { |
| 2076 Comment cmnt(masm_, "[ Call"); | 2076 Comment cmnt(masm_, "[ Call"); |
| 2077 Expression* fun = expr->expression(); | 2077 Expression* fun = expr->expression(); |
| 2078 Variable* var = fun->AsVariableProxy()->AsVariable(); | 2078 Variable* var = fun->AsVariableProxy()->AsVariable(); |
| 2079 | 2079 |
| 2080 if (var != NULL && var->is_possibly_eval()) { | 2080 if (var != NULL && var->is_possibly_eval()) { |
| 2081 // In a call to eval, we first call %ResolvePossiblyDirectEval to | 2081 // In a call to eval, we first call %ResolvePossiblyDirectEval to |
| 2082 // resolve the function we need to call and the receiver of the | 2082 // resolve the function we need to call and the receiver of the |
| 2083 // call. Then we call the resolved function using the given | 2083 // call. Then we call the resolved function using the given |
| 2084 // arguments. | 2084 // arguments. |
| 2085 ZoneList<Expression*>* args = expr->arguments(); | 2085 ZoneList<Expression*>* args = expr->arguments(); |
| 2086 int arg_count = args->length(); | 2086 int arg_count = args->length(); |
| 2087 { PreserveStatementPositionScope pos_scope(masm()->positions_recorder()); | 2087 { PreservePositionScope pos_scope(masm()->positions_recorder()); |
| 2088 VisitForStackValue(fun); | 2088 VisitForStackValue(fun); |
| 2089 // Reserved receiver slot. | 2089 // Reserved receiver slot. |
| 2090 __ push(Immediate(Factory::undefined_value())); | 2090 __ push(Immediate(Factory::undefined_value())); |
| 2091 | 2091 |
| 2092 // Push the arguments. | 2092 // Push the arguments. |
| 2093 for (int i = 0; i < arg_count; i++) { | 2093 for (int i = 0; i < arg_count; i++) { |
| 2094 VisitForStackValue(args->at(i)); | 2094 VisitForStackValue(args->at(i)); |
| 2095 } | 2095 } |
| 2096 | 2096 |
| 2097 // Push copy of the function - found below the arguments. | 2097 // Push copy of the function - found below the arguments. |
| 2098 __ push(Operand(esp, (arg_count + 1) * kPointerSize)); | 2098 __ push(Operand(esp, (arg_count + 1) * kPointerSize)); |
| 2099 | 2099 |
| 2100 // Push copy of the first argument or undefined if it doesn't exist. | 2100 // Push copy of the first argument or undefined if it doesn't exist. |
| 2101 if (arg_count > 0) { | 2101 if (arg_count > 0) { |
| 2102 __ push(Operand(esp, arg_count * kPointerSize)); | 2102 __ push(Operand(esp, arg_count * kPointerSize)); |
| 2103 } else { | 2103 } else { |
| 2104 __ push(Immediate(Factory::undefined_value())); | 2104 __ push(Immediate(Factory::undefined_value())); |
| 2105 } | 2105 } |
| 2106 | 2106 |
| 2107 // Push the receiver of the enclosing function and do runtime call. | 2107 // Push the receiver of the enclosing function and do runtime call. |
| 2108 __ push(Operand(ebp, (2 + scope()->num_parameters()) * kPointerSize)); | 2108 __ push(Operand(ebp, (2 + scope()->num_parameters()) * kPointerSize)); |
| 2109 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 3); | 2109 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 3); |
| 2110 | 2110 |
| 2111 // The runtime call returns a pair of values in eax (function) and | 2111 // The runtime call returns a pair of values in eax (function) and |
| 2112 // edx (receiver). Touch up the stack with the right values. | 2112 // edx (receiver). Touch up the stack with the right values. |
| 2113 __ mov(Operand(esp, (arg_count + 0) * kPointerSize), edx); | 2113 __ mov(Operand(esp, (arg_count + 0) * kPointerSize), edx); |
| 2114 __ mov(Operand(esp, (arg_count + 1) * kPointerSize), eax); | 2114 __ mov(Operand(esp, (arg_count + 1) * kPointerSize), eax); |
| 2115 } | 2115 } |
| 2116 // Record source position for debugger. | 2116 // Record source position for debugger. |
| 2117 SetSourcePosition(expr->position(), FORCED_POSITION); | 2117 SetSourcePosition(expr->position()); |
| 2118 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 2118 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
| 2119 CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); | 2119 CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); |
| 2120 __ CallStub(&stub); | 2120 __ CallStub(&stub); |
| 2121 // Restore context register. | 2121 // Restore context register. |
| 2122 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 2122 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 2123 context()->DropAndPlug(1, eax); | 2123 context()->DropAndPlug(1, eax); |
| 2124 } else if (var != NULL && !var->is_this() && var->is_global()) { | 2124 } else if (var != NULL && !var->is_this() && var->is_global()) { |
| 2125 // Push global object as receiver for the call IC. | 2125 // Push global object as receiver for the call IC. |
| 2126 __ push(GlobalObjectOperand()); | 2126 __ push(GlobalObjectOperand()); |
| 2127 EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT); | 2127 EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT); |
| 2128 } else if (var != NULL && var->AsSlot() != NULL && | 2128 } else if (var != NULL && var->AsSlot() != NULL && |
| 2129 var->AsSlot()->type() == Slot::LOOKUP) { | 2129 var->AsSlot()->type() == Slot::LOOKUP) { |
| 2130 // Call to a lookup slot (dynamically introduced variable). | 2130 // Call to a lookup slot (dynamically introduced variable). |
| 2131 Label slow, done; | 2131 Label slow, done; |
| 2132 | 2132 |
| 2133 { PreserveStatementPositionScope scope(masm()->positions_recorder()); | 2133 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2134 // Generate code for loading from variables potentially shadowed | 2134 // Generate code for loading from variables potentially shadowed |
| 2135 // by eval-introduced variables. | 2135 // by eval-introduced variables. |
| 2136 EmitDynamicLoadFromSlotFastCase(var->AsSlot(), | 2136 EmitDynamicLoadFromSlotFastCase(var->AsSlot(), |
| 2137 NOT_INSIDE_TYPEOF, | 2137 NOT_INSIDE_TYPEOF, |
| 2138 &slow, | 2138 &slow, |
| 2139 &done); | 2139 &done); |
| 2140 } | 2140 } |
| 2141 | 2141 |
| 2142 __ bind(&slow); | 2142 __ bind(&slow); |
| 2143 // Call the runtime to find the function to call (returned in eax) | 2143 // Call the runtime to find the function to call (returned in eax) |
| (...skipping 25 matching lines...) Expand all Loading... |
| 2169 Property* prop = fun->AsProperty(); | 2169 Property* prop = fun->AsProperty(); |
| 2170 Literal* key = prop->key()->AsLiteral(); | 2170 Literal* key = prop->key()->AsLiteral(); |
| 2171 if (key != NULL && key->handle()->IsSymbol()) { | 2171 if (key != NULL && key->handle()->IsSymbol()) { |
| 2172 // Call to a named property, use call IC. | 2172 // Call to a named property, use call IC. |
| 2173 VisitForStackValue(prop->obj()); | 2173 VisitForStackValue(prop->obj()); |
| 2174 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); | 2174 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); |
| 2175 } else { | 2175 } else { |
| 2176 // Call to a keyed property. | 2176 // Call to a keyed property. |
| 2177 // For a synthetic property use keyed load IC followed by function call, | 2177 // For a synthetic property use keyed load IC followed by function call, |
| 2178 // for a regular property use keyed EmitCallIC. | 2178 // for a regular property use keyed EmitCallIC. |
| 2179 { PreserveStatementPositionScope scope(masm()->positions_recorder()); | 2179 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2180 VisitForStackValue(prop->obj()); | 2180 VisitForStackValue(prop->obj()); |
| 2181 } | 2181 } |
| 2182 if (prop->is_synthetic()) { | 2182 if (prop->is_synthetic()) { |
| 2183 { PreserveStatementPositionScope scope(masm()->positions_recorder()); | 2183 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2184 VisitForAccumulatorValue(prop->key()); | 2184 VisitForAccumulatorValue(prop->key()); |
| 2185 } | 2185 } |
| 2186 // Record source code position for IC call. | 2186 // Record source code position for IC call. |
| 2187 SetSourcePosition(prop->position(), FORCED_POSITION); | 2187 SetSourcePosition(prop->position()); |
| 2188 __ pop(edx); // We do not need to keep the receiver. | 2188 __ pop(edx); // We do not need to keep the receiver. |
| 2189 | 2189 |
| 2190 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 2190 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
| 2191 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 2191 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
| 2192 // Push result (function). | 2192 // Push result (function). |
| 2193 __ push(eax); | 2193 __ push(eax); |
| 2194 // Push Global receiver. | 2194 // Push Global receiver. |
| 2195 __ mov(ecx, GlobalObjectOperand()); | 2195 __ mov(ecx, GlobalObjectOperand()); |
| 2196 __ push(FieldOperand(ecx, GlobalObject::kGlobalReceiverOffset)); | 2196 __ push(FieldOperand(ecx, GlobalObject::kGlobalReceiverOffset)); |
| 2197 EmitCallWithStub(expr); | 2197 EmitCallWithStub(expr); |
| 2198 } else { | 2198 } else { |
| 2199 EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET); | 2199 EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET); |
| 2200 } | 2200 } |
| 2201 } | 2201 } |
| 2202 } else { | 2202 } else { |
| 2203 // Call to some other expression. If the expression is an anonymous | 2203 // Call to some other expression. If the expression is an anonymous |
| 2204 // function literal not called in a loop, mark it as one that should | 2204 // function literal not called in a loop, mark it as one that should |
| 2205 // also use the full code generator. | 2205 // also use the full code generator. |
| 2206 FunctionLiteral* lit = fun->AsFunctionLiteral(); | 2206 FunctionLiteral* lit = fun->AsFunctionLiteral(); |
| 2207 if (lit != NULL && | 2207 if (lit != NULL && |
| 2208 lit->name()->Equals(Heap::empty_string()) && | 2208 lit->name()->Equals(Heap::empty_string()) && |
| 2209 loop_depth() == 0) { | 2209 loop_depth() == 0) { |
| 2210 lit->set_try_full_codegen(true); | 2210 lit->set_try_full_codegen(true); |
| 2211 } | 2211 } |
| 2212 { PreserveStatementPositionScope scope(masm()->positions_recorder()); | 2212 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2213 VisitForStackValue(fun); | 2213 VisitForStackValue(fun); |
| 2214 } | 2214 } |
| 2215 // Load global receiver object. | 2215 // Load global receiver object. |
| 2216 __ mov(ebx, GlobalObjectOperand()); | 2216 __ mov(ebx, GlobalObjectOperand()); |
| 2217 __ push(FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset)); | 2217 __ push(FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset)); |
| 2218 // Emit function call. | 2218 // Emit function call. |
| 2219 EmitCallWithStub(expr); | 2219 EmitCallWithStub(expr); |
| 2220 } | 2220 } |
| 2221 } | 2221 } |
| 2222 | 2222 |
| (...skipping 1725 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3948 // And return. | 3948 // And return. |
| 3949 __ ret(0); | 3949 __ ret(0); |
| 3950 } | 3950 } |
| 3951 | 3951 |
| 3952 | 3952 |
| 3953 #undef __ | 3953 #undef __ |
| 3954 | 3954 |
| 3955 } } // namespace v8::internal | 3955 } } // namespace v8::internal |
| 3956 | 3956 |
| 3957 #endif // V8_TARGET_ARCH_IA32 | 3957 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |