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 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
132 SetFunctionPosition(function()); | 132 SetFunctionPosition(function()); |
133 Comment cmnt(masm_, "[ function compiled by full code generator"); | 133 Comment cmnt(masm_, "[ function compiled by full code generator"); |
134 | 134 |
135 #ifdef DEBUG | 135 #ifdef DEBUG |
136 if (strlen(FLAG_stop_at) > 0 && | 136 if (strlen(FLAG_stop_at) > 0 && |
137 info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { | 137 info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { |
138 __ stop("stop-at"); | 138 __ stop("stop-at"); |
139 } | 139 } |
140 #endif | 140 #endif |
141 | 141 |
| 142 // Strict mode functions need to replace the receiver with undefined |
| 143 // when called as functions (without an explicit receiver |
| 144 // object). r5 is zero for method calls and non-zero for function |
| 145 // calls. |
| 146 if (info->is_strict_mode()) { |
| 147 Label ok; |
| 148 __ cmp(r5, Operand(0)); |
| 149 __ b(eq, &ok); |
| 150 int receiver_offset = scope()->num_parameters() * kPointerSize; |
| 151 __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); |
| 152 __ str(r2, MemOperand(sp, receiver_offset)); |
| 153 __ bind(&ok); |
| 154 } |
| 155 |
142 int locals_count = scope()->num_stack_slots(); | 156 int locals_count = scope()->num_stack_slots(); |
143 | 157 |
144 __ Push(lr, fp, cp, r1); | 158 __ Push(lr, fp, cp, r1); |
145 if (locals_count > 0) { | 159 if (locals_count > 0) { |
146 // Load undefined value here, so the value is ready for the loop | 160 // Load undefined value here, so the value is ready for the loop |
147 // below. | 161 // below. |
148 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | 162 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
149 } | 163 } |
150 // Adjust fp to point to caller's fp. | 164 // Adjust fp to point to caller's fp. |
151 __ add(fp, sp, Operand(2 * kPointerSize)); | 165 __ add(fp, sp, Operand(2 * kPointerSize)); |
(...skipping 1934 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2086 for (int i = 0; i < arg_count; i++) { | 2100 for (int i = 0; i < arg_count; i++) { |
2087 VisitForStackValue(args->at(i)); | 2101 VisitForStackValue(args->at(i)); |
2088 } | 2102 } |
2089 __ mov(r2, Operand(name)); | 2103 __ mov(r2, Operand(name)); |
2090 } | 2104 } |
2091 // Record source position for debugger. | 2105 // Record source position for debugger. |
2092 SetSourcePosition(expr->position()); | 2106 SetSourcePosition(expr->position()); |
2093 // Call the IC initialization code. | 2107 // Call the IC initialization code. |
2094 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 2108 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
2095 Handle<Code> ic = | 2109 Handle<Code> ic = |
2096 isolate()->stub_cache()->ComputeCallInitialize(arg_count, in_loop); | 2110 isolate()->stub_cache()->ComputeCallInitialize(arg_count, in_loop, mode); |
2097 EmitCallIC(ic, mode, expr->id()); | 2111 EmitCallIC(ic, mode, expr->id()); |
2098 RecordJSReturnSite(expr); | 2112 RecordJSReturnSite(expr); |
2099 // Restore context register. | 2113 // Restore context register. |
2100 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2114 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
2101 context()->Plug(r0); | 2115 context()->Plug(r0); |
2102 } | 2116 } |
2103 | 2117 |
2104 | 2118 |
2105 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, | 2119 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, |
2106 Expression* key, | 2120 Expression* key) { |
2107 RelocInfo::Mode mode) { | |
2108 // Load the key. | 2121 // Load the key. |
2109 VisitForAccumulatorValue(key); | 2122 VisitForAccumulatorValue(key); |
2110 | 2123 |
2111 // Swap the name of the function and the receiver on the stack to follow | 2124 // Swap the name of the function and the receiver on the stack to follow |
2112 // the calling convention for call ICs. | 2125 // the calling convention for call ICs. |
2113 __ pop(r1); | 2126 __ pop(r1); |
2114 __ push(r0); | 2127 __ push(r0); |
2115 __ push(r1); | 2128 __ push(r1); |
2116 | 2129 |
2117 // Code common for calls using the IC. | 2130 // Code common for calls using the IC. |
2118 ZoneList<Expression*>* args = expr->arguments(); | 2131 ZoneList<Expression*>* args = expr->arguments(); |
2119 int arg_count = args->length(); | 2132 int arg_count = args->length(); |
2120 { PreservePositionScope scope(masm()->positions_recorder()); | 2133 { PreservePositionScope scope(masm()->positions_recorder()); |
2121 for (int i = 0; i < arg_count; i++) { | 2134 for (int i = 0; i < arg_count; i++) { |
2122 VisitForStackValue(args->at(i)); | 2135 VisitForStackValue(args->at(i)); |
2123 } | 2136 } |
2124 } | 2137 } |
2125 // Record source position for debugger. | 2138 // Record source position for debugger. |
2126 SetSourcePosition(expr->position()); | 2139 SetSourcePosition(expr->position()); |
2127 // Call the IC initialization code. | 2140 // Call the IC initialization code. |
2128 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 2141 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
2129 Handle<Code> ic = | 2142 Handle<Code> ic = |
2130 isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count, in_loop); | 2143 isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count, in_loop); |
2131 __ ldr(r2, MemOperand(sp, (arg_count + 1) * kPointerSize)); // Key. | 2144 __ ldr(r2, MemOperand(sp, (arg_count + 1) * kPointerSize)); // Key. |
2132 EmitCallIC(ic, mode, expr->id()); | 2145 EmitCallIC(ic, RelocInfo::CODE_TARGET, expr->id()); |
2133 RecordJSReturnSite(expr); | 2146 RecordJSReturnSite(expr); |
2134 // Restore context register. | 2147 // Restore context register. |
2135 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2148 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
2136 context()->DropAndPlug(1, r0); // Drop the key still on the stack. | 2149 context()->DropAndPlug(1, r0); // Drop the key still on the stack. |
2137 } | 2150 } |
2138 | 2151 |
2139 | 2152 |
2140 void FullCodeGenerator::EmitCallWithStub(Call* expr, CallFunctionFlags flags) { | 2153 void FullCodeGenerator::EmitCallWithStub(Call* expr, CallFunctionFlags flags) { |
2141 // Code common for calls using the call stub. | 2154 // Code common for calls using the call stub. |
2142 ZoneList<Expression*>* args = expr->arguments(); | 2155 ZoneList<Expression*>* args = expr->arguments(); |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2238 | 2251 |
2239 // The runtime call returns a pair of values in r0 (function) and | 2252 // The runtime call returns a pair of values in r0 (function) and |
2240 // r1 (receiver). Touch up the stack with the right values. | 2253 // r1 (receiver). Touch up the stack with the right values. |
2241 __ str(r0, MemOperand(sp, (arg_count + 1) * kPointerSize)); | 2254 __ str(r0, MemOperand(sp, (arg_count + 1) * kPointerSize)); |
2242 __ str(r1, MemOperand(sp, arg_count * kPointerSize)); | 2255 __ str(r1, MemOperand(sp, arg_count * kPointerSize)); |
2243 } | 2256 } |
2244 | 2257 |
2245 // Record source position for debugger. | 2258 // Record source position for debugger. |
2246 SetSourcePosition(expr->position()); | 2259 SetSourcePosition(expr->position()); |
2247 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 2260 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
2248 CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); | 2261 CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_IMPLICIT); |
2249 __ CallStub(&stub); | 2262 __ CallStub(&stub); |
2250 RecordJSReturnSite(expr); | 2263 RecordJSReturnSite(expr); |
2251 // Restore context register. | 2264 // Restore context register. |
2252 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2265 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
2253 context()->DropAndPlug(1, r0); | 2266 context()->DropAndPlug(1, r0); |
2254 } else if (var != NULL && !var->is_this() && var->is_global()) { | 2267 } else if (var != NULL && !var->is_this() && var->is_global()) { |
2255 // Push global object as receiver for the call IC. | 2268 // Push global object as receiver for the call IC. |
2256 __ ldr(r0, GlobalObjectOperand()); | 2269 __ ldr(r0, GlobalObjectOperand()); |
2257 __ push(r0); | 2270 __ push(r0); |
2258 EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT); | 2271 EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT); |
(...skipping 29 matching lines...) Expand all Loading... |
2288 __ bind(&done); | 2301 __ bind(&done); |
2289 // Push function. | 2302 // Push function. |
2290 __ push(r0); | 2303 __ push(r0); |
2291 // Push global receiver. | 2304 // Push global receiver. |
2292 __ ldr(r1, GlobalObjectOperand()); | 2305 __ ldr(r1, GlobalObjectOperand()); |
2293 __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); | 2306 __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); |
2294 __ push(r1); | 2307 __ push(r1); |
2295 __ bind(&call); | 2308 __ bind(&call); |
2296 } | 2309 } |
2297 | 2310 |
2298 // The receiver is either the global receiver or a JSObject found by | 2311 // The receiver is either the global receiver or an object found |
2299 // LoadContextSlot. | 2312 // by LoadContextSlot. That object could be the hole if the |
2300 EmitCallWithStub(expr, NO_CALL_FUNCTION_FLAGS); | 2313 // receiver is implicitly the global object. |
| 2314 EmitCallWithStub(expr, RECEIVER_MIGHT_BE_IMPLICIT); |
2301 } else if (fun->AsProperty() != NULL) { | 2315 } else if (fun->AsProperty() != NULL) { |
2302 // Call to an object property. | 2316 // Call to an object property. |
2303 Property* prop = fun->AsProperty(); | 2317 Property* prop = fun->AsProperty(); |
2304 Literal* key = prop->key()->AsLiteral(); | 2318 Literal* key = prop->key()->AsLiteral(); |
2305 if (key != NULL && key->handle()->IsSymbol()) { | 2319 if (key != NULL && key->handle()->IsSymbol()) { |
2306 // Call to a named property, use call IC. | 2320 // Call to a named property, use call IC. |
2307 { PreservePositionScope scope(masm()->positions_recorder()); | 2321 { PreservePositionScope scope(masm()->positions_recorder()); |
2308 VisitForStackValue(prop->obj()); | 2322 VisitForStackValue(prop->obj()); |
2309 } | 2323 } |
2310 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); | 2324 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); |
(...skipping 20 matching lines...) Expand all Loading... |
2331 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); | 2345 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); |
2332 EmitCallIC(ic, RelocInfo::CODE_TARGET, GetPropertyId(prop)); | 2346 EmitCallIC(ic, RelocInfo::CODE_TARGET, GetPropertyId(prop)); |
2333 __ ldr(r1, GlobalObjectOperand()); | 2347 __ ldr(r1, GlobalObjectOperand()); |
2334 __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); | 2348 __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); |
2335 __ Push(r0, r1); // Function, receiver. | 2349 __ Push(r0, r1); // Function, receiver. |
2336 EmitCallWithStub(expr, NO_CALL_FUNCTION_FLAGS); | 2350 EmitCallWithStub(expr, NO_CALL_FUNCTION_FLAGS); |
2337 } else { | 2351 } else { |
2338 { PreservePositionScope scope(masm()->positions_recorder()); | 2352 { PreservePositionScope scope(masm()->positions_recorder()); |
2339 VisitForStackValue(prop->obj()); | 2353 VisitForStackValue(prop->obj()); |
2340 } | 2354 } |
2341 EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET); | 2355 EmitKeyedCallWithIC(expr, prop->key()); |
2342 } | 2356 } |
2343 } | 2357 } |
2344 } else { | 2358 } else { |
2345 { PreservePositionScope scope(masm()->positions_recorder()); | 2359 { PreservePositionScope scope(masm()->positions_recorder()); |
2346 VisitForStackValue(fun); | 2360 VisitForStackValue(fun); |
2347 } | 2361 } |
2348 // Load global receiver object. | 2362 // Load global receiver object. |
2349 __ ldr(r1, GlobalObjectOperand()); | 2363 __ ldr(r1, GlobalObjectOperand()); |
2350 __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); | 2364 __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); |
2351 __ push(r1); | 2365 __ push(r1); |
(...skipping 1288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3640 | 3654 |
3641 // Push the arguments ("left-to-right"). | 3655 // Push the arguments ("left-to-right"). |
3642 int arg_count = args->length(); | 3656 int arg_count = args->length(); |
3643 for (int i = 0; i < arg_count; i++) { | 3657 for (int i = 0; i < arg_count; i++) { |
3644 VisitForStackValue(args->at(i)); | 3658 VisitForStackValue(args->at(i)); |
3645 } | 3659 } |
3646 | 3660 |
3647 if (expr->is_jsruntime()) { | 3661 if (expr->is_jsruntime()) { |
3648 // Call the JS runtime function. | 3662 // Call the JS runtime function. |
3649 __ mov(r2, Operand(expr->name())); | 3663 __ mov(r2, Operand(expr->name())); |
| 3664 RelocInfo::Mode mode = RelocInfo::CODE_TARGET; |
3650 Handle<Code> ic = | 3665 Handle<Code> ic = |
3651 isolate()->stub_cache()->ComputeCallInitialize(arg_count, NOT_IN_LOOP); | 3666 isolate()->stub_cache()->ComputeCallInitialize(arg_count, |
3652 EmitCallIC(ic, RelocInfo::CODE_TARGET, expr->id()); | 3667 NOT_IN_LOOP, |
| 3668 mode); |
| 3669 EmitCallIC(ic, mode, expr->id()); |
3653 // Restore context register. | 3670 // Restore context register. |
3654 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 3671 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
3655 } else { | 3672 } else { |
3656 // Call the C runtime function. | 3673 // Call the C runtime function. |
3657 __ CallRuntime(expr->function(), arg_count); | 3674 __ CallRuntime(expr->function(), arg_count); |
3658 } | 3675 } |
3659 context()->Plug(r0); | 3676 context()->Plug(r0); |
3660 } | 3677 } |
3661 | 3678 |
3662 | 3679 |
(...skipping 687 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4350 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. | 4367 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. |
4351 __ add(pc, r1, Operand(masm_->CodeObject())); | 4368 __ add(pc, r1, Operand(masm_->CodeObject())); |
4352 } | 4369 } |
4353 | 4370 |
4354 | 4371 |
4355 #undef __ | 4372 #undef __ |
4356 | 4373 |
4357 } } // namespace v8::internal | 4374 } } // namespace v8::internal |
4358 | 4375 |
4359 #endif // V8_TARGET_ARCH_ARM | 4376 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |