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