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 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
140 SetFunctionPosition(function()); | 140 SetFunctionPosition(function()); |
141 Comment cmnt(masm_, "[ function compiled by full code generator"); | 141 Comment cmnt(masm_, "[ function compiled by full code generator"); |
142 | 142 |
143 #ifdef DEBUG | 143 #ifdef DEBUG |
144 if (strlen(FLAG_stop_at) > 0 && | 144 if (strlen(FLAG_stop_at) > 0 && |
145 info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { | 145 info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { |
146 __ stop("stop-at"); | 146 __ stop("stop-at"); |
147 } | 147 } |
148 #endif | 148 #endif |
149 | 149 |
| 150 // Strict mode functions need to replace the receiver with undefined |
| 151 // when called as functions (without an explicit receiver |
| 152 // object). t1 is zero for method calls and non-zero for function |
| 153 // calls. |
| 154 if (info->is_strict_mode()) { |
| 155 Label ok; |
| 156 __ Branch(&ok, eq, t1, Operand(zero_reg)); |
| 157 int receiver_offset = scope()->num_parameters() * kPointerSize; |
| 158 __ LoadRoot(a2, Heap::kUndefinedValueRootIndex); |
| 159 __ sw(a2, MemOperand(sp, receiver_offset)); |
| 160 __ bind(&ok); |
| 161 } |
| 162 |
150 int locals_count = scope()->num_stack_slots(); | 163 int locals_count = scope()->num_stack_slots(); |
151 | 164 |
152 __ Push(ra, fp, cp, a1); | 165 __ Push(ra, fp, cp, a1); |
153 if (locals_count > 0) { | 166 if (locals_count > 0) { |
154 // Load undefined value here, so the value is ready for the loop | 167 // Load undefined value here, so the value is ready for the loop |
155 // below. | 168 // below. |
156 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); | 169 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); |
157 } | 170 } |
158 // Adjust fp to point to caller's fp. | 171 // Adjust fp to point to caller's fp. |
159 __ Addu(fp, sp, Operand(2 * kPointerSize)); | 172 __ Addu(fp, sp, Operand(2 * kPointerSize)); |
(...skipping 1938 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2098 for (int i = 0; i < arg_count; i++) { | 2111 for (int i = 0; i < arg_count; i++) { |
2099 VisitForStackValue(args->at(i)); | 2112 VisitForStackValue(args->at(i)); |
2100 } | 2113 } |
2101 __ li(a2, Operand(name)); | 2114 __ li(a2, Operand(name)); |
2102 } | 2115 } |
2103 // Record source position for debugger. | 2116 // Record source position for debugger. |
2104 SetSourcePosition(expr->position()); | 2117 SetSourcePosition(expr->position()); |
2105 // Call the IC initialization code. | 2118 // Call the IC initialization code. |
2106 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 2119 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
2107 Handle<Code> ic = | 2120 Handle<Code> ic = |
2108 isolate()->stub_cache()->ComputeCallInitialize(arg_count, in_loop); | 2121 isolate()->stub_cache()->ComputeCallInitialize(arg_count, in_loop, mode); |
2109 EmitCallIC(ic, mode, expr->id()); | 2122 EmitCallIC(ic, mode, expr->id()); |
2110 RecordJSReturnSite(expr); | 2123 RecordJSReturnSite(expr); |
2111 // Restore context register. | 2124 // Restore context register. |
2112 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2125 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
2113 context()->Plug(v0); | 2126 context()->Plug(v0); |
2114 } | 2127 } |
2115 | 2128 |
2116 | 2129 |
2117 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, | 2130 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, |
2118 Expression* key, | 2131 Expression* key) { |
2119 RelocInfo::Mode mode) { | |
2120 // Load the key. | 2132 // Load the key. |
2121 VisitForAccumulatorValue(key); | 2133 VisitForAccumulatorValue(key); |
2122 | 2134 |
2123 // Swap the name of the function and the receiver on the stack to follow | 2135 // Swap the name of the function and the receiver on the stack to follow |
2124 // the calling convention for call ICs. | 2136 // the calling convention for call ICs. |
2125 __ pop(a1); | 2137 __ pop(a1); |
2126 __ push(v0); | 2138 __ push(v0); |
2127 __ push(a1); | 2139 __ push(a1); |
2128 | 2140 |
2129 // Code common for calls using the IC. | 2141 // Code common for calls using the IC. |
2130 ZoneList<Expression*>* args = expr->arguments(); | 2142 ZoneList<Expression*>* args = expr->arguments(); |
2131 int arg_count = args->length(); | 2143 int arg_count = args->length(); |
2132 { PreservePositionScope scope(masm()->positions_recorder()); | 2144 { PreservePositionScope scope(masm()->positions_recorder()); |
2133 for (int i = 0; i < arg_count; i++) { | 2145 for (int i = 0; i < arg_count; i++) { |
2134 VisitForStackValue(args->at(i)); | 2146 VisitForStackValue(args->at(i)); |
2135 } | 2147 } |
2136 } | 2148 } |
2137 // Record source position for debugger. | 2149 // Record source position for debugger. |
2138 SetSourcePosition(expr->position()); | 2150 SetSourcePosition(expr->position()); |
2139 // Call the IC initialization code. | 2151 // Call the IC initialization code. |
2140 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 2152 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
2141 Handle<Code> ic = | 2153 Handle<Code> ic = |
2142 isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count, in_loop); | 2154 isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count, in_loop); |
2143 __ lw(a2, MemOperand(sp, (arg_count + 1) * kPointerSize)); // Key. | 2155 __ lw(a2, MemOperand(sp, (arg_count + 1) * kPointerSize)); // Key. |
2144 EmitCallIC(ic, mode, expr->id()); | 2156 EmitCallIC(ic, RelocInfo::CODE_TARGET, expr->id()); |
2145 RecordJSReturnSite(expr); | 2157 RecordJSReturnSite(expr); |
2146 // Restore context register. | 2158 // Restore context register. |
2147 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2159 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
2148 context()->DropAndPlug(1, v0); // Drop the key still on the stack. | 2160 context()->DropAndPlug(1, v0); // Drop the key still on the stack. |
2149 } | 2161 } |
2150 | 2162 |
2151 | 2163 |
2152 void FullCodeGenerator::EmitCallWithStub(Call* expr, CallFunctionFlags flags) { | 2164 void FullCodeGenerator::EmitCallWithStub(Call* expr, CallFunctionFlags flags) { |
2153 // Code common for calls using the call stub. | 2165 // Code common for calls using the call stub. |
2154 ZoneList<Expression*>* args = expr->arguments(); | 2166 ZoneList<Expression*>* args = expr->arguments(); |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2248 } | 2260 } |
2249 | 2261 |
2250 // The runtime call returns a pair of values in v0 (function) and | 2262 // The runtime call returns a pair of values in v0 (function) and |
2251 // v1 (receiver). Touch up the stack with the right values. | 2263 // v1 (receiver). Touch up the stack with the right values. |
2252 __ sw(v0, MemOperand(sp, (arg_count + 1) * kPointerSize)); | 2264 __ sw(v0, MemOperand(sp, (arg_count + 1) * kPointerSize)); |
2253 __ sw(v1, MemOperand(sp, arg_count * kPointerSize)); | 2265 __ sw(v1, MemOperand(sp, arg_count * kPointerSize)); |
2254 } | 2266 } |
2255 // Record source position for debugger. | 2267 // Record source position for debugger. |
2256 SetSourcePosition(expr->position()); | 2268 SetSourcePosition(expr->position()); |
2257 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 2269 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
2258 CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); | 2270 CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_IMPLICIT); |
2259 __ CallStub(&stub); | 2271 __ CallStub(&stub); |
2260 RecordJSReturnSite(expr); | 2272 RecordJSReturnSite(expr); |
2261 // Restore context register. | 2273 // Restore context register. |
2262 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2274 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
2263 context()->DropAndPlug(1, v0); | 2275 context()->DropAndPlug(1, v0); |
2264 } else if (var != NULL && !var->is_this() && var->is_global()) { | 2276 } else if (var != NULL && !var->is_this() && var->is_global()) { |
2265 // Push global object as receiver for the call IC. | 2277 // Push global object as receiver for the call IC. |
2266 __ lw(a0, GlobalObjectOperand()); | 2278 __ lw(a0, GlobalObjectOperand()); |
2267 __ push(a0); | 2279 __ push(a0); |
2268 EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT); | 2280 EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT); |
(...skipping 29 matching lines...) Expand all Loading... |
2298 __ bind(&done); | 2310 __ bind(&done); |
2299 // Push function. | 2311 // Push function. |
2300 __ push(v0); | 2312 __ push(v0); |
2301 // Push global receiver. | 2313 // Push global receiver. |
2302 __ lw(a1, GlobalObjectOperand()); | 2314 __ lw(a1, GlobalObjectOperand()); |
2303 __ lw(a1, FieldMemOperand(a1, GlobalObject::kGlobalReceiverOffset)); | 2315 __ lw(a1, FieldMemOperand(a1, GlobalObject::kGlobalReceiverOffset)); |
2304 __ push(a1); | 2316 __ push(a1); |
2305 __ bind(&call); | 2317 __ bind(&call); |
2306 } | 2318 } |
2307 | 2319 |
2308 // The receiver is either the global receiver or a JSObject found by | 2320 // The receiver is either the global receiver or an object found |
2309 // LoadContextSlot. | 2321 // by LoadContextSlot. That object could be the hole if the |
2310 EmitCallWithStub(expr, NO_CALL_FUNCTION_FLAGS); | 2322 // receiver is implicitly the global object. |
| 2323 EmitCallWithStub(expr, RECEIVER_MIGHT_BE_IMPLICIT); |
2311 } else if (fun->AsProperty() != NULL) { | 2324 } else if (fun->AsProperty() != NULL) { |
2312 // Call to an object property. | 2325 // Call to an object property. |
2313 Property* prop = fun->AsProperty(); | 2326 Property* prop = fun->AsProperty(); |
2314 Literal* key = prop->key()->AsLiteral(); | 2327 Literal* key = prop->key()->AsLiteral(); |
2315 if (key != NULL && key->handle()->IsSymbol()) { | 2328 if (key != NULL && key->handle()->IsSymbol()) { |
2316 // Call to a named property, use call IC. | 2329 // Call to a named property, use call IC. |
2317 { PreservePositionScope scope(masm()->positions_recorder()); | 2330 { PreservePositionScope scope(masm()->positions_recorder()); |
2318 VisitForStackValue(prop->obj()); | 2331 VisitForStackValue(prop->obj()); |
2319 } | 2332 } |
2320 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); | 2333 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); |
(...skipping 20 matching lines...) Expand all Loading... |
2341 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); | 2354 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); |
2342 EmitCallIC(ic, RelocInfo::CODE_TARGET, GetPropertyId(prop)); | 2355 EmitCallIC(ic, RelocInfo::CODE_TARGET, GetPropertyId(prop)); |
2343 __ lw(a1, GlobalObjectOperand()); | 2356 __ lw(a1, GlobalObjectOperand()); |
2344 __ lw(a1, FieldMemOperand(a1, GlobalObject::kGlobalReceiverOffset)); | 2357 __ lw(a1, FieldMemOperand(a1, GlobalObject::kGlobalReceiverOffset)); |
2345 __ Push(v0, a1); // Function, receiver. | 2358 __ Push(v0, a1); // Function, receiver. |
2346 EmitCallWithStub(expr, NO_CALL_FUNCTION_FLAGS); | 2359 EmitCallWithStub(expr, NO_CALL_FUNCTION_FLAGS); |
2347 } else { | 2360 } else { |
2348 { PreservePositionScope scope(masm()->positions_recorder()); | 2361 { PreservePositionScope scope(masm()->positions_recorder()); |
2349 VisitForStackValue(prop->obj()); | 2362 VisitForStackValue(prop->obj()); |
2350 } | 2363 } |
2351 EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET); | 2364 EmitKeyedCallWithIC(expr, prop->key()); |
2352 } | 2365 } |
2353 } | 2366 } |
2354 } else { | 2367 } else { |
2355 { PreservePositionScope scope(masm()->positions_recorder()); | 2368 { PreservePositionScope scope(masm()->positions_recorder()); |
2356 VisitForStackValue(fun); | 2369 VisitForStackValue(fun); |
2357 } | 2370 } |
2358 // Load global receiver object. | 2371 // Load global receiver object. |
2359 __ lw(a1, GlobalObjectOperand()); | 2372 __ lw(a1, GlobalObjectOperand()); |
2360 __ lw(a1, FieldMemOperand(a1, GlobalObject::kGlobalReceiverOffset)); | 2373 __ lw(a1, FieldMemOperand(a1, GlobalObject::kGlobalReceiverOffset)); |
2361 __ push(a1); | 2374 __ push(a1); |
(...skipping 1294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3656 | 3669 |
3657 // Push the arguments ("left-to-right"). | 3670 // Push the arguments ("left-to-right"). |
3658 int arg_count = args->length(); | 3671 int arg_count = args->length(); |
3659 for (int i = 0; i < arg_count; i++) { | 3672 for (int i = 0; i < arg_count; i++) { |
3660 VisitForStackValue(args->at(i)); | 3673 VisitForStackValue(args->at(i)); |
3661 } | 3674 } |
3662 | 3675 |
3663 if (expr->is_jsruntime()) { | 3676 if (expr->is_jsruntime()) { |
3664 // Call the JS runtime function. | 3677 // Call the JS runtime function. |
3665 __ li(a2, Operand(expr->name())); | 3678 __ li(a2, Operand(expr->name())); |
| 3679 RelocInfo::Mode mode = RelocInfo::CODE_TARGET; |
3666 Handle<Code> ic = | 3680 Handle<Code> ic = |
3667 isolate()->stub_cache()->ComputeCallInitialize(arg_count, NOT_IN_LOOP); | 3681 isolate()->stub_cache()->ComputeCallInitialize(arg_count, |
3668 EmitCallIC(ic, RelocInfo::CODE_TARGET, expr->id()); | 3682 NOT_IN_LOOP, |
| 3683 mode); |
| 3684 EmitCallIC(ic, mode, expr->id()); |
3669 // Restore context register. | 3685 // Restore context register. |
3670 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 3686 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
3671 } else { | 3687 } else { |
3672 // Call the C runtime function. | 3688 // Call the C runtime function. |
3673 __ CallRuntime(expr->function(), arg_count); | 3689 __ CallRuntime(expr->function(), arg_count); |
3674 } | 3690 } |
3675 context()->Plug(v0); | 3691 context()->Plug(v0); |
3676 } | 3692 } |
3677 | 3693 |
3678 | 3694 |
(...skipping 684 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4363 __ Addu(at, a1, Operand(masm_->CodeObject())); | 4379 __ Addu(at, a1, Operand(masm_->CodeObject())); |
4364 __ Jump(at); | 4380 __ Jump(at); |
4365 } | 4381 } |
4366 | 4382 |
4367 | 4383 |
4368 #undef __ | 4384 #undef __ |
4369 | 4385 |
4370 } } // namespace v8::internal | 4386 } } // namespace v8::internal |
4371 | 4387 |
4372 #endif // V8_TARGET_ARCH_MIPS | 4388 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |