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 |